为什么在给定-C选项的绝对路径和本地路径时,make的行为有所不同?

时间:2019-04-16 17:49:11

标签: makefile

我正在编写一个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目录中的是另一个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 ++命令现在与我的模板匹配...有人知道这是为什么发生以及如何处理解决吗?

1 个答案:

答案 0 :(得分:0)

考虑一下:

OBJS = $(notdir $(shell find $(SRCDIR) | grep .o))

%: %.cc $(OBJS)
        $(CC) $(CFLAGS) $(IFLAGS) $(LFLAGS) -o $@ $^

设置SRCDIR可能会找到一些目标文件(顺便说一句,我不知道为什么您在这里使用grep而不是仅将-name \*.o添加到{{ 1}}命令:find有问题,因为它也将与grep之类的文件匹配。)

假设它找到了目标文件foo.ohno。在其上运行/my/path/to/src/foo.o,并将notdir设置为OBJS

这意味着模式变为:

foo.o

现在make想要搜索将匹配的模式规则。它将不符合此规则,因为尽管模式%: %.cc foo.o $(CC) $(CFLAGS) $(IFLAGS) $(LFLAGS) -o $@ $^ %匹配,但其他先决条件%.cc不存在(不在本地目录中)。结果,该模式被忽略,make将继续寻找其他模式。它将找到匹配的内置模式,这就是为什么要获得输出的原因。

在没有找到目标文件的情况下(错误的foo.o命令),find变量为空,因此模式规则匹配。

如果您删除了OBJS,它应该可以工作,但是我不知道为什么要添加它,所以也许还有其他问题。

其他说明:

  • 在调用递归生成时,应始终显式使用notdir$(MAKE),而不要使用${MAKE}或其他变量。
  • 通常,在调用make或其他速度较慢的功能时,应使用:=
  • 如果您使用显式规则而不是模式规则来构建测试程序,那么可能会更容易理解发生的情况:这样,您会得到类似 no rule来构建foo.o的错误