请考虑以下目录树,以了解要解决的问题的虚构玩具示例:
- Makefile
- lib.c
+ foo/
|-- config.mk
+ bar/
|-- config.mk
foo/config.mk
的内容:
CFLAGS += -DFOO
bar/config.mk
的内容:
CFLAGS += -DBAR
- 为
make
调用make
作为目标foo
和bar
导致文件foo/config.mk
和bar/config.mk
分别被包含(通过include directive),并且正在构建lib.o
,即:
# build lib.o with the macro FOO defined
$ make foo
# build lib.o with the macro BAR defined
$ make bar
# build lib.o with both the macros FOO and BAR defined
$ make foo bar
$ make bar foo
构建 lib.o
的默认规则使用变量 COMPILE.c
,该变量是根据通过使用选项--print-data-base调用 make
获得的输出定义的:
COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
除其他事项外, COMPILE.c
的扩展取决于变量 CFLAGS 的值,而变量 CFLAGS 依赖于是否包含 foo/config.mk
或 bar/config.mk
,因为这些makefile修改了 CFLAGS
变量 .
我想要实现的是,如果当前使用的变量 COMPILE.c
的扩展与用于上一次构建的 lib.o
的扩展不同,则将目标 lib.o
视为过时目标 . 例如:
$ make foo
# It shouldn't rebuild anything since lib.o should be up-to-date
$ make foo
# It should rebuild lib.o since it should be out-of-date
$ make bar
# It should rebuild lib.o since it is again out-of-date
$ make foo bar
# It shouldn't rebuild lib.o since it is up-to-date
$ make bar foo
This solution解释了到目前为止我是如何实现这种行为的 . 任何建议都受到欢迎 .
3 回答
我会将变量的值转储到另一个包含的makefile中,并检查当前值是否与包含的makefile中的值不同 . 就像是:
演示:
到目前为止,我的方法是生成一个文件
cc-options-dump
,每次构建lib.o
时都会使用COMPILE.c
变量的扩展内容 .将当前
COMPILE.c
变量的扩展产生的MD5哈希与用于先前构建的MD5哈希进行比较,即,其内容存储在文件cc-options-dump
中的那个(如果有的话)(即,如果文件确实存在的话) .对于目标
foo
和/或bar
调用make
时,此makefile的行为对应于所需的对应:使用sort内置函数对于上述最后两种情况正常工作至关重要 .
如果有人能够提供更优雅的解决方案,那就太棒了 .
这是我的粗略模型,它直接在文件名中编码编译器/链接器标志 . 这只是一个想法,实际的实现应该更加健壮 .
使用hello world test.c文件和这些命令进行测试: