- 开启-fvisibility=hidden,编译为静态库,不管函数导不导出,在nm中查看,显示都为T。
例如:
头文件common.h中的内容如下:
#define FUNC_EXPORT __attribute__((visibility("default")))
void funa1(void);
FUNC_EXPORT void funa2(void);
FUNC_EXPORT void funb(void);
文件a.c中的内容如下:
#include "common.h"
void funa1(void)
{
}
void funa2(void)
{
}
CMakeLists.txt中的内容如下:
cmake_minimum_required(VERSION 3.15)
project(TestHidden C CXX)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
add_library(suba STATIC a.c)
add_library(suba2 SHARED a.c)
编译后,用nm查看libsuba.a中的函数:
-
编译为动态库,在nm中查看,导出函数显示为T,非导出函数显示为t。
查看libsuba2.so中的函数:
-
使用objdump -t查看静态库中的函数,可以看出导出函数和非导出函数的区别。
非导出函数有.hidden标记。
- 应用程序可以直接调用静态库中的非导出函数,而不会链接出错。
例如,main.c中的内容如下:
#include "common.h"
int main(void)
{
funa1();
return 0;
}
CMakeLists.txt中增加两行:
add_executable(main main.c)
target_link_libraries(main suba)
编译成功:
- 动态库直接调用静态为中的非导出函数,会报错。
这种情况通常发生在:应用程序调用动态库中的函数A,A调用静态库中的非导出函数B。
例如:
文件b.c中的内容如下:
#include "common.h"
void funb(void)
{
funa1();
}
文件main.c中的内容如下:
#include "common.h"
int main(void)
{
funab();
return 0;
}
修改CMakeLists.txt如下:
add_library(subb SHARED b.c)
add_executable(main main.c)
target_link_libraries(main subb suba)
编译失败:
- 指定动态库依赖静态库,生成动态库时会把所需的符号定义拷贝到自身中,不会链接出错。
修改CMakeLists.txt如下:
target_link_libraries(subb suba)
target_link_libraries(main subb)
编译成功:
静态库中的函数拷贝到动态库中后,是外部的还是内部的?
从前面的例子中可以看出,会保持函数原来的可见性。
例如,funa1在静态库中是内部的(带.hidden),那么拷贝到libsubb.so后,是内部的(nm显示为t)。
funa2在静态库中是外部的(不带.hidden),那么拷贝到libsubb.so后,是外部的(nm显示为T)。