8

我是C新手

我用动态语言(javascript、python、haskell 等)编写了很多代码,但我现在正在为研究生院学习 C,但我不知道自己在做什么。

问题

最初,我使用 makefile 在一个目录中构建我的所有源代码,效果非常好。但是,我的项目正在增长,我想将源代码拆分为多个目录(单元测试、实用程序、核心等)。例如,我的目录树可能如下所示:

.
|-- src
|   |-- foo.c
|   |-- foo.h
|   `-- main.c
`-- test
    `-- test_foo.c

test/test_foo.c同时使用src/foo.csrc/foo.h。使用makefile,构建它的最佳/标准方法是什么?最好有一条规则用于构建项目,一条规则用于构建测试。

笔记

我知道还有其他方法可以做到这一点,包括 autoconf 和其他自动解决方案。但是,我想了解正在发生的事情并能够从头开始编写 makefile,尽管它可能不切实际。

任何指导或提示将不胜感激。谢谢!

[编辑]

所以目前给出的三种解决方案如下:

  • 将全局使用的头文件放在并行include目录中
  • 使用状态中的路径,#include#include "../src/foo.h"
  • 使用-I开关通知编译器包含位置

到目前为止,我喜欢-Iswitch 解决方案,因为它不涉及在目录结构更改时更改源代码。

4

4 回答 4

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
于 2009-02-28T15:57:57.723 回答
2

我也很少使用 GNU 自动工具。相反,我将在根目录中放置一个手工制作的 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文件创建一个可执行文件,或者只创建一个测试所有文件的可执行文件。

于 2009-02-28T16:12:04.287 回答
0

这样做的一种常见方法是,将单个 C 文件使用的头文件命名为与该 C 文件相同且位于同一目录中,并将许多 C 文件使用的头文件(尤其是整个项目使用的头文件)命名为位于include与 C 源目录平行的目录中。

于 2009-02-28T15:48:10.460 回答
0

您的测试文件应该只使用相对路径直接包含头文件,如下所示:

#include "../src/foo.h"
于 2009-02-28T15:57:48.550 回答