我有一个奇怪的错误,我设法将其减少到以下内容。我有一个只有两个空文件的文件夹:一个 Makefile 和一个 cpp 文件:
$ ls -la
total 8
drwxrwxr-x 2 erelsgl erelsgl 4096 Mar 3 20:12 .
drwxrwxr-x 13 erelsgl erelsgl 4096 Mar 3 20:10 ..
-rw-rw-r-- 1 erelsgl erelsgl 0 Mar 3 20:12 Demo.cpp
-rw-rw-r-- 1 erelsgl erelsgl 0 Mar 3 20:09 Makefile
$ cat Makefile
$ cat Demo.cpp
当我运行时,make
我得到了预期的结果:
$ make
make: *** No targets. Stop.
但当我跑步时,make Demo.o
我得到了一个非常奇怪的结果:
$ make Demo.o
clang++-5.0 -std=c++17 -c -o Demo.o Demo.cpp
make: clang++-5.0: Command not found
<builtin>: recipe for target 'Demo.o' failed
make: *** [Demo.o] Error 127
命令“clang++-5.0 -std=c++17”实际上几天前就在 Makefile 中,但我很久以前就用 clang++-9 替换了它。现在,如您所见,Makefile 完全是空的。为什么make
仍在运行这些旧命令?
编辑:当我更改 Makefile 以包含这两行时,会发生同样的事情:
%.o: %.cpp xxx.h
clang++-9 --compile $< -o $@
当文件 xxx.h 不存在时。这非常令人困惑:我运行它make Demo.o
,它是用 clang++-5.0 而不是 clang++-9 构建的!
答案1
看这个 Makefile 是如何在不指定编译器的情况下生成 C 程序的?为背景。 Make 有内置规则告诉它如何构建各种文件;在这种特殊情况下,由于您要求一个目标文件,并且.cpp
当前目录中有一个匹配的文件,因此它使用指定如何从.cpp
文件构建目标文件的规则。
在 GNU Make 中,该规则的某些部分最终使用了变量;特别是CXX
对于 C++ 编译器,以及CXXFLAGS
编译 C++ 代码时使用的标志。如果环境包含这些变量的值,则这些值优先于内置默认值。由于CXX
仍设置为clang++-5.0
,Make 尝试使用它来构建Demo.o
。
使用两行 Makefile,您定义的配方不会被使用因为它的先决条件并不全部存在,也不可能全部实现。相反,再次使用通用模式规则,但仍CXX
设置为clang++-5.0
。
-r
您可以使用 选项完全禁用内置规则make
。你也可以补充它们;因此
Demo.o: Demo.cpp xxx.h
没有配方将使用内置规则,但需要xxx.h
添加Demo.cpp
(并且正确地失败,因为xxx.h
不存在且无法构建)。