一,Linux平台
每个动态库有三个名字:real name,so name,linker name。
1.1,real name
完整的文件名形式是『lib名字.so.主版本号.次版本号.发行版本号』,例如libexslt.so.0.8.15。这种名字的文件是真正的二进制可执行的库文件。
1.2,so name
完整的文件名形式是『lib名字.so.主版本号』,例如libexslt.so.0。这种名字的文件是符号连接,指向对应的『real name』文件。该名字也会保存于库文件的『SONAME』字段,用命令『readelf -d 库文件名』可以查看:
|
该名字可以在生成动态库的时候指定:
|
如果动态库有『SONAME』字段,那么依赖该库的二进制逻辑启动要自动加载该库时,会在依次在各搜索路径下找名字和『SONAME』字段相同的文件,一找到就立即加载。搜索顺序如下:
|
系统本身不带可以修改『SONAME』字段的工具。有第三方工具『patchelf』可以修改,从这里下载源码编译可得。修改命令为『patchelf --set-soname your_soname library_name』。
1.3,linker name
完整的文件名形式是『lib名字.so』,例如libexslt.so。这种名字的文件是符号连接,指向对应的『so name』文件或者『real name』文件,用于给编译器进行连接。
|
运行时和『linker name』就没关系了,靠的是『so name』。
二,MacOS平台
每个动态库有三个名字:real name、install name、linker name。
2.1,real name
完整的文件名形式是『lib名字.主版本号.次版本号.发行版本号.dylib』,例如libnetsnmp.5.2.1.dylib。这种名字的文件是真正的二进制可执行的库文件。
有时会仿照Linux平台的『so name』,创建一个文件名形式是『lib名字.主版本号.dylib』的符号连接,指向对应的『real name』文件。例如libnetsnmp.5.dylib。
2.2,install name
这是个路径名,保存于库文件的『install_name』字段,用命令『otool -D 库文件名』可以查看:
|
该名字可以在生成动态库的时候指定:
|
如果动态库有『install_name』字段,那么依赖该库的二进制逻辑启动要自动加载该库时,会在『install_name』字段指定的位置加载,因为编译器连接时会把该库的『install_name』字段值写入到生成的二进制逻辑中。
系统本身有工具『install_name_tool』可以修改动态库中的『install_name』字段,或者依赖该库的二进制逻辑中写入的『install_name』字段值:
|
『install name』一般是绝对路径(即以『/』开头的),也可以是相对路径,其中可以带环境变量(即『${变量名}』)。若是相对路径,则可以相对于当前位置(即以『./』开头的),也可以相对于当前位置的上一级(即以『../』开头的),也可以相对于预设值(『@executable_path/』开头表示相对于所属可执行文件的所在位置,『@loader_path/』开头表示所属可执行文件的所有可加载位置的列表,『@rpath/』开头表示编译器连接阶段通过『-Wl,-rpath,your_path』指定的路径);除这些以外的相对路径,系统会依次用各搜索路径与之拼接,检查是否存在,一找到就立即加载。关于搜索顺序,目前没有找到能够明确阐述它的资料。
2.3,linker name
完整的文件名形式是『lib名字.dylib』,例如libnetsnmp.dylib。这种名字的文件是符号连接,指向对应的『real name』文件,用于给编译器进行连接。
|
运行时和『linker name』就没关系了,靠的是『install name』。