生成文件中的变量依赖目标



我有一个用于测试的小项目,我想将解决方案的不同实现链接到测试。

所以,我创建了看起来像这样的生成文件

CC=g++
FLAGS=-Wall -O2
CFLAGS=-c $(FLAGS)
I_PATH=implementation1.cpp
all: instance
instance: instance.cpp .implementation.o
$(CC) $(FLAGS) instance.cpp .implementation.o -o $@
.implementation.o: $(I_PATH)
$(CC) $(CFLAGS) $(I_PATH) -o $@
clean:
-rm .implementation*
-rm instance

在这里,I_PATH是解决方案实现的途径。我想测试通过命令行参数传递不同实现的不同解决方案:make I_PATH=implementation2.cpp.

但是,由于我所有的实现都编译到同一个对象文件.implementation.omake无法理解某些东西发生了变化并且不会重建项目。

当然,我可以在运行之前调用make cleanmake以实现特定实现。但是这增加了构建时间(我可以多次运行一个实现的测试)并且不是很舒服。

我可以将此生成文件修复为如下所示的内容:

CC=g++
FLAGS=-Wall -O2
CFLAGS=-c $(FLAGS)
I_PATH=implementation1.cpp
C_PATH := $(shell echo -n $(I_PATH) | md5sum | awk '{print ".implementation_" substr($$1, 0, 10) ".o";}')
all: force instance
force_relink: 
touch -c $(C_PATH)
instance: instance.cpp $(C_PATH)
$(CC) $(FLAGS) instance.cpp $(C_PATH) -o $@
$(C_PATH): $(I_PATH)
$(CC) $(CFLAGS) $< -o $@
clean:
-rm .implementation*
-rm instance

在这里,我创建了I_PATH依赖对象文件(采用实现路径的哈希),此外,每次运行时make都强制将instance.cpp与对象文件重新链接。

但也许make有一些机制可以解决这种行为?或者我可以用不同的方法实现相同的目标?

为每个已编译的.o文件指定一个不同的名称,并简单地链接到您想要的已编译.o文件不是更有意义吗?

instance: instance.cpp $(IMPL_O)
$(CC) $(FLAGS) $^ -o $@  # propably no need to override default rule

使用make IMPL_O=implementation2.o生成问题中的示例。

这样,每个文件的名称可以真正显示其身份,并且您不必显式跟踪任何内容。

(显然,您可以将.o扩展重构为 Makefile 本身,这样您就可以说IMPL=implementation2或其他什么。

最新更新