[英]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.