【iOS & Mac】使用shell腳本批量合成多個(gè).a文件為一個(gè)

先假設(shè)我有3個(gè)源文件:A、B、C,如果3個(gè)源文件分別編譯成3個(gè)靜態(tài)庫(kù),那么就會(huì)得到3個(gè).a文件,分別是A.a、B.a和C.a;這樣子在別人引用的時(shí)候需要導(dǎo)入的文件過(guò)多,那我們有沒有什么辦法可以將這些文件合并為一個(gè)lib.a文件呢?


注意,我這里說(shuō)的合并多個(gè)庫(kù)并不是指真機(jī)和模擬器版本的合并。

思路誤區(qū)

很多人覺得既然.a就是一個(gè)靜態(tài)庫(kù)文件,那么是不是把多個(gè)靜態(tài)庫(kù)文件直接合成一個(gè)文件不就OK了?
但是,事實(shí)上這是不行的。因?yàn)殪o態(tài)庫(kù)的模塊是.o文件,你合并.a進(jìn)去會(huì)導(dǎo)致無(wú)法找到符號(hào),那么這個(gè)庫(kù)就沒用了。
所以,我們需要的是把.a里的.o提取出來(lái),然后再把所有.o合并在一起,再打包成.a文件。

原理

首先,我們先認(rèn)識(shí)下gcc的幾個(gè)選項(xiàng):

  • -c表示只編譯(compile)源文件但不鏈接,會(huì)把.c或.cc的c源程序編譯成目標(biāo)文件(二進(jìn)制文件),一般是.o文件。
  • -o用于指定輸出(out)文件名。不用-o的話,一般會(huì)在當(dāng)前文件夾下生成默認(rèn)的a.out文件作為可執(zhí)行程序。
  • 在命令行中使用ar rc lib.a lib.o生成.a文件。

從這里可以看出,真正帶符號(hào)的是.o文件,而.a文件是.o文件加層殼。

其實(shí).a文件的結(jié)構(gòu)和.tar文件沒啥區(qū)別。我們可以用ar命令去做操作:

  • x命令解出來(lái)。
  • r命令將文件插入庫(kù)文件中。
  • c命令建立庫(kù)文件。
  • a命令添加。
  • u命令只將日期較新文件插入庫(kù)文件中。

更多rc命令內(nèi)容請(qǐng)參考該文章:linux ar命令用法

但是,單單使用ar命令還是不夠的。因?yàn)?code>ar命令只是把.o文件插入進(jìn)去,并沒有更新符號(hào)表,所以我們需要使用ranlib命令更新符號(hào)表。
用法很簡(jiǎn)單,ranlib 庫(kù)文件名即可,如:ranlib lib.a

更多關(guān)于ranlib命令請(qǐng)參考文章:ranlib的作用

示例

假設(shè)我有上百個(gè).a文件需要合并,如果在命令行自己敲,那不知道需要敲到什么時(shí)候了,所以我用shell來(lái)進(jìn)行批處理。代碼如下:

#!/bin/sh
#
# 批量合并多個(gè).a文件

dir_path="${HOME}/Documents/library" # ${HOME}是登錄用戶的目錄;這里先設(shè)置好需要解壓的.a文件所在的絕對(duì)路徑;根據(jù)實(shí)際情況修改
lib_path="${dir_path}/lib_folder" # 解壓.a和合成.a絕對(duì)路徑;根據(jù)實(shí)際情況修改
file_name="libxx.a" # 合成.a的名字;根據(jù)實(shí)際情況修改

#創(chuàng)建庫(kù)文件目錄
if [[ ! -d "${lib_path}" ]]
then
mkdir -p "${lib_path}" # 使用雙引號(hào)防止存在空格導(dǎo)致錯(cuò)誤
fi

cd "${lib_path}"

# 查找文件并解壓
for file in $(ls "${dir_path}"|tr " " "?") # 解決名字帶空格的問(wèn)題
do
if [[ "${file}" =~ ".a" ]]
then
ar x "${dir_path}/${file}" #解壓文件所在的路徑 如果是在上級(jí)目錄,可以用../${file}
fi
done

# 合并文件
ar cru "${file_name}" *.o
ranlib "${file_name}"

# 刪除解壓出來(lái)的文件
for file in $(ls|tr " " "?")
do
if [ "${file}" != "${file_name}" ] # 不是我們最終的.a文件,就刪掉
then
rm -f "${file}"
fi
done

# 打開文件夾
open "${lib_path}"

在這里,我假設(shè)我的.a文件都放在dir_path里,生成新的.a文件放在lib_path里,新生成的.a名字叫file_name。當(dāng)然,這3個(gè)變量都需要你根據(jù)自己的實(shí)際情況去改。
lib_path并不需要事先創(chuàng)建,我在腳本做了判斷,如果沒有該文件夾則會(huì)創(chuàng)建,并且包括其父文件夾也會(huì)創(chuàng)建。

如果腳本文件報(bào)沒權(quán)限的錯(cuò)誤,需要使用命令行來(lái)打開權(quán)限。
打開命令行,cd到腳本所在的目錄,然后執(zhí)行sudo chmod +x 腳本名即可。
腳本我做了文件名帶空格時(shí)的處理,所以無(wú)須擔(dān)心文件名有空格會(huì)導(dǎo)致錯(cuò)誤的問(wèn)題。

iOS OC Swift Flutter開發(fā)群 139322447

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者。

相關(guān)閱讀更多精彩內(nèi)容

  • 動(dòng)態(tài)鏈接,在可執(zhí)行文件裝載時(shí)或運(yùn)行時(shí),由操作系統(tǒng)的裝載程序加載庫(kù)。大多數(shù)操作系統(tǒng)將解析外部引用(比如庫(kù))作為加載過(guò)...
    小5筒閱讀 5,798評(píng)論 0 3
  • 2016年國(guó)慶假期終于把此書過(guò)完,整理筆記和體會(huì)于此。 關(guān)于書名 書名源于俄羅斯的演員斯坦尼斯拉夫斯基創(chuàng)作的《演員...
    李劍飛的簡(jiǎn)書閱讀 7,463評(píng)論 2 65
  • 少年,是一首詩(shī),是一個(gè)夢(mèng)。 少年,自以為已經(jīng)長(zhǎng)大,其實(shí)并沒有真正長(zhǎng)大;希望被理解,卻又常常得不到理解。所以在平淡的...
    流酸Fh2閱讀 233評(píng)論 0 1
  • 突然之間,暑熱消退,秋高氣爽。 然則我的腳步還留在春天里,那些花朵似乎也從未遠(yuǎn)離,我竟然能感覺到空氣中芬芳的花香四...
    楊榆閱讀 964評(píng)論 1 4
  • 個(gè)人筆記:一篇文章的標(biāo)簽不宜超三個(gè),新聞標(biāo)簽在5個(gè)以內(nèi)。搜索方式可以采用搜關(guān)鍵詞、標(biāo)簽的方法來(lái)搜索 1、每天整理網(wǎng)...
    怡怡怡怡怡寶閱讀 343評(píng)論 0 0

友情鏈接更多精彩內(nèi)容