makefile - 为什么在给定绝对路径与 -C 选项的本地路径时,make 的行为会有所不同?
问题描述
我正在编写一个 make 文件来编译源代码树中的代码。在我的制作文件中,我有以下内容:
MK = make
CC = g++
PWD = $(shell pwd)
CFLAGS = -std=c++11 -g -Wall
SRCDIR = $(PWD)/src
TSTDIR = $(PWD)/tests
export MK CC SRCDIR TSTDIR CFLAGS
tests:
$(MK) -C $(TSTDIR)
然后在TSTDIR
's 目录中是另一个 makefile:
OBJS = $(notdir $(shell find $(SRCDIR) | grep .o))
IFLAGS = -I$(SRCDIR)
all: ts_tst
%: %.cc $(OBJS)
$(CC) $(CFLAGS) $(IFLAGS) $(LFLAGS) -o $@ $^
我从运行中得到的输出是:
make -C <pwd>/tests
make[1]: Entering directory `<pwd>/tests'
g++ ts_tst.cc -o ts_tst
ts_tst.cc:8:31: fatal error: packets/ts_packet.h: No such file or directory
#include "packets/ts_packet.h"
^
compilation terminated.
make[1]: *** [ts_tst] Error 1
make[1]: Leaving directory `<pwd>/tests'
make: *** [tests] Error 2
请注意,g++ 命令与我在 make 文件中的模板不匹配。现在,如果我$(PWD)/
从变量中删除SRCDIR
并TSTDIR
得到这个...
make -C tests
find: ‘src’: No such file or directory
make[1]: Entering directory `<pwd>/tests'
g++ -std=c++11 -g -Wall -Isrc -o ts_tst ts_tst.cc
ts_tst.cc:8:31: fatal error: packets/ts_packet.h: No such file or directory
#include "packets/ts_packet.h"
^
compilation terminated.
make[1]: *** [ts_tst] Error 1
make[1]: Leaving directory `<pwd>/tests'
make: *** [tests] Error 2
如您所见,搜索源目录显然失败了,因为路径现在是本地的,因此它不存在,但是 g++ 命令现在与我的模板匹配......有谁知道为什么会发生这种情况以及我该如何解决?
解决方案
考虑一下:
OBJS = $(notdir $(shell find $(SRCDIR) | grep .o))
%: %.cc $(OBJS)
$(CC) $(CFLAGS) $(IFLAGS) $(LFLAGS) -o $@ $^
当SRCDIR
设置它可能会找到一些目标文件(顺便说一下,我不知道你为什么在grep
这里使用而不是仅仅添加-name \*.o
到find
命令:这grep
是错误的,因为它也会匹配文件foo.ohno
)。
假设它找到了目标文件/my/path/to/src/foo.o
。在其notdir
上运行并OBJS
设置为foo.o
.
这意味着模式变为:
%: %.cc foo.o
$(CC) $(CFLAGS) $(IFLAGS) $(LFLAGS) -o $@ $^
现在 make 想要搜索匹配的模式规则。它不会匹配此规则,因为虽然模式%
和%.cc
匹配,但其他先决条件foo.o
不存在(它不在本地目录中)。结果这个模式被忽略了,make 会继续寻找另一个模式。它将找到匹配的内置模式,这就是您获得输出的原因。
在没有找到目标文件的情况下(错误find
的命令),OBJS
变量为空,因此模式规则匹配。
如果你删除notdir
它应该可以工作,但我不知道你为什么添加它,所以可能是其他问题。
其他注意事项:
- 在调用递归 make 时,您应该始终使用
$(MAKE)
or显式使用,而从不使用或其他一些变量。${MAKE}
make
- 一般来说,您应该
:=
在调用shell
或其他较慢的功能时使用。 - 如果您使用显式规则而不是模式规则来构建测试程序,则可能更容易理解正在发生的事情:然后您会收到一个错误,例如no rule to build foo.o
推荐阅读
- wordpress - 如何使 wordpress 主题与 Elementor 兼容?
- angular - 我想使用 filter() 运算符来删除一个元素,但是在将更改后的列表作为新列表传递时遇到了麻烦?
- flutter - 未处理的异常:NoSuchMethodError:类'_InternalLinkedHashMap
Flutter Map 未加载 Firestore 标记 - java - 使用本地字段时的 Java JIT 优化
- python - 如何优化多维numpy数组计算?
- r - 创建一个函数以使用 R 获取双向表
- c++ - 是否存在与 c++ 中文本文件大小相关的问题?
- python - 如何在python的类中调用嵌套函数
- swift - 明年从年末日期开始的 Swift Returns 中的日期组件
- r - 将 .dta 导入 R