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 $@
我正在尝试用 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 $@