iT邦幫忙

2023 iThome 鐵人賽

DAY 12
0

在上一篇I7565H1/H2 SDK的檔案架構中有一個現象,lib資料夾中動態庫(.so)旁邊都有一個箭頭指向該檔案,靜態庫(.a)卻沒有,這個現象就和動態庫的版本號有關。

// I7565H1/H2 SDK 的 lib 資料夾部份內容
├── lib
│   ├── libI7565H1H2_64.a
│   ├── libI7565H1H2_64.so -> ../lib/libI7565H1H2_64.so.1
│   ├── libI7565H1H2_64.so.1 -> ../lib/libI7565H1H2_64.so.1.0
│   ├── libI7565H1H2_64.so.1.0
│   ├── libI7565H1H2.a
│   ├── libI7565H1H2_arm.a
│   ├── libI7565H1H2_arm.so -> ../lib/libI7565H1H2_arm.so.1
│   ├── libI7565H1H2_arm.so.1 -> ../lib/libI7565H1H2_arm.so.1.0
│   ├── libI7565H1H2_arm.so.1.0
│   ├── libI7565H1H2.so -> ../lib/libI7565H1H2.so.1

什麼是版本號?
一個箭頭指向動態庫的行為是什麼?
為什麼靜態庫並沒有版本號呢?
以上問題都會在接下來的文章中解答。

版本號簡介

庫更新後,發布的版本號碼可以分為三類:

  1. 主要(Major)版本:對接口或使用方法進行向後不兼容的更改。
  2. 次要(Minor)版本:新增接口或內容。
  3. 補丁(Patch):修正錯誤或優化程式碼。

以常用的程式庫OpenCV為例,都遵循著[主版本號.次要版本號.補丁]格式來發布程式庫版本。
https://ithelp.ithome.com.tw/upload/images/20230926/20162026RwKpuzy9iE.png

  • 一個箭頭指向動態庫的行為是什麼?

在Linux中,這個行為就是軟鍊結(Wiki),動態庫的版本實現機制就是透過軟鍊結來實現的。

// 以這個檔案架構為例
├── libmysqrt.so -> libmysqrt.so.1
├── libmysqrt.so.1 -> libmysqrt.so.1.1.0
└── libmysqrt.so.1.0.0

比如說當程式想要鍊結 mysqrt 這個動態庫,那鍊結器會到指定的目錄去搜尋 mysqrt 這個庫的 SONAME ,也就是 libmysqrt.so 這個檔案,而 libmysqrt.so 指向 libmysqrt.so.1 , libmysqrt.so.1 又指向 libmysqrt.so.1.0.0 因此最後鍊結到的動態庫就是 libmysqrt.so.1.0.0 。

  • 為什麼要搞的這麼麻煩?一開始直接鍊結到 libmysqrt.so.1.0.0 不就好了?

這樣就可以在不更改主程式的鍊結方式或程式碼的狀態下更新函式庫了!因為鍊結器只知道要鍊結到函式庫的 SONAME ,所以只要在更新動態庫的時候一起更改軟鍊結鍊結到的檔案,就可以實現動態庫最方便的特點之一 修改/升級庫程式後,不需要重新編譯/鏈接整個應用程式
如果對上述的說明不是很理解也沒關係,明天就會開始實際操作如何更新動態庫啦!

  • 那為什麼動態庫有版本號,靜態庫沒有呢?

因為靜態庫的特性是在編譯時就和其他檔案一起鍊結成執行檔,而動態庫是在運行時才去庫存放的資料夾中尋找所需的檔案,因此就可以實現一個非常方便的功能--動態庫更新時,使用到該動態庫的程式不需要重新編譯。
因為一個大型專案要重新編譯會耗費非常多的時間,而且專案可以和庫分別獨立開發,只要將新版本動態庫安裝到指定目錄或系統目錄就行了,專案可以立刻享受新版本的功能。

  • 那在動態庫進行兼容更新時需要刪除原本舊有的庫嗎?

答案是不用,因為動態庫有版本號這個機制,讓專案在使用時能夠永遠指向最新版本。
但是能夠不重新編譯整個專案有一個重要的前提,就是ABI(Application Binary Interface)二進制檔接口必須要相同,因此在發布之前需要 ABI Compliance Checker來檢查ABI是否一致。
會改變ABI導致向後不兼容的行為通常有以下幾點:

  • 導出函數行為改變
  • 導出函數被刪除
  • 導出數據的結構(struct)改變
  • 導出函數的接口發生變化,如輸入參數和返回直被更改

之後會有範例來說明 ABI 與 如何使用 ABI Checker。

Reference

書籍:程序员的自我修养—链接、装载与库
Dynamic linking best practices

Creating Dynamic Libraries
ABI Policy and Guidelines


上一篇
[Day 11] 庫的實際應用經驗--使用別人的庫
下一篇
[Day 13] 實際操作動態庫的版本號
系列文
建構屬於自己的C/C++專案 : 我的30天CMake學習之旅29
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言