我在我的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系统有任何限制吗?
答案 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命令用于获取详细的链接器输出。