我正在尝试编写一个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中有其他目标用于不同目的。
答案 0 :(得分:3)
如果你不能使用
obj/%.o: src/app/%.cpp
然后第二种最简单的方法是在前面添加$(OBJ):
:
$(OBJ): obj/%.o: src/app/%.cpp
它被称为&#34;静态模式规则&#34; - 在GNU Make手册中查找。
答案 1 :(得分:0)
我找到了解决这个问题的方法(感谢Zereges的想法):
$(RGAOBJ): $(RGASRC)
$(CC) $(CFLAGS) -I/src/app/app.h -c \
$(addprefix src/app/,$(notdir $(@:.o=.cpp))) -o $@
我认为有更好的方法。
所以任何其他指针都会有所帮助。
答案 2 :(得分:0)
$<
变量获取第一个依赖项。它与具有可变目标并产生不同结果的通用目标一起使用。编译目标将模式匹配为目标并具有通用依赖关系。在你的情况下,第一个目标不会改变。
您无法使用通用规则的约束完全违背了$<
变量的目的。一个有点天真的解决方法是将目的地名称转换回源,例如,
$(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 $@