如何链接C中的对象文件? 未能通过“架构x86_64的未定义符号”
所以我试图使用我的文件(file2.c)中另一个C(file1.c)文件中定义的函数。 我包含file1(file1.h)的头文件,以便执行此操作。
但是,当我尝试使用gcc编译我的文件时,我总是收到以下错误:
Undefined symbols for architecture x86_64: "_init_filenames", referenced from: _run_worker in cc8hoqCM.o "_read_list", referenced from: _run_worker in cc8hoqCM.o ld: symbol(s) not found for architecture x86_64
我已经被告知我需要“将目标文件链接在一起”,以便使用file2中的file1函数,但是我不知道这意味着什么:
我假设你使用的是gcc
,只需链接目标文件即可:
$ gcc -o output file1.o file2.o
获取对象文件简单地编译使用
$ gcc -c file1.c
这产生file1.o等等。
如果你想链接你的文件到一个可执行文件
$ gcc -o output file1.c file2.c
现有的答案已经涵盖了“如何”,但我只是想详细说明其他人可能想知道的“什么”和“为什么”。
编译器(gcc)做了什么:术语“编译”是一个超载的术语,因为它被用在高级别的意思是“将源代码转换成程序”,但更技术上意味着“将源代码转换为目标代码“。 像gcc这样的编译器实际上执行了两个相关的,但可以说是截然不同的function来将你的源代码转换成一个程序:编译(如在后来的源代码转换为目标代码的定义)和链接(将必要的目标代码文件组合到一起一个完整可执行文件)
您看到的原始错误在技术上是一个“链接错误”,并由链接器“ld”引发。 与(严格的)编译时错误不同,没有对源代码行的引用,因为链接器已经在对象空间中。
默认情况下,当gcc被赋予源代码作为input时,它会尝试编译每个然后将它们连接在一起。 正如其他回复中指出的那样,可以使用标志来指示gcc首先编译,然后稍后使用目标文件在单独的步骤中进行链接。 这个两步过程可能看起来没有必要(可能是非常小的程序),但是在pipe理一个非常大的程序时非常重要,在每次进行小的更改时编译整个项目会浪费相当多的时间。
你可以编译和链接在一个命令:
gcc file1.c file2.c -o myprogram
并运行:
./myprogram
但要回答问题,只需将目标文件传递给gcc
:
gcc file1.o file2.o -o myprogram
将foo1.c,foo2.c,foo3.c和makefile添加到bash中的maketypes的文件夹中
如果您不想使用makefile,则可以运行该命令
gcc -c foo1.c foo2.c foo3.c
然后
gcc -o output foo1.o foo2.o foo3.o
foo1.c
#include <stdio.h> #include <string.h> void funk1(); void funk1() { printf ("\nfunk1\n"); } int main(void) { char *arg2; size_t nbytes = 100; while ( 1 ) { printf ("\nargv2 = %s\n" , arg2); printf ("\n:> "); getline (&arg2 , &nbytes , stdin); if( strcmp (arg2 , "1\n") == 0 ) { funk1 (); } else if( strcmp (arg2 , "2\n") == 0 ) { funk2 (); } else if( strcmp (arg2 , "3\n") == 0 ) { funk3 (); } else if( strcmp (arg2 , "4\n") == 0 ) { funk4 (); } else { funk5 (); } } }
foo2.c
#include <stdio.h> void funk2(){ printf("\nfunk2\n"); } void funk3(){ printf("\nfunk3\n"); }
foo3.c
#include <stdio.h> void funk4(){ printf("\nfunk4\n"); } void funk5(){ printf("\nfunk5\n"); }
生成文件
outputTest: foo1.o foo2.o foo3.o gcc -o output foo1.o foo2.o foo3.o make removeO outputTest.o: foo1.c foo2.c foo3.c gcc -c foo1.c foo2.c foo3.c clean: rm -f *.o output removeO: rm -f *.o
由于没有提到如何编译一个.c文件以及一堆.o文件,并且这个注释要求:
在这个答案main.c在哪里? :/如果file1.c是主要的,你如何链接它与其他已编译的.o文件? – 汤姆布里托14年10月12日在19:45
$ gcc main.c lib_obj1.o lib_obj2.o lib_objN.o -o x0rbin
在这里,main.c是main()函数的C文件,而对象文件(* .o)是预编译的。 GCC知道如何一起处理这些数据,并相应调用链接器,并产生最终的可执行文件,在我们的例子中是x0rbin。
您将能够使用main.c中没有定义的函数,但是使用extern引用来定义目标文件(* .o)中定义的函数。
如果对象文件具有正确的格式(如COFF),您也可以链接.obj或其他扩展名。