makefile - 为什么 Make 更喜欢隐式规则而不是 Makefile 中列出的规则?
问题描述
我试图弄清楚为什么 Make 使用某个规则来编译我的代码。这是一个最小的例子:
生成文件
CC := gcc CFLAGS := -O2 -Wno-implicit-function-declaration targets := main1 main2 obj_targets := $(patsubst %,%.o,$(targets)) src_lib := add.c obj_lib := $(patsubst %.c,%.o,$(src_lib)) all: $(targets) %: %.o $(obj_lib) $(CC) $(CFLAGS) -static -o $@ $^ .PHONY: all
添加.c:
int add(int a, int b) { return a + b; }
main1.c:
int main(void) { return add(1,2); }
main2.c:
int main(void) { return add(3,4); }
运行时make
我得到以下信息:
$ make
gcc -O2 -Wno-implicit-function-declaration main1.c -o main1
/usr/bin/ld: /tmp/ccBsxlMV.o: in function `main':
main1.c:(.text.startup+0x11): undefined reference to `add'
collect2: error: ld returned 1 exit status
make: *** [<builtin>: main1] Error 1
我的意图是通过%: %.o $(obj_lib)
表明每个目标都依赖于所有目标文件,以便目标.o
文件将与add.o
. 但是,我观察到的是 Make 正在使用隐式规则将.c
文件编译为可执行文件,由于add.o
没有被链接,因此失败。
为什么 Make 使用隐式规则而不是我定义的规则?如何使用我在那里指定的命令让 Make 编译我的目标?
解决方案
原因是 make 总是使用最短的隐式规则链。所以,如果 make 可以找到一个规则%.x -> %.y
和另一个规则%.x -> %.z -> %.y
,它总是会选择第一个。
Make 不会区别对待内置规则和用户定义规则,只是先搜索用户定义规则,然后再搜索内置规则。
在您的情况下,您有一个知道如何从具有相同名称的源文件创建二进制文件的内置规则,以及您定义的知道如何从目标文件创建二进制文件的规则和另一个构建来自源文件的目标文件。所以make选择了第一个。
您可以使用以下方法删除该内置规则:
%: %.c
正如你所做的(你不必删除%.o : %.c
规则)。或者,您可以使用创建显式规则的静态模式规则:
all: $(targets)
$(targets): %: %.o $(obj_lib)
...
因为这是一种显式规则,所以不会使用隐式规则(如模式规则)。
推荐阅读
- python - 如何在 jupyter 实验室笔记本中显示 gmplot HTML?
- java - 设置 applicationName 配置
- android - 适配不同的机器人显示
- laravel - 跟随 Laravel 安装时 Laravel Docker Swoole 错误
- c++ - 使用 CopyFile 函数复制目录及其所有子目录
- xcode - Xcode“跳转到下一个问题”仅用于错误?
- javascript - 有没有办法在没有 API 的情况下使用 JS 来操作嵌入式视频?
- audio - 将音频作为流 0 并将视频作为流 1 可以解释为什么我的 MPG 将在 OSX QuickTime Player 上播放,而不是 Win10 影视?
- ruby - Ruby:nil:NilClass(NoMethodError)的未定义方法'>'
- c++ - 从地图中检索值 <