我有 2 个
.c
文件以及各自的 .h
文件和 main.c
。
文件内容如下:
main.c
#include "a.h"
int main() {
a_func();
}
啊啊
#include "b.h"
/* struct defined in b.h is used here */
void a_func();
a.c
#include "a.h"
#include "b.h"
void a_func(){...} /* b_func is called within a_func */
b.h
void b_func();
b.c
#include "b.h"
b_func(){...}
我写了一个Makefile来编译
main.c
:
main: main.o a.o
gcc main.o a.o -o main
main.o main.c
gcc -c main.c
a.o: a.c a.h b.h
gcc -c a.c
但是,投诉一下:
a.o: In function `a_func':
a.c: undefined reference to `b_func'
我想知道如何修改 Makefile 才能使其工作。
我认为这是学习翻译单位概念的最佳时机。
简而言之,翻译单元是单个源文件,包含所有包含的标头。这是编译器本身使用的单位。
您的代码使用多个翻译单元,其中的函数定义(实现)是从其他翻译单元使用的。编译器对其他翻译单元一无所知,只知道它当前正在编译的翻译单元。
链接器的工作是获取所有翻译单元(编译器创建的
*.o
文件,本质上是翻译单元的二进制形式)并将它们与库一起拉到一起以创建可执行程序文件。链接器会解析缺少的外部函数,因此如果目标文件 main.o
使用 a.o
中的函数,那么它将确保解析该连接。
您遇到的问题是您仅链接到
main.o
和 a.o
翻译单元。并且 a.o
没有定义 b_func
函数,导致出现错误。
要解决该问题,您需要将
b.c
源文件构建到 b.o
目标文件中,然后与其链接。您需要创建一个类似于 a.o
的规则,并在 b.o
的依赖项中添加 main
。