这是我当前的 makefile
.PHONY = all clean
all: foo
@echo "Dependencies: $<"
%: %.o
@echo "Checking.. $@, <- $<"
gcc -lm foo.o -o foo
@echo "\n"
%.o: %.c
@echo "Creating object.. $@, <- $<"
gcc -c foo.c
@echo "\n"
clean:
@echo "Cleaning up..."
rm -rvf foo.o foo
当我运行 make 时,它不会打印出任何回显的字符串,但我仍然得到可执行文件。这是打印到终端的所有内容
gcc foo.c -o foo
echo "Dependencies: foo"
当我用 %: foo.o
替换 %: %.0
规则时,所有内容都会正常打印到终端
Creating object.. foo.o, <- foo.c
gcc -c foo.c
Checking.. foo, <- foo.o
gcc -lm foo.o -o foo
Dependencies: foo
rm foo.o
在这两种情况下,我仍然得到可执行文件 foo
并且它正常工作,但为什么我在终端中得到 2 个不同的结果?
最佳答案
When I run make, it doesn't print out any echoed strings, but I still get the executable file.
由于您没有明确的构建规则 foo
,(GNU)make
执行implicit rule search ,通过它尝试找到一系列一个或多个模式规则,无论是用户提供的还是内置的,通过它可以构建 foo
。尽管它可以选择应用您的规则来构建 foo.o
来自foo.c
然后你的规则构建 foo
来自foo.o
,它有一个较短的链可用:构建 foo
的内置规则直接来自foo.c
。它选择后者,因为它更短。
When I replace
%: %.0
rule with%: foo.o
, everything is printed to the terminal normally
这是隐式规则搜索过程的一个怪癖。当您进行更改时,make
将修订后的规则标识为“适用于”建筑 foo
由于唯一的先决条件是具有明确的名称(这是手册中描述的算法中的第 5.3 项)。直接从%.c
构建的内置规则也适用,但 makefile 中给出的规则具有优先权(在相同长度的规则链中)。事实是make
必须单独弄清楚如何制作foo.o
在这种情况下不考虑(这是奇怪的部分,但从文档中可以清楚地看出)。
当然,这种特殊的怪癖很少会被触发,因为修订后的规则几乎总是不合适的。它说无论要构建什么目标,都可以从 foo.o
构建它。 ,通过提供的配方,但该配方确实仅适用于构建 foo
。而不是%: foo.o
,那么,你真的应该做到 foo: foo.o
:
.PHONY = all clean
all: foo
@echo "Dependencies: $<"
foo: foo.o
@echo "Checking.. $@, <- $<"
gcc -o $@ $< -lm
@echo "\n"
%.o: %.c
@echo "Creating object.. $@, <- $<"
gcc -c foo.c
@echo "\n"
clean:
@echo "Cleaning up..."
rm -rvf foo.o foo
附加说明:
- 链接库选项,例如
-lm
应该出现在链接线的末尾。这些文件和目标文件在命令行上的相对顺序很重要。 - 避免重复自己的话。规则的配方应该使用 automatic variables尽可能避免重复目标或先决条件名称。
关于makefile - 为什么 echo 在 % : foo. o 规则中起作用,但在 % : %. o 中不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57233519/