一、“--export-dynamic”参数的使用
GCC编译可执行文件时可以使用-Wl,--export-dynamic参数,此时链接器产生可执行文件时会将所有全局符号导出到动态符号表。
gcc -Wl,--export-dynamic -o p1 p1.c -L. -l0
如果在创建动态链接的可执行文件不加-Wl,--export-dynamic选项,则它所export的动态符号仅仅包括在链接时动态对象所用到的。因为dlopen是自行加载动态库,并不存在与可执行文件动态符号解析的过程,所以如果dlopen加载的动态库使用了主模块中定义的函数,则会出现找不到符号的情况。
默认链接器在产生可执行文件时,只会将那些链接时被其他共享模块引用到的符号放到动态符号表中,这样可以减少动态符号表的大小,也就是说,在共享模块中反向引用主模块中的符号时,只有那些在链接时被共享模块引用到的符号才会被导出。(主模块的符号表中依赖的共享模块主模块才会去链接,否则不会去链接,不被链接的模块引用了主模块的符号就不会被导出到动态符号表中,导致运行时报错)。
但是使用--export-dynamic参数后由于将所有的全局符号导出到动态符号表中导致可执行程序会变大。
二、strip清除符号信息
正常情况下编译出来的共享库和可执行文件中都带有符号信息和调试信息,但是发布版本一般不需要这些信息。且这些信息会导致可执行文件大一倍多,所以可以使用strip命令去掉调试信息:strip liba.so
ld的“-S”和“-s”也能使链接器输出的可执行文件不产生调试信息,“-S”消除调试符号信息,“-s”消除所有符号信息。
gcc -WI,-s a.out或gcc -WI,-S a.out
三、共享库的安装部署
1、设置环境变量LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/home/work/deal/dynamic
export LD_LIBRARY_PATH=$(pwd)
2、使用链接器的“-rpath”选项,可以指定链接器产生的目标文件的共享库查找路径。
ld -rpath /home/lib -o a.out a.o -lc
这样参数的a.out首先会在/home/lib目录下查找共享库,可以使用“-L”,“-l”分别指定共享库的搜索目录和共享库的名称。
3、将共享库复制到共享目录中/lib /usr/lib然后运行ldconfig即可。需要root才能有权限往lib下拷贝文件和运行ldconfig
4、建立相应的SO-NAME软链接GCC可以使用“-WI,-soname,my_soname”参数将my_soname传递给链接器,用来指定输出共享库的SO-NAME,如:
gcc -shared -WI,-soname,my_soname -o a.so a.c -lc
如果不使用-soname指定共享库的SO-NAME,那么默认共享库就没有SO-NAME,即使用ldconfig更新SO-NAME的软链接时,对该库也没有效果。
使用ldconfig更新SO-NAME的软链接命令:
ldconfig -n /home/lib