1

我正在尝试在 OS X (10.7.5) 下对共享库进行版本控制,但我无法dyld识别最大兼容性版本(最低版本还可以)。考虑下面的测试代码和以下场景:

  1. 二进制链接到版本 1.0 的库,兼容性版本 1.0

    • binary按预期工作
      • otool -L binarylibdyldtest.dylib (compatibility version 1.0.0, current version 1.0.0)
      • otool -L libdyldtest.dyliblibdyldtest.dylib (compatibility version 1.0.0, current version 1.0.0)
  2. 库更新并重新编译,移至 2.0 版,兼容 1.0 版

    • binary应该仍然可以工作,并且确实可以,因为库的兼容性已经足够老了
      • otool -L binarylibdyldtest.dylib (compatibility version 1.0.0, current version 1.0.0)
      • otool -L libdyldtest.dyliblibdyldtest.dylib (compatibility version 1.0.0, current version 2.0.0)
  3. 库已更新并重新编译为不兼容的版本。将版本和兼容版本都设置为 3.0。二进制不重新编译。

    • binary应该停止工作,因为它想要与 1.0 兼容但libdyldtest仅与 3.0 及更高版本兼容的东西。为什么这行得通?
      • otool -L binarylibdyldtest.dylib (compatibility version 1.0.0, current version 1.0.0)
      • otool -L libdyldtest.dyliblibdyldtest.dylib (compatibility version 3.0.0, current version 3.0.0)
      • 设置DYLD_PRINT_LIBRARIES显示libdyldtest.3.0.dylib正在加载

问题是上面的 3 个有效,我认为它不应该。这是预期的行为吗?如果没有,我该如何纠正?

注意:10.7.5 的相关dyld 源代码似乎没有使用结构的maxVersion成员LibraryInfo,只有minVersion. 因此,将最低兼容版本设置得较低可以按预期工作:

  • 库设置为版本 0.9,兼容性 0.0
    • binary正如预期的那样停止工作。
      • otool -L binarylibdyldtest.dylib (compatibility version 1.0.0, current version 1.0.0)
      • otool -L libdyldtest.dyliblibdyldtest.dylib (compatibility version 0.0.0, current version 0.9.0)
        • 正如预期的那样,运行binary结果。Reason: Incompatible library version: binary requires version 1.0.0 or later, but libdyldtest.0.9.dylib

谢谢!


示例代码

图书馆.h:

#ifndef __LIBRARY_H__
#define __LIBRARY_H__

void functionFromLibrary();

#endif /* __LIBRARY_H__ */

图书馆.c:

#include "library.h"

#include <stdio.h>

void
functionFromLibrary()
{
    printf("functionFromLibrary()\n");
}

二进制.c:

#include "library.h"

int
main(
    int argc, 
    char *argv[])
{
    functionFromLibrary();
    return (0);
}

生成文件:

.PHONY: all library binary

MAJOR=1
MINOR=0
COMPAT=1.0
LIBNAME=dyldtest
BINNAME=binary

all: library binary

binary: binary.o
    $(CC) $< -L. -l$(LIBNAME) -o $(BINNAME)

library: library.o
    $(CC) -dynamiclib $< -Wl,-current_version,$(MAJOR).$(MINOR) \
        -Wl,-compatibility_version,$(COMPAT) -Wl,-macosx_version_min,10.6 \
        -Wl,-install_name,lib$(LIBNAME).dylib \
        -o lib$(LIBNAME).$(MAJOR).$(MINOR).dylib
    ln -f -s lib$(LIBNAME).$(MAJOR).$(MINOR).dylib \
        lib$(LIBNAME).$(MAJOR).dylib
    ln -f -s lib$(LIBNAME).$(MAJOR).dylib lib$(LIBNAME).dylib

clean:
    $(RM) *.o lib$(LIBNAME)*.dylib $(BINNAME)
4

2 回答 2

2

这是预期的行为。

执行的版本号检查dyld仅限于确保正在加载的库的兼容性版本高于构建时使用的库的兼容版本。库的当前版本是可以通过编程访问的,但dyld在评估是否应该加载特定库时不使用它。您可以通过查看手册页的-compatibility_version-current_version部分了解有关这两个版本号的更多信息。ld

您可以通过使用库的安装名称来实现您想要的效果。您可以通过查看如何libSystem.dylib使用来了解这一点:

mrowe@angara:~$ ls -lha /usr/lib/libSystem.{,B.}dylib
-rwxr-xr-x  1 root  wheel    53K Jul  9  2012 /usr/lib/libSystem.B.dylib
lrwxr-xr-x  1 root  wheel    17B Jul  9  2012 /usr/lib/libSystem.dylib -> libSystem.B.dylib
mrowe@angara:~$ otool -L /usr/lib/libSystem.dylib | head -2
/usr/lib/libSystem.dylib:
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)
mrowe@angara:~$ 

请注意输出第二行中的安装名称如何otool指向名称由版本号限定的 dylib 的版本(在情况 B 中)。如果 Apple 要引入向后不兼容的修订版,libSystem.dylib他们可以将其放在/usr/lib/libSystem.C.dylib并更新符号链接libSystem.dylib以指向它。现有程序仍会查找,libSystem.B.dylib因为这是在链接时写入其LC_LOAD_DYLIB加载命令的安装名称。任何新链接的程序libSystem.dylib都会找到libSystem.C.dylib并将其安装名称写入其LC_LOAD_DYLIB加载命令。这样的程序将无法在缺少libSystem.C.dylib.

于 2013-04-10T06:59:57.863 回答
-1

查看动态库编程主题->“管理与依赖库的客户端兼容性”->“指定版本信息”。您可以使用主要版本和命名设置正确的兼容性。

于 2013-04-10T06:30:15.093 回答