在 Ubuntu 系统中链接动态库时未定义引用
undefined reference when linking dynamic library in Ubuntu system
我在我的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;
}
然后我使用以下命令来构建它们:
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
but when i use the same code run in Fedora23 and Fedora24, it works well.
所以我想知道为什么会这样? Ubuntu系统有什么限制吗?
您违反了link年龄惯例之间的差异
Fedora 的 GCC 构建和 Debian/Ubuntu 的 GCC 构建。
当您调用 gcc
来执行 C 可执行文件的 linkage 时,它又会调用系统 linker
ld
,将其传递给您的命令行 linkage 选项并默默地添加到
他们有大量 "boilerplate" linkage 选项是不变的
对于 C 语言 linkages(对于 g++
和 C++ 语言 linkages 也是如此)。
那些不变的 linkage 选项由您的发行版决定并配置
进入他们的GCC构建。所以它们不是跨发行版不变。
Debian/Ubuntu GCC 默默地将 --as-needed
添加到 linkage 选项
输入文件和库之前的位置。 Fedora 的 GCC 没有。
--as-needed
的作用是让linker link成为共享库
它在 linkage 序列 只有 中发现
linker 已经找到一个或多个符号的定义
未定义的引用(即在早期的目标文件或库中
在 link 年龄序列中)。此行为在任何情况下都适用于静态库。
因此 --as-needed
使静态和共享的 linkage 规则相似
图书馆 - 这可能被认为对普通用户有帮助。
此差异是发行版之间的link年龄政策差异。什么
对你来说意味着 link 在 Ubuntu 上成功,你的 linkage 命令行
必须在 之后提及任何库 任何目标文件或依赖的其他库
在上面。如果你在一个命令中是compiling-and-linking,那么你必须
在 之后提及任何库 其对应目标文件的任何源文件
取决于那个图书馆。所以在 ubuntu 上,你的问题命令行应该是:
gcc -I. -o test main.c -L. -lmy
成功。这当然也适用于 Fedora。
如果您有兴趣检查link年龄中隐藏的差异
两个发行版之间的选项你可以通过添加 -Wl,-v
来显示它们
compile-and-link 命令获得详细的 linker 输出。
我在我的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;
}
然后我使用以下命令来构建它们:
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
but when i use the same code run in Fedora23 and Fedora24, it works well.
所以我想知道为什么会这样? Ubuntu系统有什么限制吗?
您违反了link年龄惯例之间的差异 Fedora 的 GCC 构建和 Debian/Ubuntu 的 GCC 构建。
当您调用 gcc
来执行 C 可执行文件的 linkage 时,它又会调用系统 linker
ld
,将其传递给您的命令行 linkage 选项并默默地添加到
他们有大量 "boilerplate" linkage 选项是不变的
对于 C 语言 linkages(对于 g++
和 C++ 语言 linkages 也是如此)。
那些不变的 linkage 选项由您的发行版决定并配置 进入他们的GCC构建。所以它们不是跨发行版不变。
Debian/Ubuntu GCC 默默地将 --as-needed
添加到 linkage 选项
输入文件和库之前的位置。 Fedora 的 GCC 没有。
--as-needed
的作用是让linker link成为共享库
它在 linkage 序列 只有 中发现
linker 已经找到一个或多个符号的定义
未定义的引用(即在早期的目标文件或库中
在 link 年龄序列中)。此行为在任何情况下都适用于静态库。
因此 --as-needed
使静态和共享的 linkage 规则相似
图书馆 - 这可能被认为对普通用户有帮助。
此差异是发行版之间的link年龄政策差异。什么 对你来说意味着 link 在 Ubuntu 上成功,你的 linkage 命令行 必须在 之后提及任何库 任何目标文件或依赖的其他库 在上面。如果你在一个命令中是compiling-and-linking,那么你必须 在 之后提及任何库 其对应目标文件的任何源文件 取决于那个图书馆。所以在 ubuntu 上,你的问题命令行应该是:
gcc -I. -o test main.c -L. -lmy
成功。这当然也适用于 Fedora。
如果您有兴趣检查link年龄中隐藏的差异
两个发行版之间的选项你可以通过添加 -Wl,-v
来显示它们
compile-and-link 命令获得详细的 linker 输出。