1、linux中靜態庫和動態庫區別:
庫從本質上來說是一種可執行代碼的二進制格式,可以被載入內存中執行。庫分靜態庫和動態庫兩種。
靜態庫:這類庫的名字一般是libxxx.a;利用靜態函數庫編譯成的文件比較大,因為整個函數庫的所有數據都會被整合進目標代碼中,他的優點就顯而易見了,即編譯後的執行程序不需要外部的函數庫支持,因為所有使用的函數都已經被編譯進去了。當然這也會成為他的缺點,因為如果靜態函數庫改變了,那麼你的程序必須重新編譯。
動態庫:這類庫的名字一般是libxxx.so;相對於靜態函數庫,動態函數庫在編譯的時候 並沒有被編譯進目標代碼中,你的程序執行到相關函數時才調用該函數庫裡的相應函數,因此動態函數庫所產生的可執行文件比較小。由於函數庫沒有被整合進你的程序,而是程序運行時動態的申請並調用,所以程序的運行環境中必須提供相應的庫。動態函數庫的改變並不影響你的程序,所以動態函數庫的升級比較方便。
2、iOS開發中靜態庫和動態庫區別:
靜態庫和動態庫是相對編譯期和運行期的:靜態庫在程序編譯時會被鏈接到目標代碼中,程序運行時將不再需要改靜態庫;而動態庫在程序編譯時並不會被鏈接到目標代碼中,只是在程序運行時才被載入,因為在程序運行期間還需要動態庫的存在。
靜態庫 好處:
i.模塊化,分工合作,提高了代碼的復用及核心技術的保密程度
ii.避免少量改動經常導致大量的重復編譯連接
iii.也可以重用,注意不是共享使用
動態庫 好處:
i.使用動態庫,可以將最終可執行文件體積縮小,將整個應用程序分模塊,團隊合作,進行分工,影響比較小
ii.使用動態庫,多個應用程序共享內存中得同一份庫文件,節省資源
iii.使用動態庫,可以不重新編譯連接可執行程序的前提下,更新動態庫文件達到更新應用程序的目的。
iv.應用插件化
v.軟件版本實時模塊升級
vi.共享可執行文件 在其它大部分平台上,動態庫都可以用於不同應用間共享,這就大大節省了內存。從目前來看,iOS仍然不允許進程間共享動態庫,即iOS上的動態庫只能是私有的,因為我們仍然不能將動態庫文件放置在除了自身沙盒以外的其它任何地方。 不過iOS8上開放了App Extension功能,可以為一個應用創建插件,這樣主app和插件之間共享動態庫還是可行的。
3、Xcode創建靜態庫
打開Xcode, 選擇File ----> New ---> Project。 新建工程。 選擇iOS ----> Framework & Library ---> Cocoa Touch Static Library。 點擊Next。創建工程:
新增2個類作為我們的一個靜態類文件:
其中LogLib.h的代碼如下:(作為公開存在)
LogLib.m實現方法如下,變成靜態庫後該文件隱藏:
然後選擇真機進行靜態庫的創建:(command + B)
這個時候會出現如下的錯誤提示:
按照錯誤的提示得知我們需要在iOS8.1下build需要選擇證書:
好了,在Product下會存在libStaticLib.a文件:
這只是真機下的一個靜態庫,同樣選擇模擬器,command + B,生成模擬器下的靜態庫。
找到這2個新建的靜態庫文件:
分別用2個.a加入到其他項目在不同運行壞境選擇不同的.a靜態庫明顯不明智,打開終端,輸入以下命令行進行整合:
lipo -create 真機.a路徑 模擬器.a路徑 -output 整合的.a路徑
lipo -create /Users/fangdd/Library/Developer/Xcode/DerivedData/StaticLib-ercfdooewtvlxmakqvyxkohcagph/Build/Products/Debug-iphoneos/libStaticLib.a /Users/fangdd/Library/Developer/Xcode/DerivedData/StaticLib-ercfdooewtvlxmakqvyxkohcagph/Build/Products/Debug-iphonesimulator/libStaticLib.a -output /Users/fangdd/Desktop/staticLib.a
會在 整合的.a路徑下找到合體的靜態庫。
將生產的靜態庫及相應的頭文件加入到我們的測試項目中,運行得到:
完畢.
4、Xcode創建動態庫
打開Xcode, 選擇File ----> New ---> Project。 新建工程。 選擇iOS ----> Framework & Library ---> Cocoa Touch Framework。 點擊Next。創建工程:
命名為DymicLib:
同樣的添加新的2個類作為測試:
將頭文件作為公共的頭文件,提供給外部調用:
運行後變生成了一個動態庫,找到Product下的DymicLib.framework所在的目錄:
注意這個只是運行壞境下的動態庫(模擬器和真機),下面建立新的TARGETS:命名為CommonDymicLib:
將之前生成的DymicLib加入到新的CommonDymicLib中:
為CommonDymicLib添加新的腳本來實現模擬器和真機合並:
腳本如下:
# Sets the target folders and the final framework product. FMK_NAME=${PROJECT_NAME} # Install dir will be the final output to the framework. # The following line create it in the root folder of the current project. INSTALL_DIR=${SRCROOT}/Products/${FMK_NAME}.framework # Working dir will be deleted after the framework creation. WRK_DIR=build DEVICE_DIR=${WRK_DIR}/Release-iphoneos/$ {FMK_NAME}.framework SIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.framework # -configuration ${CONFIGURATION} # Clean and Building both architectures. # 分別編譯生成真機和模擬器使用的framework xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphoneos clean build xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphonesimulator clean build # Cleaning the oldest. if [ -d "${INSTALL_DIR}" ] then rm -rf "${INSTALL_DIR}" fi mkdir -p "${INSTALL_DIR}" cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/" # Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product. # 使用lipo命令將其合並成一個通用framework # 最後將生成的通用framework放置在工程根目錄下新建的Products目錄下 lipo -create "${DEVICE_DIR}/${FMK_NAME}" "${SIMULATOR_DIR}/${FMK_NAME}" -output "${INSTALL_DIR}/${FMK_NAME}" rm -r "${WRK_DIR}"
選擇iOS Device運行:
找到生成的CommonDymicLib下的動態庫DymicLib.framework:
在測試項目中將DymicLib.framework加入:
運行即可!
心得:這個時候所謂的動態庫其實意義就是升級版的靜態庫,因為動態庫使用的前提是項目在發布前添加到項目中,這和我們所謂的插件(即插即用,隨時在自己的服務器上下載一個動態庫運行,而不需要重新打包,我們可以選擇在需要的時候再加載動態庫)完全是兩碼事。
插件實現方式:使用dlopen加載動態庫,動態庫中真正的可執行代碼為DymicLib.framework/DymicLib文件,因此使用dlopen時如果僅僅指定加載動態庫的路徑為DymicLib.framework是沒法成功加載的。將我們創建的動態庫放在我們的服務器,項目上線後再下載這個動態庫到我們的Documents文件夾中,使用如下代碼動態使用動態庫:
#import NSString *documentsPath = [NSString stringWithFormat:@"%@/Documents/DymicLib.framework/DymicLib",NSHomeDirectory()]; void * libHandle = NULL; libHandle = dlopen([documentsPath cStringUsingEncoding:NSUTF8StringEncoding], RTLD_NOW); if (libHandle == NULL) { char *error = dlerror(); NSLog(@"dlopen error: %s", error); } else { NSLog(@"dlopen load framework success."); }
使用 動態庫 中的類:
Class rootClass = NSClassFromString(@"DymicLog"); if (rootClass) { id object = [[rootClass alloc] init]; [(DymicLog *)object relog:@"hello world"]; }