首页 > 解决方案 > 让运行cc,我不明白为什么

问题描述

我有以下 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)

标签: linuxmakefile

解决方案


一个简单的答案是make的行为。但它并没有让人理解它是如何工作的,所以让我们更深入地了解它。

我们从第一个 Makefile 开始。因为我的目录只有一个文件fizzbuzz.s,所以变量BIN是相等的fizzbuzzMake搜索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 的情况下也能正常工作。我想,这是因为%在内置规则之后具有最后的优先级执行。我们可以通过添加MAKEFLAGS += --no-builtin-rulesMakefile 来改变行为,一切正常。

但我注意到没有选项的一件奇怪的事情。我执行了命令make fizzbuzz.o并且它已经构建fizzbuzz.o(它处理来自我的 Makefile 的命令)。那么好吧。让我们再跑make一次。我运行它,它为我建立了最终fizzbuzz目标。惊喜!

所以规则

%: %.o
    $(LNK) -melf_i386 $< -o $@

当前目录中有目标文件(.o)时正在工作。我不知道它是什么,一个错误或一个功能(恕我直言,一个奇怪的功能),但它确实有效。

最后,我们有两个解决方案可以使第二个 Makefile 工作,它们如下:

  • .s通过替换扩展名.asm或任何其他没有内置规则的内容来省略内置规则make
  • 通过向 Makefile 添加一个选项或使用或MAKEFLAGS += --no-builtin-rules运行来禁用内置规则make -Rmake -r

推荐阅读