gpt4 book ai didi

macos - 在 macOS 上使用当前版本和兼容版本

转载 作者:行者123 更新时间:2023-12-04 15:00:17 26 4
gpt4 key购买 nike

在 macOS 上,dylib 具有 兼容版本和一个 当前版本 作为元数据,每个都具有 x.y.z. 的形式. otool -L可以显示这些。
系统或各种工具/程序如何以及何时使用这些版本?
对于 兼容版本 ,我能够发现:

  • 将程序与库链接时,该库的兼容版本将被记录到程序中。动态链接器将拒绝链接到兼容版本小于记录版本的库。 ( reference ,尽管这是针对框架的)。

  • 问题:
  • 系统(例如,动态链接器)在任何情况下都使用当前版本吗?
  • 比较兼容版本的时候,都是x.y.z的部分使用的方案?比较是按字典顺序排列的吗?还是分别对 x、y 和 z 有特殊含义?
  • 是否有关于这些版本号在哪里使用的文档?请注意,我要求的是在实践中实际使用它们的位置/时间,而不仅仅是关于建议如何设置它们的指南。
  • 系统的任何部分是否对元数据中的两种类型的版本应如何与文件名或为库创建的符号链接(symbolic link)名称相关联有任何期望?例如。与 ls -l /usr/lib/libz*我看到同一个库有许多不同的符号链接(symbolic link),每个符号链接(symbolic link)的名称都有不同的版本。
  • 最佳答案

    1. 系统(例如动态链接器)在任何情况下都使用当前版本吗?
    是的,当使用 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.
    这些变量仅支持 macOS 和 DriverKit 目标。
    此外,库的 Mach-O 头文件中的 current_version 可以通过 NSVersionOfRunTimeLibrary() 查询。 ,以及与 NSVersionOfLinkTimeLibrary() 链接到库的 Mach-O header 中的 current_version .
    2. 比较兼容版本时,x.y.z方案的所有部分都使用了吗?比较是按字典顺序排列的吗?还是分别对 x、y 和 z 有特殊意义?
    所有部分都使用并且比较是字典序的。
    从技术上讲,部分 x.y.z 形成了 xxxxyyzz 形式的 32 位数字,即 16 位 x、8 位 y 和 z。
    3. 是否有关于这些版本号在哪里使用的文档?请注意,我要求的是在实践中实际使用它们的位置/时间,而不仅仅是关于建议如何设置它们的指南。 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.
    但这只是事实的一半。对于真正发生的事情,我们必须查看 dyld sources :
    // check found library version is compatible
    // <rdar://problem/89200806> 0xFFFFFFFF is wildcard that matches any version
    if ( (requiredLibInfo.info.minVersion != 0xFFFFFFFF) && (actualInfo.minVersion < requiredLibInfo.info.minVersion)
    && ((dyld3::MachOFile*)(dependentLib->machHeader()))->enforceCompatVersion() ) {
    // record values for possible use by CrashReporter or Finder
    dyld::throwf("Incompatible library version: %s requires version %d.%d.%d or later, but %s provides version %d.%d.%d",
    this->getShortName(), requiredLibInfo.info.minVersion >> 16, (requiredLibInfo.info.minVersion >> 8) & 0xff, requiredLibInfo.info.minVersion & 0xff,
    dependentLib->getShortName(), actualInfo.minVersion >> 16, (actualInfo.minVersion >> 8) & 0xff, actualInfo.minVersion & 0xff);
    }
    除了 0xffffffff可以用作通配符,这里有趣的是调用 enforceCompatVersion() :
    bool MachOFile::enforceCompatVersion() const
    {
    __block bool result = true;
    forEachSupportedPlatform(^(Platform platform, uint32_t minOS, uint32_t sdk) {
    switch ( platform ) {
    case Platform::macOS:
    if ( minOS >= 0x000A0E00 ) // macOS 10.14
    result = false;
    break;
    case Platform::iOS:
    case Platform::tvOS:
    case Platform::iOS_simulator:
    case Platform::tvOS_simulator:
    if ( minOS >= 0x000C0000 ) // iOS 12.0
    result = false;
    break;
    case Platform::watchOS:
    case Platform::watchOS_simulator:
    if ( minOS >= 0x00050000 ) // watchOS 5.0
    result = false;
    break;
    case Platform::bridgeOS:
    if ( minOS >= 0x00030000 ) // bridgeOS 3.0
    result = false;
    break;
    case Platform::driverKit:
    case Platform::iOSMac:
    result = false;
    break;
    case Platform::unknown:
    break;
    }
    });
    return result;
    }
    如您所见,如果库声明其最低支持的操作系统版本有些新,那么 dyld 会完全忽略兼容性版本。
    因此,如果您完全依赖强制执行的兼容性版本,您将需要使用类似 --target=arm64-macos10.13 的选项。建立你的图书馆。
    4. 系统的任何部分是否对元数据中的两种类型的版本应如何与文件名或为库创建的符号链接(symbolic link)名称相关联有任何期望?
    动态链接仅严格要求,如果您的二进制文件要求 /usr/lib/libz.dylib ,那么库也必须具有完全相同的名称作为其名称。如果库具有 /usr/lib/libz.0.dylib 的嵌入式安装路径,那么它将被视为一个不同的库。
    但是,在绝大多数情况下,您将依赖于在文件系统上的安装路径中找到的库,这需要在 /usr/lib/libz.dylib 处有一个文件。那要么是您要查找的库,要么是指向它的符号链接(symbolic link)。但是在这个阶段通常没有理由涉及符号链接(symbolic link)。
    现在,您看到版本化文件编号的原因是 API 损坏。 compatibility_version字段处理向前兼容性:如果您链接到版本 1.2.3 ,然后任何大于或等于 1.2.3 的版本将工作。但是,如果您以破坏向后兼容性的方式删除或更改导出的 API,则必须使用新的安装名称创建一个新库,并继续发送旧库的最新版本的副本以实现向后兼容性。
    然后符号链接(symbolic link)仅用于链接时间,以指向库的最新版本。
    例子:
    假设您有一个 /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.0lz.1在命令行上,这不是特别好,需要手动更新,如果您希望人们采用新版本,这通常很糟糕。因此,您从 /usr/lib/libz.dylib 创建了一个符号链接(symbolic link)。至 /usr/lib/libz.1.dylib以便 -lz链接到最新版本的库。

    关于macos - 在 macOS 上使用当前版本和兼容版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67055770/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com