我用动态语言(javascript,python,haskell等)编写了很多代码,但我现在正在为研究生院学习C语言而且我不知道我在做什么。
最初我使用makefile在一个目录中构建了我的所有源代码,该代码运行得相当不错。但是,我的项目正在增长,我想将源分成多个目录(单元测试,工具,核心等)。例如,我的目录树可能如下所示:
.
|-- src
| |-- foo.c
| |-- foo.h
| `-- main.c
`-- test
`-- test_foo.c
test/test_foo.c
同时使用src/foo.c
和src/foo.h
。使用makefile,构建它的最佳/标准方法是什么?最好是建立项目的规则和构建测试的规则。
我知道还有其他方法可以做到这一点,包括autoconf和其他自动解决方案。但是,我想了解发生了什么,并且能够从头开始编写makefile,尽管它可能不切实际。
任何指导或提示将不胜感激。谢谢!
所以到目前为止给出的三个解决方案如下:
include
目录#include
声明中的路径,如#include "../src/foo.h"
-I
开关通知编译器包含位置到目前为止,我喜欢-I
切换解决方案,因为它不涉及在目录结构更改时更改源代码。
答案 0 :(得分:3)
对于test_foo.c,您只需告诉编译器可以找到头文件的位置。例如。
gcc -I../src -c test_foo.c
然后编译器也会查看此目录以查找头文件。在test_foo.c中,您可以写:
#include "foo.h"
修改强>: 要链接foo.c,实际上是针对foo.o,你需要在目标文件列表中提及它。我假设您已经有了目标文件,然后执行:
gcc test_foo.o ../src/foo.o -o test
答案 1 :(得分:2)
我也很少使用GNU autotools。相反,我会在根目录中放置一个手工制作的makefile。
要获取源目录中的所有标头,请使用以下内容:
get_headers = $(wildcard $(1)/*.h)
headers := $(call get_headers,src)
然后,您可以使用以下命令使测试目录中的对象文件依赖于这些标题:
test/%.o : test/%.c $(headers)
gcc -std=c99 -pedantic -Wall -Wextra -Werror $(flags) -Isrc -g -c -o $@ $<
正如您所看到的,我不喜欢内置指令。另请注意-I
开关。
获取目录的目标文件列表稍微复杂一些:
get_objects = $(patsubst %.c,%.o,$(wildcard $(1)/*.c))
test_objects = $(call get_objects,test)
以下规则将为您的测试制作对象:
test : $(test_objects)
test
规则不应只生成目标文件,而应生成可执行文件。如何编写规则取决于测试的结构:例如,您可以为每个.c
文件创建一个可执行文件,或者只为一个测试所有文件的文件创建一个可执行文件。
答案 2 :(得分:0)
执行此操作的常用方法是将单个C文件使用的头文件命名为与该C文件相同且位于同一目录中的头文件,以及许多C文件使用的头文件(特别是整个使用的文件) project)位于与C源目录并行的目录include
中。
答案 3 :(得分:0)
您的测试文件应该直接使用相对路径包含头文件,如下所示:
#include "../src/foo.h"