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