在Ubuntu系统中链接动态库时未定义的引用

时间:2017-02-08 12:32:30

标签: ubuntu linker dynamic-library

我在我的Ubuntu系统中编写了这样的代码:

my.h

#include <stdio.h>
int a;
int set(void);

lib.c

#include "my.h"
int set(void) {
  a = 100;
  return 0;
}

的main.c

#include "my.h"

int main(void){
  set();
  printf("a = %d\n", a);
  return 0;
}

然后我使用follow命令来构建它们:

gcc -shared -fPIC -o libmy.so -I. lib.c

gcc -L. -lmy -I. -o test main.c

当我构建测试时,我收到错误信息:

main.c:(.text+0x5):undefined reference to 'set'
collect2: error: ld returned 1 exit status
  

但是当我在Fedora23和Fedora24中使用相同的代码时,它运行良好。

所以我想知道为什么会发生这种情况? Ubuntu系统有任何限制吗?

1 个答案:

答案 0 :(得分:1)

你已经违背了联系惯例之间的差异 Fedora的GCC构建和Debian / Ubuntu的GCC构建。

当您调用gcc执行C可执行文件的链接时,它会调用系统链接程序 ld,将命令行链接选项传递给它并静默添加 它们是大量的“样板”连接选项,它们是不变的 用于C语言链接(类似于g++和C ++语言链接)。

这些不变的链接选项由您的发行版决定并配置 进入他们的GCC建设。所以他们在发行版中不变。

Debian / Ubuntu GCC默默地将--as-needed添加到a​​的链接选项中 输入文件和库之前的位置。 Fedora的GCC没有。

--as-needed的作用是使链接器链接为共享库 如果该库提供,它在链接序列中仅找到 链接器找到的一个或多个符号的定义 未定义的引用(即在早期的目标文件或库中) 在连锁序列中)。此行为适用于静态库的任何情况。 因此--as-needed使静态和共享的链接规则相似 库 - 可能被认为对普通用户有帮助。

这种差异是发行版之间的联系政策差异。什么 意味着你要在你的联动命令行Ubuntu上成功链接 必须在任何目标文件或依赖的其他库之后提及任何库 在上面。如果你在一个命令中编译和链接,那么你必须 提及任何库之后任何相应目标文件的源文件 取决于该库。所以在ubuntu上,你的问题命令行应该是:

gcc -I. -o test main.c -L. -lmy

成功。这当然也适用于Fedora。

如果您有兴趣检查链接中隐藏的差异 两个发行版之间的选项,你可以通过添加-Wl,-v来揭示它们 compile-and-link命令用于获取详细的链接器输出。