[英]Library versioning on Mach-O platforms
当SOVERSION
目标属性的文档提到在Mach-O系统(例如OS X和iOS)上,它对应于“兼容版本”,而VERSION
对应于“当前版本”。
在Linux上,它与VERSION 5.4.2
和SOVERSION 5
类似,表明该库与5.0版及更高版本兼容,并且VERSION
在Windows上以<major>.<minor>
形式用作DLL映像版本(I我不确定SOVERSION
在Windows上有何不同)。
但是, 文档中所引用的FRAMEWORK
目标属性的示例说明了如何在Mach-O平台上VERSION 16.4.0
和SOVERSION 1.0.0
(我对构建框架不感兴趣,只是想知道外部版本控制方案。)
在Mach-O世界中版本控制是如何工作的? 如果删除某些功能(如果会破坏兼容性),我习惯于碰到主要版本,那么16.4.0版的库如何与该库的1.0.0版保持兼容? “兼容”是什么意思?
首先,只是为了解决这个问题,框架只是被命名为Something.framework/Something
而不是libsomething.dylib
。 但是,文件格式完全相同,因此在本篇文章中,我仅将它们称为dylib。
现在,让我们从mach-o/loader.h
标头(Mach-O文件格式的实际权威源)摘录开始:
/*
* Dynamicly linked shared libraries are identified by two things. The
* pathname (the name of the library as found for execution), and the
* compatibility version number. The pathname must match and the compatibility
* number in the user of the library must be greater than or equal to the
* library being used. The time stamp is used to record the time a library was
* built and copied into user so it can be use to determined if the library used
* at runtime is exactly the same as used to built the program.
*/
struct dylib {
union lc_str name; /* library's path name */
uint32_t timestamp; /* library's build time stamp */
uint32_t current_version; /* library's current version number */
uint32_t compatibility_version; /* library's compatibility vers number*/
};
/*
* A dynamically linked shared library (filetype == MH_DYLIB in the mach header)
* contains a dylib_command (cmd == LC_ID_DYLIB) to identify the library.
* An object that uses a dynamically linked shared library also contains a
* dylib_command (cmd == LC_LOAD_DYLIB, LC_LOAD_WEAK_DYLIB, or
* LC_REEXPORT_DYLIB) for each library it uses.
*/
struct dylib_command {
uint32_t cmd; /* LC_ID_DYLIB, LC_LOAD_{,WEAK_}DYLIB,
LC_REEXPORT_DYLIB */
uint32_t cmdsize; /* includes pathname string */
struct dylib dylib; /* the library identification */
};
如评论中所述, struct dylib
既嵌入在库中,又嵌入到与其链接的二进制文件中,都包含current_version
和compatibility_version
的副本。 后者的工作方式已在此处进行了说明,但前者未解决。
可以在dyld
手册页上找到有关该文档的信息(源在这里 ,但是在man
之外看起来并不漂亮):
DYLD_VERSIONED_FRAMEWORK_PATH
This is a colon separated list of directories that contain potential override frame-
works. The dynamic linker searches these directories for frameworks. 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 is the supplied framework is newer.
Note: dyld does not check the framework's Info.plist to find its version. Dyld only
checks the -current_version number supplied when the framework was created.
[...]
DYLD_VERSIONED_LIBRARY_PATH
This is a colon separated list of directories that contain potential override
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.
简而言之:
compatibility_version
用于确定库是否对于要加载的二进制文件来说“足够新”。 current_version
选择库。 关于您对当前版本为16.4.0
与1.0.0
兼容版本的困惑:从某些资料来源看 ,只要引入任何功能,Apple似乎16.4.0
主要版本,并使用次要版本( s)仅适用于错误修复,即AFAIK。
所以他们称之为16.4.0
,我可能会称之为1.16.4
。 ;)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.