Makefile在子文件夹中找不到文件

mat*_*to0 1 c gcc makefile gnu-make

我正在尝试用 C 为我的项目编写 Makefile。
我的.c文件在src
.o文件build夹中,子文件夹中的
.h文件,src/header子文件夹中的文件
和子文件夹.c中的测试tests文件。

在我的 Makefile 中,我使用的是 vpath:

 vpath %.c src:tests
 vpath %.h src/header
 vpath %.o build
Run Code Online (Sandbox Code Playgroud)

当我想编译时file1,Makefilefile1.c在子文件夹中查找并将目标文件编译到子文件夹中没有问题build/file1.o。但是当它把file1编译成可执行文件时,Makefile找不到file1.o

这是我在 Makefile 中针对特定文件的代码:

test_file1: test_file1.o file.o
    $(CC) $^ -o tests/$@

test_file1.o: test_file1.c file1.h  
    $(CC) $(CFLAGS) -c $< -o build/$@

file1.o: file1.c file1.h file2.h file3.h
    $(CC) $(CFLAGS) -c $< -o build/$@
Run Code Online (Sandbox Code Playgroud)

test_file1.o我得到:
gcc -std=c99 -Wall -Wextra -pedantic -g -c tests/test_file1.c -o build/test_file1.o没有问题。

file1.o我得到:
gcc -std=c99 -Wall -Wextra -pedantic -g -c src/file1.c -o build/file1.o也没有问题。

但是从test_file1我得到的文件没有子文件夹的路径:
gcc test_file1.o file1.o -o tests/test_file1.

并得到这个错误:
gcc: error: test_file1.o: No such file or directory gcc: error: file1.o: No such file or directory gcc: fatal error: no input files

这两个文件都在子文件夹中build
哪里有问题?

Bet*_*eta 5

问题在于您的某些规则实际上并未构建他们声称要构建的内容,这违反了Mad Scientist's Second Law of Makefiles

Make 认为它必须构建file1.o. 该文件一开始不存在,vpath 无法找到尚不存在的文件。所以 Make 寻找一个规则并发现:

file1.o: file1.c file1.h file2.h file3.h
    $(CC) $(CFLAGS) -c $< -o build/$@
Run Code Online (Sandbox Code Playgroud)

该规则的目标是file1.o。Make 假设这将构建file1.o,执行它,然后尝试file1.o在另一个配方中使用——这失败了,因为file1.o仍然不存在。

该规则实际上建立build/file1.o。不,Make 不够聪明,无法从食谱中推断出这个事实。

解决方法:更改规则。

build/file1.o: file1.c file1.h file2.h file3.h
    $(CC) $(CFLAGS) -c $< -o $@
Run Code Online (Sandbox Code Playgroud)

同样地:

build/test_file1.o: test_file1.c file1.h  
    $(CC) $(CFLAGS) -c $< -o $@
Run Code Online (Sandbox Code Playgroud)