将两个使用GCC编译的.o目标文件合并成第三个.o文件

98

如何将两个由GCC编译的.o目标文件合并为第三个.o文件?

$ gcc -c  a.c -o a.o
$ gcc -c  b.c -o b.o
$ ??? a.o b.o -o c.o
$ gcc c.o other.o -o executable

如果您可以访问源文件,则-combine GCC标志将在编译之前合并源文件:

$ gcc -c -combine a.c b.c -o c.o

不过这只适用于源文件,GCC不接受.o文件作为该命令的输入。

通常来说,链接.o文件无法正常工作,因为你无法将链接器的输出作为其输入。结果是一个共享库,而非静态链接到生成的可执行文件中。

$ gcc -shared a.o b.o -o c.o
$ gcc c.o other.o -o executable
$ ./executable
./executable: error while loading shared libraries: c.o: cannot open shared object file: No such file or directory
$ file c.o
c.o: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, not stripped
$ file a.o
a.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped

2
gcc目前没有-combine选项。它存在于gcc 4.1.2中,但不存在于gcc 6.3.0中(其他人可以弄清楚它是何时被删除的)。 - Keith Thompson
2个回答

115

-relocatable-r传递给ld,将创建一个适用于ld的输入对象。

$ ld -relocatable a.o b.o -o c.o
$ gcc c.o other.o -o executable
$ ./executable

生成的文件与原始的.o文件类型相同。

$ file a.o
a.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
$ file c.o
c.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped

如需深入了解,请参阅MaskRay的可重定位链接文章。


2
能否进行反向操作?即从c.o生成a.o和b.o? - Bert Regelink
9
@BertRegelink 不行,因为它没有唯一的逆元。用数学术语来说,它不构成一个群 :P。 - Alec Teal
7
警告:--relocatable似乎不够通用。随Android NDK附带的ld只能识别-relocatable。如果需要可移植性,请坚持使用-r - Martin Bonner supports Monica
3
@matthijs 这个词是一样的,区别在于减一或减二。 - Martin Bonner supports Monica
1
使用ld组合多个.o文件会产生副作用。如果a.o中有一些弱函数恰好在b.o中被定义,那么这些弱函数将在最终的c.o中变成强函数。这可能会打乱一些目的。 - smwikipedia
显示剩余3条评论

10
如果您想创建两个或多个.o文件的存档(即静态库),请使用ar命令:
ar rvs mylib.a file1.o file2.o

@Lucian但是您为什么要这样做呢?静态库比.o文件更方便链接。 - anon
7
我需要在生成的文件上运行objcopy命令,并使某些类型的符号仅对该文件局部可见,以便它们不会在外部可见。其中一些需要局部化的符号在a.ob.o文件之间被引用。我不能局部化单个文件 - 因为在链接时找不到这些符号 - 也不能从静态存档中局部化符号。 - Lucian Adrian Grijincu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接