1. 程式人生 > >Android.mk 連結庫時undefined reference to的錯誤處理

Android.mk 連結庫時undefined reference to的錯誤處理

我們在編譯Android JNI的時候,經常要連結一些其他的開源庫,總是會碰到undefined reference to的問題。

一般編譯器報 “undefined reference to”的錯誤是以下幾種情況。

1 沒有指定對應的庫(.o/.a/.so) 

使用了庫中定義的實體,但沒有指定庫(-lXXX)或者沒有指定庫路徑(-LYYY),會導致該錯誤, 

在Android.mk中 用LDFLAGS引數來定義庫(-lXXX)和 (-LYYY)的

例如:當前模組編譯,依賴於 libxxx, libxxx2庫,但是 libxxx 又依賴於 libxxx2, 這種情況時 需要對依賴的庫的順序進行調整LOCAL_STATIC_LIBRARIES := \
    ...    libxxx \    libxxx2 \
2 連線庫引數的順序不對 

在預設情況下,對於-l 使用庫的要求是越是基礎的庫越要寫在後面,無論是靜態還動態 

在實際使用的過程中,發現-D引數的使用,也會導致undefined reference to”的錯誤,推薦大家如果想在做巨集控制的時候,把-D引數放到最後

3 gcc/ld 版本不匹配 
gcc/ld的版本的相容性問題,由於gcc2 到 gcc3大版本的相容性存在問題(其實gcc3.2到3.4也一定程度上存在這樣的問題) 當在高版本機器上使用低版本的機器就會導致這樣的錯誤, 這個問題比較常見在32位的環境上, 另外就在32位環境不小心使用了64位的庫或者反過來64位環境使用了32位的庫. 

這個問題與Linux下幾乎一樣

4 C/C++相互依賴和連結 
gcc和g++編譯結果的混用需要保證能夠extern "C" 兩邊都可以使用的介面,在我們的64位環境中gcc連結g++的庫還需要加上 -lstdc++,具體見前文對於混合編譯的說明 。用JNI連結純C語言的庫,extern "C" 必須要包含標頭檔案。例如:在 .h 中新增下面程式碼進行包裹:#ifdef __cplusplusextern "C" {#endif
xxx code
#ifdef __cplusplus}#endif
5 執行期報錯 

這個問題基本上是由於程式使用了dlopen方式載入.so, 但.so沒有把所有需要的庫都連結上,具體參加上文中對於靜態庫和動態庫混合使用的說明 

關於執行時動態連結的問題,碰到過很糾結的情況,就是在Android連結的庫依賴於我現在當前的庫,就變成了你連結我,我再連結你,導致死都編不過,最好撇清這種關係.

當然這種雙向依賴的問題也可以解決。還有一種更簡單的方法就是在Android.mk中加入LOCAL_ALLOW_UNDEFINED_SYMBOLS := true一句話就可以搞定,忽略連結錯誤,但是在執行中可能會出現錯誤,因為庫檔案找不到依賴的檔案就會報錯。

ps:是一種解決方案,但並不適用所有的問題,還是要具體問題具體分析