Sza*_*lcs 4 macos version shared-libraries dylib dynamic-linking
在 macOS 上,dylib 有一个兼容版本和一个当前版本作为元数据,每个版本都有x.y.z.. otool -L可以显示这些。
系统或各种工具/程序如何以及何时使用这些版本?
对于兼容性版本,我发现:
问题:
x.y.z?比较是字典顺序吗?还是x、y、z分别有特殊含义?ls -l /usr/lib/libz*我看到同一个库有许多不同的符号链接,每个符号链接的名称都有不同的版本。是的,当使用DYLD_VERSIONED_LIBRARY_PATH或DYLD_VERSIONED_FRAMEWORK_PATH环境变量时。从man dyld:
DYLD_VERSIONED_LIBRARY_PATH
This is a colon separated list of directories that contain potential over-
ride libraries. The dynamic linker searches these directories for dynamic
libraries. For each library found dyld looks at its LC_ID_DYLIB and gets
the current_version and install name. Dyld then looks for the library at
the install name path. Whichever has the larger current_version value
will be used in the process whenever a dylib with that install name is
required. This is similar to DYLD_LIBRARY_PATH except instead of always
overriding, it only overrides is the supplied library is newer.
DYLD_VERSIONED_FRAMEWORK_PATH
This is a colon separated list of directories that contain potential over-
ride frameworks. The dynamic linker searches these directories for frame-
works. For each framework found dyld looks at its LC_ID_DYLIB and gets
the current_version and install name. Dyld then looks for the framework
at the install name path. Whichever has the larger current_version value
will be used in the process whenever a framework with that install name is
required. This is similar to DYLD_FRAMEWORK_PATH except instead of always
overriding, it only overrides if the supplied framework is newer. Note:
dyld does not check the framework's Info.plist to find its version. Dyld
only checks the -currrent_version number supplied when the framework was
created.
Run Code Online (Sandbox Code Playgroud)
这些变量仅支持 macOS 和 DriverKit 目标。
此外,库的 Mach-O 标头中的 current_version 可以通过 查询NSVersionOfRunTimeLibrary(),并且 Mach-O 标头中的 current_version 通过 与库链接NSVersionOfLinkTimeLibrary()。
所有部分均已使用,并且比较是按字典顺序进行的。
从技术上讲,xyz 部分形成 xxxxyyzz 形式的 32 位数字,即各 16 位 x、8 位 y 和 z。
有一些文档man ld:
-compatibility_version number
Specifies the compatibility version number of the library. When a
library is loaded by dyld, the compatibility version is checked and if
the program's version is greater that the library's version, it is an
error. The format of number is X[.Y[.Z]] where X must be a positive
non-zero number less than or equal to 65535, and .Y and .Z are
optional and if present must be non-negative numbers less than or
equal to 255. If the compatibility version number is not specified,
it has a value of 0 and no checking is done when the library is used.
This option is also called -dylib_compatibility_version for compati-
bility.
Run Code Online (Sandbox Code Playgroud)
但这只是事实的一半。对于真正发生的事情,我们必须查看dyld 来源:
DYLD_VERSIONED_LIBRARY_PATH
This is a colon separated list of directories that contain potential over-
ride libraries. The dynamic linker searches these directories for dynamic
libraries. For each library found dyld looks at its LC_ID_DYLIB and gets
the current_version and install name. Dyld then looks for the library at
the install name path. Whichever has the larger current_version value
will be used in the process whenever a dylib with that install name is
required. This is similar to DYLD_LIBRARY_PATH except instead of always
overriding, it only overrides is the supplied library is newer.
DYLD_VERSIONED_FRAMEWORK_PATH
This is a colon separated list of directories that contain potential over-
ride frameworks. The dynamic linker searches these directories for frame-
works. For each framework found dyld looks at its LC_ID_DYLIB and gets
the current_version and install name. Dyld then looks for the framework
at the install name path. Whichever has the larger current_version value
will be used in the process whenever a framework with that install name is
required. This is similar to DYLD_FRAMEWORK_PATH except instead of always
overriding, it only overrides if the supplied framework is newer. Note:
dyld does not check the framework's Info.plist to find its version. Dyld
only checks the -currrent_version number supplied when the framework was
created.
Run Code Online (Sandbox Code Playgroud)
0xffffffff除了可以用作通配符这一事实之外,这里有趣的一点是对 的调用enforceCompatVersion():
-compatibility_version number
Specifies the compatibility version number of the library. When a
library is loaded by dyld, the compatibility version is checked and if
the program's version is greater that the library's version, it is an
error. The format of number is X[.Y[.Z]] where X must be a positive
non-zero number less than or equal to 65535, and .Y and .Z are
optional and if present must be non-negative numbers less than or
equal to 255. If the compatibility version number is not specified,
it has a value of 0 and no checking is done when the library is used.
This option is also called -dylib_compatibility_version for compati-
bility.
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,如果库声明其支持的最低操作系统版本有点新,则 dyld 会完全忽略兼容性版本。
因此,如果您完全依赖于强制执行的兼容性版本,那么您将需要使用诸如--target=arm64-macos10.13构建库之类的选项。
动态链接仅严格要求,如果您的二进制文件需要/usr/lib/libz.dylib,则库也必须具有完全相同的名称集。如果该库具有嵌入式安装路径/usr/lib/libz.0.dylib,那么它将被视为不同的库。
但是,在绝大多数情况下,您将依赖于在文件系统的安装路径上找到的库,并且这要求存在一个文件,该文件要么/usr/lib/libz.dylib是您正在查找的库,要么是指向它的符号链接。但在这个阶段通常没有理由涉及符号链接。
现在,您看到版本化文件编号的原因是 API 损坏。该compatibility_version字段处理向前兼容性:如果您链接到 version 1.2.3,则任何大于或等于的版本都1.2.3将起作用。但是,如果您以破坏向后兼容性的方式删除或更改导出的 API,则必须使用新的安装名称创建一个新库,并继续发布旧库的最后版本的副本以实现向后兼容性。
然后,符号链接仅用于链接时,以指向库的最新版本。
示例:
假设您有一个/usr/lib/libz.0.dylib,它有许多更新,修复了错误,扩展了 API 并提升了compatibility_version. 所有这些都将作为 发布/usr/lib/libz.0.dylib,并且该库的最新版本仍将使用与其第一个版本链接的二进制文件。
现在,您要删除其中一个导出的函数,并且由于这是一项重大更改,因此从此之后的任何版本都不能作为/usr/lib/libz.0.dylib. 因此,您创建/usr/lib/libz.1.dylib并传送两个库,dyld 将加载主二进制文件构建所针对的任何库。
但现在任何链接到该库的人都必须在命令行上传递 或-lz.0,lz.1这不是特别好并且需要手动更新,如果您希望人们采用新版本,这通常是不好的。因此,您可以创建一个从/usr/lib/libz.dylib到 的符号链接/usr/lib/libz.1.dylib,以便-lz链接到该库的最新版本。
| 归档时间: |
|
| 查看次数: |
1325 次 |
| 最近记录: |