【发布时间】:2017-09-19 15:47:10
【问题描述】:
我想同时使用符号版本控制和链接时优化 (LTO) 来编译一个共享库。但是,一旦我打开 LTO,一些导出的符号就会消失。这是一个最小的例子:
首先定义一个函数的两个实现fun:
$ cat fun.c
#include <stdio.h>
int fun1(void);
int fun2(void);
__asm__(".symver fun1,fun@v1");
int fun1() {
printf("fun1 called\n");
return 1;
}
__asm__(".symver fun2,fun@@v2");
int fun2() {
printf("fun2 called\n");
return 2;
}
创建版本脚本以确保只导出fun:
$ cat versionscript
v1 {
global:
fun;
local:
*;
};
v2 {
global:
fun;
} v1;
第一次尝试,不使用 LTO 编译:
$ gcc -o fun.o -Wall -Wextra -O2 -fPIC -c fun.c
$ gcc -o libfun.so.1 -shared -fPIC -Wl,--version-script,versionscript fun.o
$ nm -D --with-symbol-versions libfun.so.1 | grep fun
00000000000006b0 T fun@@v2
0000000000000690 T fun@v1
.. 应该是这样。但如果我用 LTO 编译:
$ gcc -o fun.o -Wall -Wextra -flto -O2 -fPIC -c fun.c
$ gcc -o libfun.so.1 -flto -shared -fPIC -Wl,--version-script,versionscript fun.o
$ nm -D --with-symbol-versions libfun.so.1 | grep fun
..不再导出符号。
我做错了什么?
【问题讨论】:
-
不确定到底发生了什么,但您知道符号指定的对象(函数?!)在重新编译后甚至可能不再存在?对于调试构建,不要使用 LTO 并使用
-Og -
我不明白你的评论。 “重新编译”是什么意思?我只编译一次。为什么该功能应该不复存在?我正在创建一个共享对象,因此 LTO 应该单独保留导出的符号。
-
""重新编译"是什么意思?我只编译一次。"在使用 LTO 之类的功能之前,最好了解它的实际作用。
-
哦,这就是你的意思。不过,我的问题仍然存在:为什么该功能不复存在?
-
也许可以试试
# define DLLEXPORT __attribute__((visibility("default"),externally_visible))