PJSIP 【編譯多平臺支援的靜態庫】
好久沒有寫部落格了,這也算是我步入新工作後的第一篇技術博文吧。在進入新公司前,早就有了技術層進入下一個迭代的準備,但很多事情是意想不到的,就像我以 C# 程式設計師的身份面試入職的,而今卻是一個全職的 IOS 開發。從 C# 到 Objective-C 的切換,還是有不少成本的,加上今年又推出了 Swift,以後要學習的路是漫長的,其實,學習的路本身就是漫長的,不應該滿足於一個階段和特定領域。對我而言,語言的切換,已經太常見了,學習一門語言是很容易的事情,但,完全的掌握它,卻不是易事,就像去摸清一個陌生人的脾氣一樣。有點扯遠了,還是進入今天的正題吧!
PJSIP,如果你不知道它是什麼,那麼說明你無需使用它,那也就沒必要繼續看我的這篇文章了。由於專案中需要使用到 VOIP,而對比下來,使用 SIP 實現的代價是相對小的,在 Android 裡,谷歌內建了對 SIP 的支援,IOS 中就沒這麼好運了,於是乎找到了 PJSIP,這是一個純 C 的庫,實現的相當漂亮。在網路上找了很久,也沒有找到適合我這種的入門級教程,在我的摸索和努力下,終於搞出點名堂來了。那麼,恭喜你,你不用走我走過的彎路了。
下面正式開始,一步步來:
第一步:下載
首先,去官網下載原始碼,這裡推薦下載 .tar.bz2 的包,下載完成後,找到對應的目錄,用 tar 或者圖形化操作來解壓,這裡我用命令列的方式來操作:
$ tar -jxvf pjproject-2.2.1.tar.bz2
第二步:編譯
首先,要在 pjlib/include/pj/ 目錄下,建立一個 config_site.h 的檔案,切換到該目錄下,用 vi 或者 touch 一個檔案:
$ cd pjlib/include/pj/ $ vi config_site.h
按照官方的說明文件,我們檔案內容定義如下:
#define PJ_CONFIG_IPHONE 1
#include <pj/config_site_sample.h>
OK,儲存,切換回主目錄下(也就是有pjlib、pjmedia、pjnath等目錄的資料夾),這時候我們就可以編譯了,還有個前提,你必須安裝了 XCode 的 Command Line Tools(XCode –> Preferences –>Downloads)。
i386
首先編譯模擬器平臺的靜態庫,依次執行下面這三句:
$ export DEVPATH=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer $ ARCH="-arch i386" CFLAGS="-O2 -m32 -mios-simulator-version-min=5.0"LDFLAGS="-O2 -m32 -mios-simulator-version-min=5.0" ./configure-iphone $ make dep && make clean && make
OK,沒有什麼問題的話,你模擬器版本的靜態庫就編譯完成了,它們存在於:
- pjlib/lib
- pjlib-util/lib
- pjmedia/lib
- pjnath/lib
- pjsip/lib
- third_party/lib
這些,是在以後的 SIP 開發中,必須要使用到的靜態庫,目前該庫只支援模擬器(可使用 lipo –info 命令來檢視,只支援 i386),所以,我們將其拷貝出來,當然,我已經為你寫好拷貝的指令碼了:
#!/bin/bash PJLIB_PATH="./lib/$1/pjlib" PJLIB_UTIL_PATH="./lib/$1/pjlib-util" PJMEDIA_PATH="./lib/$1/pjmedia" PJNATH_PATH="./lib/$1/pjnath" PJSIP_PATH="./lib/$1/pjsip" THIRD_PARTY="./lib/$1/third_party" echo "start coping to $1" rm -rf $PJLIB_PATH rm -rf $PJLIB_UTIL_PATH rm -rf $PJMEDIA_PATH rm -rf $PJNATH_PATH rm -rf $PJSIP_PATH rm -rf $THIRD_PARTY mkdir -p $PJLIB_PATH mkdir -p $PJLIB_UTIL_PATH mkdir -p $PJMEDIA_PATH mkdir -p $PJNATH_PATH mkdir -p $PJSIP_PATH mkdir -p $THIRD_PARTY cp -r ./pjlib/lib/ $PJLIB_PATH cp -r ./pjlib-util/lib/ $PJLIB_UTIL_PATH cp -r ./pjmedia/lib/ $PJMEDIA_PATH cp -r ./pjnath/lib/ $PJNATH_PATH cp -r ./pjsip/lib/ $PJSIP_PATH cp -r ./third_party/lib/ $THIRD_PARTY echo "copy done"
將該指令碼儲存為 copylibs.sh 存放到主目錄下(你應該知道主目錄在哪吧!),然後執行:
$ ./copylibs.sh i386
如果提示許可權不夠,那麼使用 chmod 777 copylibs.sh 來賦予該檔案最大的訪問許可權,執行完後,所有生成的靜態庫,都被拷貝到主目錄下 lib 目錄中的對應位置。
armv7
下面繼續編譯 armv7 版的庫,關閉剛剛的那個控制檯,注意,是全部關閉後再進入,然後到主目錄依次執行下面的命令:
$ ARCH='-arch armv7' ./configure-iphone $ make dep && make clean && make $ ./copylibs.sh armv7
armv7s
現在編譯 armv7s 版本的庫,這次不用關閉控制檯了,直接依次執行下面的命令(有報錯誤,但都是示例專案編譯出錯,和靜態連結庫檔案沒關係):
$ ARCH='-arch armv7s' ./configure-iphone $ make dep && make clean && make $ ./copylibs.sh armv7s
arm64
最後,我們完成 arm64 版本庫的編譯:
$ ARCH='-arch arm64' ./configure-iphone $ make dep && make clean && make $ ./copylibs.sh arm64
第三步:合併靜態連結庫
好了,現在我們需要的庫都已經被拷貝到 lib 目錄下了,它目前應該是這樣的:
對的,這底下有一個 mix.sh,當然,這也是我為你寫好的指令碼:
#!/bin/bash OUPUT_PATH="./mixed/" XLIPO="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/lipo" for dir in armv7/* do LIB_NAME=${dir##*/} LIB_OUTPUT=${OUPUT_PATH}$LIB_NAME rm -rf $LIB_OUTPUT mkdir -p $LIB_OUTPUT for subdir in ${dir}/* do AFILE=${subdir##*/} ARMV7_FILE="./armv7/$LIB_NAME/$AFILE" ARMV7S_FILE="./armv7s/$LIB_NAME/$AFILE" ARM64_FILE="./arm64/$LIB_NAME/$AFILE" I386_FILE="./i386/$LIB_NAME/$AFILE" echo "start mixing file: $AFILE" ${XLIPO} -arch armv7 $ARMV7_FILE -arch armv7s $ARMV7S_FILE -arch arm64 $ARM64_FILE -arch i386 $I386_FILE -create -output ${LIB_OUTPUT}/$AFILE done done echo "all mixed done"
將上面的指令碼,儲存到 lib 目錄下 mix.sh 中,控制檯中,cd 切換到 lib 目錄下,然後執行:
./mix.sh
OK,現在一切都完成了,在 lib 目錄下會多出個 mixed 目錄,該目錄底下的所有庫,都是包含了上訴各種架構版本資訊的,可以使用 lipo 來驗證下:
注意,無論是合併還是檢視,都要使用 Xcode 下的 lipo,mac 自帶的那個 lipo 不支援。
如果你覺得,親自動手太麻煩的話,那麼這裡有一個已經幫你編譯好的版本,直接下載使用即可:
不過,我還是推薦你自己動手來一遍,自己弄出來的,使用起來才更有意思嘛,呵呵~