如何正确编写由make本身生成的头文件的gmake规则?
假设我可以传递do make BUILDTYPE=1
和buildtype.h将被创建并填充
#define BUILDTYPE 1
Makefile只会做这样的事情:
buildtype.h:
echo #define BUILDTYPE 1 > TMPFILE
//pseudo code:
if(TMPFILE != buildtype.h)
cat TMPFILE > buildtype.h
我需要确保每个cpp文件不会重复此过程1000次,我想确保此过程至少完成一次
我想要确保的是,此规则始终只运行一次。也就是说,即使存在buidtype.h,它仍然必须运行。我有自动依赖关系跟踪,它应该只在make运行时触发一次这个规则。
也就是说,如果我运行make BUILDTYPE = 2并且无需执行任何操作,它仍然必须为buildtype.h运行该规则,并且如果buildtype.h将按规则更新,则应重新编译所有文件。
gmake有可能吗?
答案 0 :(得分:1)
我需要确保每个cpp文件不会重复此过程1000次
您不需要做任何特别的事情来确保这一点。 Make将跟踪它已更新的目标。它不会多次重新运行规则,因为多个其他目标依赖于其输出。
我希望确保此过程至少完成一次
这样做的规范方法是:
.PHONY: force
buildtype.h: force
您没有要求它,而是一种实施
的简单方法//pseudo code: if(TMPFILE != buildtype.h) cat TMPFILE > buildtype.h
是
cmp -s TMPFILE buildtype.h || cp TMPFILE buildtype.h
更新:相关的“有趣问题”是如何在任何编译尝试使用它之前确保buildtype.h
是最新的。对于“干净”构建,自动依赖关系跟踪系统可能会失败,因为它们的输出仅基于它们可以在磁盘上看到的头文件;如果尚未创建buildtype.h
,makedepend
或gcc -M
无法知道,则无法生成正确的依赖关系。
一个解决方案是将正确的依赖项手动编码到makefile中,如
foo.o: buildtype.h # because foo.c includes buildtype.h
一个更简单但更糟糕的选择是编写
Makefile: buildtype.h
确保make
在任何其他内容之前更新buildtype.h
(请参阅the manual)。所以现在buildtype.h
永远不会丢失或过时。
该方法的一个缺点是,即使输入make clean
之类的内容也会导致更新buildtype.h
,即使在这种情况下根本不需要它。对于特定情况,这可以通过像
ifneq (clean,$(MAKECMDGOALS))
Makefile: buildtype.h
endif
答案 1 :(得分:0)
以下是使用sed的一种方法:
deps =
ifdef BUILDTYPE
old = $(shell sed -n 's/\#define *BUILDTYPE *\([0-9]*\)/\1/p' buildtype.h)
ifneq ($(BUILDTYPE),$(old))
deps := buildtype.h
endif
endif
all: $(deps)
@echo $(deps)