2

如何为 make 本身生成的头文件正确编写 gmake 规则?

假设我可以通过 domake 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可以做到这样的事情吗?

4

2 回答 2

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.hbuildtype.h

该方法的一个缺点是即使键入类似的make clean内容也会导致buildtype.h更新,即使在这种情况下根本不需要它。对于特定情况,可以通过非常丑陋的黑客来缓解这种情况

ifneq (clean,$(MAKECMDGOALS))
Makefile: buildtype.h
endif
于 2012-12-21T15:09:38.840 回答
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)
于 2012-12-20T01:49:41.853 回答