有時我們用C/C++編寫的庫,希望可以在Android / iOS上運行, 那么將其編譯為Android/iOS的動態或靜態庫是個不錯的選擇, 這時就需要用到交叉編譯, 意思就是在*nix或win平台編譯出arm架構的庫.
方法1: 手寫編譯命令 llvm/prebuilt/<host>/bin/clang++ -o xxx a.cpp b.cpp -I../inclue -Lliblog --sysroot=./ndk <...>
這種方法對於不熟悉編譯命令的小白門檻稍高
方法2: 就是今天我們重點介紹的CMake交叉編譯
Android Studio推薦我們使用cmake, 那么怎么才能正確編譯出arm架構的so庫呢, 其實相當簡單, 我們都不需要去看cmake的官方手冊-(當然CMakeLists.txt的寫法還是要看一下). AS提供了現成的東西
1. AS隨便建個c++工程
創建好大概長這樣
build一下, 構建成功后看下這個文件 app/.cxx/cmake/debug/arm64-v8a/build_command.txt, 文件內容就是cmake編譯命令.
Executable : /Users/apple/developer/AndroidSDK/cmake/3.10.2.4988404/bin/cmake # cmake程序目錄 arguments : -H/Users/apple/development/CxxTest/app/src/main/cpp # 源碼目錄,AS特有(可選,as的cmake必要) -B/Users/apple/development/CxxTest/app/.cxx/cmake/debug/arm64-v8a # 編譯產出的臨時文件目錄, AS特有 (可選, as的cmake必要) -DCMAKE_CXX_FLAGS=-std=c++14 # c++附加的編譯參數, 這里意思采用c++14標准編譯 (可選) -DCMAKE_BUILD_TYPE=Debug # 編譯類型, Debug/Release, Release模式下so會小一點,刪除了符號表. -DCMAKE_TOOLCHAIN_FILE=/Users/apple/developer/AndroidSDK/ndk/21.3.6528147/build/cmake/android.toolchain.cmake # 工具鏈文件路徑(必要,重要) -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a # 架構類型(必要) -DANDROID_ABI=arm64-v8a # (可選) -DCMAKE_ANDROID_NDK=/Users/apple/developer/AndroidSDK/ndk/21.3.6528147 # (必要) -DANDROID_NDK=/Users/apple/developer/AndroidSDK/ndk/21.3.6528147 # (可選) -DANDROID_PLATFORM=android-19 # 最小支持版本(可選) -DCMAKE_EXPORT_COMPILE_COMMANDS=ON # 是否導出詳細編譯參數(可選) -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/Users/apple/development/CxxTest/app/build/intermediates/cmake/debug/obj/arm64-v8a # lib臨時目錄(可選) -DCMAKE_MAKE_PROGRAM=/Users/apple/developer/AndroidSDK/cmake/3.10.2.4988404/bin/ninja # 構建工具, 根據需要(可選) -DCMAKE_SYSTEM_NAME=Android # 系統名稱(必要,重要) -DCMAKE_SYSTEM_VERSION=19 # 最小支持版本(必要) -GNinja # 生成類型, ninja據說比make要快, 默認生成Makefile (可選)
jvmArgs :
Android Studio自帶的cmake程序可能是經過修改的, 它有一些特有參數, 如果不使用AS的cmake, 剛不需要這些參數
所以編譯c/c++可以這樣寫
$ mkdir -p build
$ cd build # 這樣編譯產生的臨時文件會build目錄, 不會污染源碼git
$ cmake ../src \ -DCMAKE_SYSTEM_NAME=Android \ -DCMAKE_SYSTEM_VERSION=19 \ -DANDROID_PLATFORM=android-19 \ -DCMAKE_ANDROID_STL_TYPE=c++_static \ #c++_static會將c++庫一起打進目標, 如果不需要這樣可以換成c++_shared, 默認就是c++_static -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_TOOLCHAIN_FILE=$CMAKE_TOOL_CHAIN \ -DCMAKE_ANDROID_NDK=$NDK_HOME \ -DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a
$ make -j8 # 即可編譯出最終產物
我們甚至都不需要手動去處理include/library包含目錄, cmake都幫我們做了, 是不是超簡單
參考: