Xcode 依賴管理帶來的靜態庫動態庫分析

2021-07-13 18:28:35 字數 3139 閱讀 3358

最近整理一些專案以前依賴留下的問題,在使用 cocoapods 和 carthage 的時候引出了關於靜態庫和動態庫的思考,手動編譯靜態庫的朋友應該知道,如果自己編譯了乙個靜態庫,這個靜態庫依賴了 ios 自帶的庫,即使你在

xcode

開發工具

中顯式指定了依賴,當你在另乙個工程中使用這個靜態庫的時候,依舊需要顯式在那個工程指定這個靜態庫所依賴的系統庫。

舉個栗子

afnetworking 是個好東西,大家都喜歡用,在日常使用的時候,一般都是使用 cocoapods 引入這個庫,筆者前面有篇文章分析了 cocoapods 做了什麼工作,但是卻沒有分析 cocoapods 為何如此設計,這裡先賣個關子不講。afnetworking 依賴

security.framework

mobilecoreservices.frameworksystemconfiguration.framework 三個系統框架,如果我們將其編譯為靜態庫,然後這個靜態庫被其他工程依賴,那麼其他工程依舊需要引入這三個框架。如果我們將其編譯為動態庫,則不需要依賴這三個框架。這個情況引起了筆者的興趣 分析

模擬靜態庫的編譯

建立乙個動態庫用於模擬系統庫

dynamic.h

----------void hello();

dynamic.c

----------#include "dynamic.h"#include

void hello()

然後編譯打包動態庫

> gcc -c -o dynamic.o dynamic.c # 編譯為物件檔案

> gcc -shared dynamic.o -o libdynamic.so

建立乙個靜態庫用於模擬第三方靜態庫

static.h

--------void sayhello();

static.c

--------#include "static.h"#include "dynamic.h"

void sayhello()

然後編譯靜態庫

> gcc -c -o static.o static.c

> ar -r libstatic.a static.o

這裡大家有沒有發現乙個問題,靜態庫實際上並沒有鏈結動態庫,僅僅只是 include 了乙個標頭檔案用於編譯通過。最終生成的靜態庫根本不知道動態庫的存在。然後建立乙個帶有main 函式的程式

hello.c

-------#include "static.h"int main(int argc, char *argv)

然後編譯

> gcc -o hello hello.c -l. -lstatic# 直接報錯沒有找到 hello() 的二進位制**

undefined symbols for architecture x86_64:

"_hello", referenced from:

_sayhello in libstatic.a(static.o)

ld: symbol(s) not found for architecture x86_64

clang: error: linker command failed with exit code 1 (use -v to see invocation)

模擬動態庫的編譯

建立乙個動態庫用於模擬系統庫

dynamic1.h

----------void hello();

dynamic1.c

----------#include "dynamic1.h"#include

void hello()

然後編譯打包動態庫

> gcc -c -o dynamic1.o dynamic1.c # 編譯為物件檔案

> gcc -shared dynamic1.o -o libdynamic1.so

建立動態庫用於模擬第三方動態庫

dynamic2.h

--------void sayhello();

dynamic2.c

--------#include "dynamic2.h"#include "dynamic1.h"

void sayhello()

然後編譯打包動態庫

> gcc -c -o dynamic2.o dynamic2.c # 編譯為物件檔案

> gcc -shared dynamic2.o -o libdynamic2.so# 報錯,顯示 dynamic2.o 中沒有 hello() 二進位制**

undefined symbols for architecture x86_64:

"_hello", referenced from:

_sayhello in dynamic2.o

ld: symbol(s) not found for architecture x86_64

clang: error: linker command failed with exit code 1 (use -v to see invocation)

> gcc -shared dynamic2.o -o libdynamic2.so -l. -ldynamic1# 成功,無報錯

然後建立乙個帶有 main 函式的程式

hello.c

-------#include "static.h"int main(int argc, char *argv)

然後編譯

> gcc -o hello hello.c -l. -ldynamic2

總結 從上面兩個編譯過程大家應該也能明白了,靜態庫實際上只是物件檔案的打包,也就是說,只經過了編譯過程,而沒有鏈結過程,編譯乙個靜態庫甚至只需要滿足所有函式的宣告就行,而動態庫雖然沒有經過正規的鏈結,但是實際上還是通過 gcc 做了跟其他動態庫的鏈結,動態庫自身有了依賴的概念。所以不需要在工程中顯式依賴了。這裡可能有朋友想要問,這種知識有什麼用處?實際上這種知識在依賴管理中有用,前面說過 cocoapods 對工程修改了很多內容,這是有原因的,因為 ios8 之前是不存在動態庫的,只存在靜態庫,cocoapods 不得不對目標工程也作出修改來新增對其他庫的依賴,因為靜態庫不知道自身依賴什麼庫。而 carthage 則只支援 ios8 和動態庫,所以完全可以沒有侵入性,只需要提供乙個動態庫,然後工程依賴這個動態庫就行了。

vc的靜態庫依賴

技術部落格 vc編譯的靜態庫.lib檔案是一系列.obj檔案的集合,這點和linux系統上的靜態庫一致,但是vc的靜態庫有乙個獨有的功能,強制這個靜態庫的使用者必須鏈結某個庫。這點在靜態庫已經有很複雜的依賴關係或者需要強制鏈結某個版本的庫時及其有用。否則,如果靜態庫中用到了其他的庫,需要這個靜態庫的...

Xcode中聯調靜態庫工程

對於靜態庫的使用,只需要把.h和.a加進來就可以了,但是在除錯階段,能把庫工程新增進來可以打斷點除錯還是很重要的,下面介紹新增靜態庫工程聯調的方法 1.在frameworks束下,通過add files to 把靜態庫工程的.xcodeproj工程檔案add進來,加進來之後如下圖,要是沒加好的話,s...

Xcode 之自己編譯靜態庫

今天介紹下,如何利用xcode,新建乙個靜態庫,以及如何編譯成i386 armv7 armv7s 等平台架構。開發環境 mac os x 10.9.4 xcode 5.0.2 一 新建靜態庫 1,開啟xcode,create a new xcode project framework library...