【发布时间】:2019-08-06 20:21:51
【问题描述】:
假设我有两个文件
// a.c
int a() {return 1;}
// b.c
int a();
int b() {return a();}
我将它们分别编译为a.o 和b.o。
为了创建一个可执行或共享库,可以调用gcc a.o b.o -o libab.so -shared。但我也注意到,也可以调用gcc b.o -L. -l:a.o -o libab.so -shared 来生成(显然)相同的输出。令我惊讶的是,即使运行gcc a.o -L. -l:b.o -shared 也会生成一个同时包含a() 和b() 的库。 (链接器不应该丢弃未使用的库b.o,因为a.o 不依赖它吗?)
后两个大概传递a 就好像a.o 是一个库一样。现在,如果我运行 ar rcs liba.a a.o、gcc b.o -L. -l:liba.a -shared 和 gcc b.o liba.a -shared 都运行没有任何问题并给出相同的输出。
但是,我也看到了这种技巧不起作用并导致未定义引用的情况。因此,正如标题所说,我的问题是:将对象作为库和普通对象文件传递有什么区别,在 C++ 方面有什么区别?
问题出现在一个更大的项目中。抱歉缺少 mcve,因为我似乎无法隔离问题。
【问题讨论】:
-
我想,这里有一些误解。静态库只是 .o 文件的存档,因此链接器可以将单个 .o 文件视为库也就不足为奇了。它本身不应导致任何未定义的行为。恐怕,您必须在隔离测试用例上做更多工作。
-
@SergeyA,我知道
.a是.o文件的存档。为简单起见,假设.a是.o,那么问题是gcc a.o b.o与gcc a.o -L. -l:b.o有何不同。 -
这正是我所说的,没有真正的区别。另外,
-l:<lib>是我不熟悉的语法,我在任何地方都找不到它的引用。我认为它有效,但我很确定这不是传统的。 -
results undefined references- 这到底是什么意思? -
您知道库的顺序在链接器调用中很重要吗?也许这可能是一个答案?使用 .o 文件时,符号的顺序无关紧要,而对于 .so 文件,它很重要?