gnu-make - Makefiles:它们如何确定构建目标?
问题描述
我在尝试为当前项目扩展的继承生成文件中遇到了有趣的行为。
LIBS := lib/precompiled1.a lib/precompiled2.a lib/mylib1.a lib/mylib2.a
mylib1-src := (source directory)
mylib1-obj := $(patsubst $(mylib1-src)/%.c, obj/LIB1/%.o, $(wildcard $(mylib1-src)/*.c))
mylib2-src := (source directory)
mylib2-obj := $(patsubst $(mylib2-src)/%.cpp, obj/LIB2/%.o, $(wildcard $(mylib2-src)/*.cpp))
default: all
lib/mylib1.a: $(mylib1-obj)
ar -r $@ $^
lib/mylib2.a: $(mylib2-obj)
ar -r $@ $^
all: exe/my_out
exe/my_out: $(my_out-obj)
g++ $^ $(COMMON_FLAGS) $(LIBS) $(MY_FLAGS)
当我运行 make 时,我遇到了一个错误,它无法链接到 lib/mylib1.a,并且它中断了。很酷,我只需要确保正在构建 .a 目标。像这样天真地使用makefile:
lib/mylib1.a: $(mylib1-obj)
ar -r $@ $^
lib/mylib2.a: $(mylib2-obj)
ar -r $@ $^
default: all
这现在编译 mylib1.a 就好了,但既不编译 mylib2.a 也不编译'all'。
这就是我卡住的地方。如果我执行以下操作:
default: all
lib/mylib1.a: $(mylib1-obj)
ar -r $@ $^
lib/mylib2.a: $(mylib2-obj)
ar -r $@ $^
all: lib/mylib1.a exe/my_out
然后编译器抱怨 lib/mylib1.a 不是可执行文件。它不是,很好,但让我陷入了一个奇怪的境地。我可以单独编译 .a 文件。我可以将它们链接到可执行文件。我不能一次做所有这些事情,只能通过弄乱makefile,这在某种程度上违背了这一点。
我的问题是,为什么更改默认顺序会改变构建的内容?如何让所有 .a 文件构建并链接到主可执行文件,而无需每次都手动弄乱makefile?一般来说,我对 makefile 相当陌生,我不确定为什么会发生这种行为。
谢谢!
解决方案
makefile 中目标的顺序无关紧要,但有一个例外:第一个是默认目标,即在没有目标的情况下调用make
的目标。可以在 GNU make 中更改此行为.DEFAULT_GOAL := ...
依赖顺序
串行构建 ( make -j1
) 中重要的是目标定义中的依赖顺序,例如
T: A B C
或者
T: A B
T: C
rule
在串行构建make
中,将首先实现“A”,然后是“B”,然后是“C”。如果“C”在构建“A”时缺少满足的依赖项,则构建将成功。将生成文件更改为
T: C A B
...并且串行构建将开始失败。
在并行构建 ( make -jN
) 中,依赖顺序无关紧要,因为make
如果允许,将尝试并行构建“A”、“B”和“C”。
不完全依赖
如果没有为目标“T”列出强制依赖项“D”,则make
一旦满足列出的依赖项,将允许构建目标“T”。但它不会等待“D”完成。因此,构建成功取决于未定义的行为,要么
- “D”在构建开始之前已经存在并且当前构建没有触及,或者
- 目标“D”在目标“T”开始之前完成。
并行构建的最坏情况:如果“T”的规则在同时读取“D”和“D”时没有失败,那么最终构建成功,但构建工件无效。
不完全依赖的常用指标是
- 从串行切换到并行时,构建开始(随机)失败,
- 移动到另一台构建机器时构建开始随机失败,或者
- 从具有奇怪测试失败的成功构建中构建工件。
解决方案
始终为所有目标指定完整的依赖关系。在您的情况下,这至少是:
# Add internal dependencies included in $(LIBS)
exe/my_out: $(my_out-obj) $(filter lib/%.a, $(LIBS))
g++ $^ $(COMMON_FLAGS) $(LIBS) $(MY_FLAGS)
推荐阅读
- oracle - 在没有 DENSE_RANK 的情况下重写查询
- java - 使用 Java 中的销售值更新库存系统文件
- sql - 从sql中的join复制行
- spring-security - 显示此 div 的正确 thymeleaf 语法是什么?
- oracle - 与 Pentaho PDI 连接时出现 ORA-01017
- react-native - 如何在 ClusteredMapView 中呈现我的标记?
- javascript - 移除 JavaScript 类中的嵌套事件监听器
- php - jQuery / AJAX 发送更改的 div 的内容
- c - 在 Solaris 5.10 上使用 flock()
- c# - 刷新 x:静态属性绑定