我知道我做错了,但我无法弄清楚如何组织这个makefile.我定义了我的util源文件,并使用一些函数来定义它们的.o文件:
UTIL_SRC = utils/src/foo.cpp utils/src/bar.cpp utils/src/baz.cpp
UTIL_OBJS = $(patsubst utils/src/%.cpp,utils/obj/%.o,$(UTIL_SRC))
Run Code Online (Sandbox Code Playgroud)
这是我使用这些文件的目标:
lib : lib/libutils.a
lib/libutils.a : $(UTIL_OBJS)
rm -f lib/libutils.a
ar -c -q lib/libutils.a $(UTIL_OBJS)
Run Code Online (Sandbox Code Playgroud)
然后,当我得到编译这些婴儿的规则时,我希望只有一个命令可以遍历每个UTIL_OBJS文件和每个UTIL_SRC文件.相反,我采用了这种怪物,这使得将它们存储在变量中的目的就失败了.
$(UTIL_OBJS) : $(UTIL_SRC)
g++ $(UTIL_FLAGS) utils/src/foo.cpp -o utils/obj/foo.o
g++ $(UTIL_FLAGS) utils/src/bar.cpp -o utils/obj/bar.o
g++ $(UTIL_FLAGS) utils/src/baz.cpp -o utils/obj/baz.o
Run Code Online (Sandbox Code Playgroud)
我可以将它浓缩为一行吗?怎么样?谢谢,很棒!
使用隐式规则通常更容易.有很多预定义的,你只需要指定变量.
CXX=g++
CXXFLAGS=$(UTIL_FLAGS)
Run Code Online (Sandbox Code Playgroud)
然后你需要定义一个可执行文件,就像这样
myutil: $(UTIL_OBJS)
Run Code Online (Sandbox Code Playgroud)
由于您没有将对象存储在同一目录中,因此您也需要指定一个新的隐式规则(否则,我们现在就完成了).
utils/obj/%.o: utils/obj/%.cpp
Run Code Online (Sandbox Code Playgroud)
%是模式匹配,它将匹配左侧和右侧的相同文本,因此此规则将使foo.o脱离foo.cpp.尝试在没有命令的情况下工作(它可能从另一个规则中抓取了它,我不确定),否则让它说:
utils/obj/%.o: utils/obj/%.cpp
$(CXX) $(CXXFLAGS) -o $@ $^
Run Code Online (Sandbox Code Playgroud)
$ @是规则的目标(例如foo.o),$ ^是右侧的所有文件.我正在写这篇文章,没有测试它的可能性,所以请让我知道它是如何结果.. :)
为了使它更加优雅,您可以包含一个依赖项文件
include .depend
Run Code Online (Sandbox Code Playgroud)
如果你正在运行GNU make,它会尝试制作.depend文件,如果它找不到它(使用旧学校制作,你需要先自己创建它,它可能只是一个假人,如果你' d喜欢通过makefile来管理它
.depend: $(UTIL_SRC)
$(CXX) -MM -o $@ $^
Run Code Online (Sandbox Code Playgroud)
依赖项文件将包含每个.cpp文件的行,告诉make它需要哪些头文件,这将允许make在您更改某些内容时重新编译必要的文件.这对你原来的问题没有帮助,只是觉得它可能会派上用场.
编辑:
作为对您的编辑的回应.您也可以删除用于创建.a文件的命令,它也已作为隐式规则提供.虽然不确定它是如何工作的,但还没有使用它.我知道在制作处理.a(rchive?)文件时有很多怪癖.