当SOVERSION目标属性的文档提到在Mach-O系统(如OS和iOS )上,它对应于“兼容性版本”,而VERSION对应于“当前版本”时,我正在研究一个小型个人项目的共享库。
在Linux上,它只是一些类似于VERSION 5.4.2和SOVERSION 5的东西,表明库与版本5.0及更高版本兼容,VERSION作为<major>.<minor>表单中的<major>.<minor>映像版本在Windows上使用(我不知道SOVERSION在Windows上有什么不同)。
然而,目标属性中的示例说明了如何在Mach-O平台上使用VERSION 16.4.0和SOVERSION 1.0.0 (我对构建框架并不感兴趣,只是想知道国外的版本控制方案)。
在Mach-O世界中,版本控制是如何工作的?如果我删除一些功能(这将是兼容性中断),那么我习惯于仅仅删除主要版本,那么如何使16.4.0版本的库与库的1.0.0版本保持兼容呢?“兼容”是什么意思?
发布于 2018-08-28 16:51:31
首先,为了避免这种情况,框架只是名为Something.framework/Something而不是libsomething.dylib的dylibs。但是文件格式是完全相同的,所以在这篇文章中,我将简单地将它们称为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的混淆:从一些来源的角度来看,苹果似乎在有任何特性引入的时候,都会把主要的版本撞上,并且只使用次要版本来修复bug,AFAIK。
所以他们所说的16.4.0,我可能会叫1.16.4。;)
https://stackoverflow.com/questions/51940963
复制相似问题