1. 程式人生 > >VS2015編譯Android版Cocos專案所踩的那些坑

VS2015編譯Android版Cocos專案所踩的那些坑

微軟現在已經越來越變態了,簡直萬能了.徹底的擁抱了開源.
比如,Windows10下直接把Ubuntu變成了子系統(不是基於虛擬機器,基於容器),用起來就跟CMD一樣!
比如,VS2015直接支援Android的編譯打包.
說實話,就目前來說,VS的學習成本是最低的,雖然現在Android Studio 2.2已經支援了CMake編譯NDK原生程式碼了,但是Gradle,Ant,NDK這些學習成本太高,弄起來也稍微有點複雜,特別是,國內把谷歌牆了的情況下,它又非常的依賴網路.
我用慣了VS,VS+VA真是天生絕配.我要說明的是,我VIM也用得挺溜的,就算是開發linux程式,我編碼還是用的VS(VS+Samba+SSH).以前想,如果VS能提供全套服務,那該多好.如今,這個夢想實現了.

我的工程基礎來自於這篇文章:
Cocos2d-x Visual Studio Android Project

下載下來,然後按照教程裡面一二三的做,經過了編譯的等待之後,成功的打包出apk,燒到手機上,也毫無問題的執行成功.

這看起來是很完美,但是,它是把cocos引擎程式碼放在so裡面跟遊戲程式碼一起編譯的,真要搞起來,編譯cocos就要搞死人,這很坑.
很顯然,我需要把cocos提取出來編譯成單獨的一個靜態庫.a.
我拿so檔案稍作修改,改出了一個cocos引擎的靜態庫工程,然後編譯,一切都很順利,很正常.
然而,編譯so專案的時候,么蛾子出現!
出現無數的undefined referenced錯誤,通常來說,這都是沒有引用靜態庫導致的未找到實現程式碼的錯誤.
可是,問題是我已經引用了所有的.a檔案了,然後我納悶了很久.
突然一激靈:gcc的連結器對ld連結的檔案是有順序要求的!

因為我用VS引用.lib從來沒有說有這樣的順序問題.以為它對gcc也一樣,然而並沒有.
我立馬根據依賴關係,調整了引用的順序.(o゜▽゜)o☆[BINGO!]果然OK了!

我看了apk,比之前那個少了一半的大小,想著靜態庫的話,動態庫是選擇性的把程式碼連結進去,而沒用的程式碼拋去.想著應該沒啥問題,於是就興沖沖的燒進手機,結果懵逼了,crash了!
趕緊的VS開USB真機除錯,然後我就懵逼了:jni的入口方法:JNI_OnLoad沒有被呼叫!
難道沒有被匯出?這不應該吧?只能用nm命令檢視下了.
這時候,Windows10的子系統Ubuntu就派上了大大的用場了.我Win+R->bash,啟動了Ubuntu,然後輸入命令檢視:

尼瑪,果然!!!
我接著,試著在so裡面直接模擬呼叫了JNI_OnLoad,沒問題,除錯進去了.a裡面的程式碼塊,也就是說,連結進去了,但是,並沒有將之匯出.哪怕我強制性的設定其可見性,也是沒用的:
__attribute__ ((visibility ("default"))) jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
    JniHelper::setJavaVM(vm);

    cocos_android_app_init(JniHelper::getEnv());

    return JNI_VERSION_1_4;
} 我再一次懵逼了.
如果是這樣,那麼恐怕只有完整的連結到so才能解決問題了.
我在so工程的 連結器->高階 裡面找到了"整個存檔"這個選項,或許就是它了,我把它設定成:

然後把so工程重編譯了,看了下,so的大小這時候跟最早沒拆分的版本一樣大了.
燒進真機一除錯,果然就沒問題了.
雖然這當中折騰了我不少時間和精力,但是相對來說,VS不算折騰了.

另外,資源只是放在assets裡面,還不夠的,還需要在工程裡面引用才可以,這點有點坑。

開發環境
VS2015 Update3 cocos2d-x-3.13. apache-ant-1.9.7 jdk1.8.0_112 android-ndk-r13b
下載
cocos引擎靜態庫工程檔案,請將其解壓放置在$COCOS_ROOT()/build下,靜態庫.a檔案生成在$COCOS_ROOT()/lib下:/Files/tx7do/libcocos2d-android.zip
HelloWorld示例工程檔案:/Files/tx7do/proj.visualstudio.zip

Linux系統下 聯結器ld連結順序的總結
我所理解的jni與ndk

posted on 2017-01-01 14:40 楊粼波 閱讀(2769) 評論(0)  編輯 收藏 引用 所屬分類: C++