假设您有一个带有两个伪目标的Makefile,'all'和'debug'。 'debug'目标用于构建与'all'相同的项目,除了一些不同的编译开关(例如-ggdb)。由于目标使用不同的编译开关,如果在两者之间切换,显然需要重建整个项目。但GNUmake自然不会认识到这一点。
因此,如果您输入make all
,您将获得
Building ...
...
然后,如果您输入make debug
,则会获得
make: Nothing to be done for `debug'.
所以我的问题是:你如何在Makefile中实现一个干净的解决方案,注意到最后一个构建使用了与你当前想要的不同的伪目标或不同的编译开关?如果它们不同,Makefile将重建所有内容。
答案 0 :(得分:2)
将构建产品放入不同的目录树中(同时保留源代码的一个副本)。这样,您始终只是从最新版本进行简短编译,无论是调试还是发布(甚至是其他版本)。也没有混淆的可能性。
修改强>
上述草图。
src := 1.c 2.c 3.c
bare-objs := ${src:%.c=%.o}
release-objs := ${bare-objs:%=Release/%}
debug-objs := ${bare-objs:%=Debug/%}
Release/prog: ${release-objs}
Debug/prog: ${debug-objs}
${release-objs}: Release/%.o: %.c # You gotta lurve static pattern rules
gcc -c $< -o $@
${debug-objs}: Debug/%.o: %.c
gcc -c $< -o $@
Release/prog Debug/prog:
gcc $^ -o $@
.PHONY: all
all: Release/prog ; echo $@ Success
.PHONY: debug
debug: Debug/prog ; echo $@ Success
(免责声明:未经过测试,甚至未经过制作。)
你去吧。它甚至可以-j
安全,因此您可以执行make -j5 all debug
。有很多明显的锅炉板只是为了整理而哭泣。
答案 1 :(得分:1)
保持对象文件的变体集(如在bobbogo的解决方案中)可能是最好的方法,但如果由于某种原因你不想这样做,你可以使用空文件作为标记,以指示你上次构建的方式可执行文件:
%-marker:
@rm -f $(OBJECTS) *-marker
@touch $@
debug: GCCFLAGS += -ggdb
debug: SOMEOTHERFLAG = WHATEVER
all debug: % : %-marker
@echo making $@
@$(MAKE) -S GCCFLAGS='$(GCCFLAGS)' SOMEOTHERFLAG='$(SOMEOTHERFLAG)' main
这个想法还有其他变种;你可以有一个包含标志设置的小文件,makefile将构建它,include
。那将是聪明的,但并不比这更清洁。
答案 2 :(得分:0)
唯一干净的解决方案是将差异纳入目标名称。
例如。您可以定义变量$(DEBUG)
并在依赖于编译步骤的所有目标中始终使用它。