c++ - GNU make 有时不在 VPATH 中声明的文件夹中搜索

标签 c++ makefile gnu-make flex-lexer

我正在尝试使用 GNU make(版本 3.81)构建一个小型 C++ 项目,但我必须调用 make 两次,因为第一次运行失败。这是我的项目目录:

project
    makefile
    include
        lexer.hpp   
    src
        main.cpp
        lexer.l

以下是我的makefile:

CC = g++
CPPFLAGS = -I include
VPATH = include src

OBJECTS = main.o lexer.o

test: $(OBJECTS)
$(CC) $(CPPFLAGS) -lfl -o $@ $^

main.o: lexer.hpp main.cpp
    $(CC) -c $(CPPFLAGS) $^

lexer.o: lexer.cpp
    $(CC) -c $(CPPFLAGS) $^

lexer.cpp: lexer.l
    flex -t $^ > src/lexer.cpp

.PHONY: clean

clean:
    rm -fR $(OBJECTS) src/lexer.cpp test

我第一次运行 make 时得到以下输出,其中 make 提示找不到 lexer.cpp 文件。但我不明白为什么 make 不在 VPATH 中声明的文件夹中查找。

g++ -c -I include include/lexer.hpp src/main.cpp
flex -t src/lexer.l > src/lexer.cpp
g++ -c -I include lexer.cpp
g++: error: lexer.cpp: No such file or directory
g++: fatal error: no input files
compilation terminated.
make: *** [lexer.o] Error 1

但是,如果我再次调用 make,则会找到 lexer.cpp 并且编译工作。

g++ -c -I include src/lexer.cpp
g++ -I include -lfl -o test main.o lexer.o

为什么?

附言我为糟糕的英语道歉。

最佳答案

这条规则是错误的:

lexer.cpp: lexer.l
        flex -t $^ > src/lexer.cpp

这条规则告诉 make 它将构建一个文件 lexer.cpp,这就是 make 期望它做的事情,并且在规则完成后 make 认为该文件已准备就绪,并且当其他目标依赖它时,它将使用该文件名。但规则真正做的是构建 src/lexer.cpp

要正确编写此规则,您需要将其编写为:

src/lexer.cpp: lexer.l
        flex -t $^ > $@

(您编写的每个 make 规则都应该始终准确地更新文件 $@)。

但是,一般来说,VPATH 不利于查找生成的文件(目标文件等:由 make 生成的任何文件)。它仅对查找源文件有用(文件 make 不会自行构建)。

关于c++ - GNU make 有时不在 VPATH 中声明的文件夹中搜索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17749391/

相关文章:

c++ - 将 jpeg 从一个缓冲区调整到另一个缓冲区

linux - 如何使用 autotools、make 和 gcc 在 64 位 (Ubuntu 12.04LTS) Linux 上编译和安装 32 位库?

macos - 在 Mac OS X 上的 Makefile 中设置 PATH(但它适用于 Linux)

makefile - Makefile中的函数“patsubst”

shell - 编译 Readline 时对 "tputs"的 undefined reference

c++ - 合并两个优先队列

c++ - QWeb引擎 : How to get attribute value?

c++ - vb.net byte[] 到 C++ char*

c++ - 使用 G++ 编译多个 .cpp 和 .h 文件

c++ - Ubuntu 上 Eclipse 中的非自由库(用于 Surf Descriptor)的 OpenCV 编译错误