cmake使用教程(九)-關於安卓的交叉編譯

saka發表於2018-02-22

【cmake系列使用教程】

cmake使用教程(一)-起步

cmake使用教程(二)-新增庫

cmake使用教程(三)-安裝、測試、系統自檢

cmake使用教程(四)-檔案生成器

cmake使用教程(五)-cpack生成安裝包

cmake使用教程(六)-蛋疼的語法

cmake使用教程(七)-流程和迴圈

cmake使用教程(八)-macro和function

cmake使用教程(九)-關於安卓的交叉編譯

cmake使用教程(十)-關於file

這個系列的文章翻譯自官方cmake教程:cmake tutorial

示例程式地址:github.com/rangaofei/t…

不會僅僅停留在官方教程。本人作為一個安卓開發者,實在是沒有linux c程式開發經驗,望大佬們海涵。教程是在macos下完成,大部分linux我也測試過,有特殊說明的我會標註出來。本教程基於cmake-3.10.2,同時認為你已經安裝好cmake。

簡介

該文章未介紹如何編譯,可以參考我的另一篇文章

shell指令碼生成安卓全abi動態庫與靜態庫

用cmake交叉編譯相當簡單,基本可以達到一次編寫,每次都能執行的目的。

CMake使用toolchain來編譯,連結library和建立archives,以及其他task來驅動構建。 可用的toolchain實用程式由啟用的語言確定。 在正常版本中,CMake根據系統預設值自動確定主使用的toolchain。 在交叉編譯場景中,可以使用關於編譯器和實用程式路徑的資訊來指定toolchain檔案。

假如我們已經編寫好了自己的toolchain檔案,那麼在執行構建時新增引數-DCMAKE_TOOLCHAIN_FILE=path/to/file即可,cmake系統會自動使用執行的toolchain.cmake檔案。

安卓平臺交叉編譯有兩種方式,一是使用ndk編譯,另一種是使用自己的工具鏈編譯,我感覺我只會ndk編譯,另一中我就不介紹了,因為我不會。

這裡介紹如何構建makefile和ninja兩種方式的交叉編譯。

變數說明

有幾個特殊的變數需要設定:

  1. CMAKE_SYSTEM_NAME

    編譯安卓平臺時請設定這個變數為Android。而且CMAKE_SYSTEM_VERSION必須指定。

  2. CMAKE_SYSTEM_VERSION

    設定安卓的api level,假如未設定這個值,則會由以下兩個方式決定:

    • CMAKE_ANDROID_API設定了,則使用該api level
    • CMAKE_SYSROOT設定了,則使用該api level
    • 都沒設定,則使用ndk中最新的api levele
  3. CMAKE_ANDROID_ARCH_ABI

    arm64-v8a armeabi-v7a armeabi-v6 armeabi mips mips64 x86 x86_64。 這個牛逼了,設定abi架構,假如未設定,則使用預設的armeabi。設定了這個變數系統會自動設定CMAKE_ANDROID_ARCH,不必手動設定。

  4. CMAKE_ANDROID_NDK

    這個更牛逼了,使用它來設定ndk的路徑,必須是絕對路徑,到ndk的根目錄即可。

  5. CMAKE_ANDROID_NDK_DEPRECATED_HEADERS

    設定為true,則會使用每個api level中已經廢棄的標頭檔案,而不會使用統一的標頭檔案。預設為false,使用統一的標頭檔案。

  6. CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION

    設定NDK編譯鏈的版本,假如不設定,則使用最新的。

  7. CMAKE_ANDROID_STL_TYPE 這個牛逼了。有好幾個值:

    none No C++ Support

    system Minimal C++ without STL

    gabi++_static GAbi++ Static

    gabi++_shared GAbi++ Shared

    gnustl_static GNU libstdc++ Static

    gnustl_shared GNU libstdc++ Shared

    c++_static LLVM libc++ Static

    c++_shared LLVM libc++ Shared

    stlport_static STLport Static

    stlport_shared STLport Shared

    預設值是gnustl_static。

  8. CMAKE_<LANG>_ANDROID_TOOLCHAIN_PREFIX

    自動生成的,絕對路徑的字首。

  9. CMAKE_<LANG>_ANDROID_TOOLCHAIN_SUFFIX 自動生成的,絕對路徑的字尾。

構建順序

  1. 假如設定了CMAKE_ANDROID_NDK,就會使用該變數指定的NDK路徑
  2. 假如設定了CMAKE_ANDROID_STANDALONE_TOOLCHAIN,而1中的變數未設定,就會使用該獨立的工具鏈編譯。
  3. 假如設定了CMAKE_SYSROOT,1、2未設定,並且路徑形式是<ndk>/platforms/android-<api>/arch-<arch>,則相當於設定了CMAKE_ANDROID_NDK,並且會使用該路徑的ndk。
  4. 假如設定了CMAKE_SYSROOT,1、2、3未設定,並且路徑形式是<standalone-toolchain>/sysroot,則相當於設定了CMAKE_ANDROID_STANDALONE_TOOLCHAIN並且使用該工具鏈編譯。
  5. 假如設定了ANDROID_NDK,1、2、3、4未設定,則相當於設定了1,並且使用該ndk。
  6. 假如設定了ANDROID_STANDALONE_TOOLCHAIN,1、2、3、4、5未設定,則相當於設定了2,並且使用該工具鏈。
  7. 假如設定了環境變數ANDROID_NDK_ROOT或者ANDROID_NDK,1、2、3、4、5、6則相當於設定了1,並且使用NDK。
  8. 假如設定了ANDROID_STANDALONE_TOOLCHAIN,1、2、3、4、5、6、7未設定,則相當於設定了2,並且使用該工具鏈。
  9. 全都沒設定會報錯。

編譯方式

一般需要設定的如下:

set(CMAKE_SYSTEM_NAME Android)
set(CMAKE_SYSTEM_VERSION 21) # API level
set(CMAKE_ANDROID_ARCH_ABI arm64-v8a)
set(CMAKE_ANDROID_NDK /path/to/android-ndk)
set(CMAKE_ANDROID_STL_TYPE gnustl_static)
複製程式碼

假如不想編寫toolchain.cmake檔案,也課可以在命令列直接輸入引數來完成構建:

cmake ../src \
  -DCMAKE_SYSTEM_NAME=Android \
  -DCMAKE_SYSTEM_VERSION=21 \
  -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
  -DCMAKE_ANDROID_NDK=/path/to/android-ndk \
  -DCMAKE_ANDROID_STL_TYPE=gnustl_static
複製程式碼

效果與上邊是一樣的。

相關文章