linux - 让运行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)
解决方案
一个简单的答案是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 的情况下也能正常工作。我想,这是因为%
在内置规则之后具有最后的优先级执行。我们可以通过添加MAKEFLAGS += --no-builtin-rules
Makefile 来改变行为,一切正常。
但我注意到没有选项的一件奇怪的事情。我执行了命令make fizzbuzz.o
并且它已经构建fizzbuzz.o
(它处理来自我的 Makefile 的命令)。那么好吧。让我们再跑make
一次。我运行它,它为我建立了最终fizzbuzz
目标。惊喜!
所以规则
%: %.o
$(LNK) -melf_i386 $< -o $@
当前目录中有目标文件(.o)时正在工作。我不知道它是什么,一个错误或一个功能(恕我直言,一个奇怪的功能),但它确实有效。
最后,我们有两个解决方案可以使第二个 Makefile 工作,它们如下:
.s
通过替换扩展名.asm
或任何其他没有内置规则的内容来省略内置规则make
- 通过向 Makefile 添加一个选项或使用或
MAKEFLAGS += --no-builtin-rules
运行来禁用内置规则make -R
make -r
推荐阅读
- c# - 基于 Vector3 moveDirection 旋转字符
- c++ - 无法获取到小部件组件 UE4 的链接
- mysql - innodb_sys_tables 中的 MYSQL 表分区阻止 aws 升级
- javascript - 节点服务器端口在开发过程中不断“插入”
- apache-spark - 通过将其转换为列表来根据另一个数据框列过滤火花数据框
- python - 如何让我的网站在每次有人访问或每隔几分钟重新运行一些 python 烧瓶代码?
- reactjs - http fetch 返回 true 而不是实际数据
- python - 不能同时在scrapy中运行多个蜘蛛
- python - 如何使用 python 保存 to_csv
- c# - ASP.NET Core Web App appsettings.json 值被 docker 容器中的随机字符串替换