Makefile 无法在子文件夹中找到文件

Makefile can not find files in subfolders

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

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

 vpath %.c src:tests
 vpath %.h src/header
 vpath %.o build

当我想编译 file1 时,Makefile 可以在子文件夹中找到 file1.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/$@

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 中。
哪里有问题?

问题在于您的某些规则实际上并未构建他们声称要构建的内容,这违反了 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/$@

这条规则的目标是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 $@

同样:

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