我正在尝试在 OS X (10.7.5) 下对共享库进行版本控制,但我无法dyld
识别最大兼容性版本(最低版本还可以)。考虑下面的测试代码和以下场景:
二进制链接到版本 1.0 的库,兼容性版本 1.0
binary
按预期工作otool -L binary
:libdyldtest.dylib (compatibility version 1.0.0, current version 1.0.0)
otool -L libdyldtest.dylib
:libdyldtest.dylib (compatibility version 1.0.0, current version 1.0.0)
库更新并重新编译,移至 2.0 版,兼容 1.0 版
binary
应该仍然可以工作,并且确实可以,因为库的兼容性已经足够老了otool -L binary
:libdyldtest.dylib (compatibility version 1.0.0, current version 1.0.0)
otool -L libdyldtest.dylib
:libdyldtest.dylib (compatibility version 1.0.0, current version 2.0.0)
库已更新并重新编译为不兼容的版本。将版本和兼容版本都设置为 3.0。二进制不重新编译。
binary
应该停止工作,因为它想要与 1.0 兼容但libdyldtest
仅与 3.0 及更高版本兼容的东西。为什么这行得通?otool -L binary
:libdyldtest.dylib (compatibility version 1.0.0, current version 1.0.0)
otool -L libdyldtest.dylib
:libdyldtest.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 binary
:libdyldtest.dylib (compatibility version 1.0.0, current version 1.0.0)
otool -L libdyldtest.dylib
:libdyldtest.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)