Makefile一次又一次地为不同的对象选择相同的源文件

makefile picks the same source file again and again for different objects

本文关键字:选择 源文件 对象 一次又一次 Makefile      更新时间:2023-10-16

我想写一个makefile,假设我在目录src/app/中有4个源文件:

src/app/file1.cpp
src/app/file2.cpp
src/app/file3.cpp
src/app/file4.cpp

和我想创建不同的目标文件(即file1.o, file2.o等)到另一个名为obj/的目录。在makefile中,我像这样定义变量:

$(SRC) := $(wildcard src/app/*.cpp)
$(OBJ) := $(addprefix obj/,$(notdir $(SRC:.cpp=.o)))

和我的命令是这样的:

all: $(OBJ)
$(OBJ): $(SRC)
    $(CC) $(CFLAGS) -I/src/app/app.h -c $< -o $@

所以当我运行make时,我看到这些操作:

g++ -g -Wall -I/src/app/app.h -c src/app/file1.cpp -o obj/file1.o
g++ -g -Wall -I/src/app/app.h -c src/app/file1.cpp -o obj/file2.o
g++ -g -Wall -I/src/app/app.h -c src/app/file1.cpp -o obj/file3.o
g++ -g -Wall -I/src/app/app.h -c src/app/file1.cpp -o obj/file4.o

您可以看到,目标文件有不同的名称,但源文件是相同的。如何解决?

请注意,我不能使用%.o: %.cpp,因为我在我的makefile中有其他目标用于不同的目的。

如果你不能使用

obj/%.o: src/app/%.cpp

那么第二种最简单的方法是在前面添加$(OBJ)::

$(OBJ): obj/%.o: src/app/%.cpp

它被称为"静态模式规则"-在GNU Make手册中查找它。

我已经找到了解决这个问题的方法(感谢Zereges的想法):

$(RGAOBJ): $(RGASRC)
    $(CC) $(CFLAGS) -I/src/app/app.h -c 
        $(addprefix src/app/,$(notdir $(@:.o=.cpp))) -o $@

我认为有更好的方法。

所以其他的指针都是有用的

$<变量选择第一个依赖项。它用于具有可变靶标的通用靶标,并产生不同的结果。编译目标将匹配模式作为目标,并具有通用依赖项。在您的例子中,第一个目标不会改变。

不能使用通用规则的约束完全违背了$<变量的目的。一种比较天真的解决方法是将目标名称转换回源名称,例如

$(OBJ): $(SRC)
    $(CC) $(CFLAGS) -I/src/app/app.h -c $(@:%.o=%.cpp) -o $@ 

这种方法的问题是并不是所有的目标文件都依赖于所有的源文件。因此,每当一个源文件被更改时,就会生成所有的目标文件。对于可能可行的小项目和资源。对于任何我认为是实的投影,这两个条件都不成立。

我对你说不能使用模式规则的理解是,你已经有了相同模式的规则,但你需要用一些特殊的规则来建立一些目标。针对这种情况的一种解决方案是使用自定义后缀构建目标,该后缀实际上构建的是不同的东西,并且只是使用标记文件来防止不必要的重建。例如:

all: $(OBJ:%=%.custom)
%.o.custom: %.cpp
    $(CC) $(CFLAGS) -W -I/src/app/app.h -c $< -o $(@:%.custom=%) && touch $@