我有以下Makefile:
SRC = $(wildcard *.s)
BIN = $(SRC:.s=)
all: $(BIN)
echo 4
当前目录中有一个汇编程序文件(fizzbuzz.s)。当我执行make
命令时,它会运行
cc fizzbuzz.s -o fizzbuzz
我不明白为什么会这样?怎么了?
更新:
当我使用另一个Makefile时,也会发生同样的情况:
.PHONY: clean all
AS = nasm
LNK = ld
SRC = $(wildcard *.s)
BIN := $(SRC:.s=)
all: $(BIN)
%: %.o
$(LNK) -melf_i386 $< -o $@
%.o: %.s
$(AS) -f elf $< -o $@
clean:
rm -f $(BIN)
答案 0 :(得分:2)
一个简单的答案是make
的行为。但这并不能理解其工作原理,因此让我们更深入。
我们从第一个Makefile开始。由于我的目录只有一个文件fizzbuzz.s
,因此变量BIN
将等于fizzbuzz
。 Make
搜索fizzbuzz
目标,但没有目标。因此,make
处理内置规则。它搜索带有扩展名添加到fizzbuzz
目标的文件,如果已搜索文件,它将处理自己的规则。我试图删除Makefile并运行命令:make fizzbuzz
,它运行另一个
cc fizzbuzz.s -o fizzbuzz
。
它等于第一个Makefile。
现在,我们将使用第二个Makefile。
当我在.s
上更改了.asm
扩展名时,它起作用了。有趣的行为是因为make
没有内置.asm
扩展规则。我想了解一下,所以我将.asm
返回到.s
。
我的第二个Makefile有一个没有扩展名的目标规则:
%: %.o
$(LNK) -melf_i386 $< -o $@
但是它不能按预期工作,并且像没有Makefile一样工作。我想这是因为%
具有内置规则之后的最后优先级执行。我们可以通过在Makefile中添加MAKEFLAGS += --no-builtin-rules
来更改行为,一切正常。
但是我注意到没有选择的一件奇怪的事情。我执行了命令make fizzbuzz.o
,它已经建立fizzbuzz.o
(它处理我的Makefile中的命令)。那么好吧。让我们再次运行make
。运行它,它为我建立了最终的fizzbuzz
目标。惊喜!
所以规则
%: %.o
$(LNK) -melf_i386 $< -o $@
当前目录中有目标文件(.o)时,工作。我不知道它是什么,一个错误或一个功能(恕我直言,这是一个奇怪的功能),但它确实可以正常工作。
最后,我们有两种解决方案可以使第二个Makefile工作,它们是:
.s
扩展名替换为.asm
或make
中没有内置规则的其他扩展名,来省略内置规则MAKEFLAGS += --no-builtin-rules
或使用make -R
或make -r
来运行内置规则