【cmake系列使用教程】
這個系列的文章翻譯自官方cmake教程:cmake tutorial。
示例程式地址:github.com/rangaofei/t…
不會僅僅停留在官方教程。本人作為一個安卓開發者,實在是沒有linux c程式開發經驗,望大佬們海涵。教程是在macos下完成,大部分linux我也測試過,有特殊說明的我會標註出來。本教程基於cmake-3.10.2,同時認為你已經安裝好cmake。
簡介
該文章未介紹如何編譯,可以參考我的另一篇文章
用cmake交叉編譯相當簡單,基本可以達到一次編寫,每次都能執行的目的。
CMake使用toolchain來編譯,連結library和建立archives,以及其他task來驅動構建。 可用的toolchain實用程式由啟用的語言確定。 在正常版本中,CMake根據系統預設值自動確定主使用的toolchain。 在交叉編譯場景中,可以使用關於編譯器和實用程式路徑的資訊來指定toolchain檔案。
假如我們已經編寫好了自己的toolchain檔案,那麼在執行構建時新增引數-DCMAKE_TOOLCHAIN_FILE=path/to/file
即可,cmake系統會自動使用執行的toolchain.cmake檔案。
安卓平臺交叉編譯有兩種方式,一是使用ndk編譯,另一種是使用自己的工具鏈編譯,我感覺我只會ndk編譯,另一中我就不介紹了,因為我不會。
這裡介紹如何構建makefile和ninja兩種方式的交叉編譯。
變數說明
有幾個特殊的變數需要設定:
-
CMAKE_SYSTEM_NAME
編譯安卓平臺時請設定這個變數為
Android
。而且CMAKE_SYSTEM_VERSION
必須指定。 -
CMAKE_SYSTEM_VERSION
設定安卓的api level,假如未設定這個值,則會由以下兩個方式決定:
CMAKE_ANDROID_API
設定了,則使用該api levelCMAKE_SYSROOT
設定了,則使用該api level- 都沒設定,則使用ndk中最新的api levele
-
CMAKE_ANDROID_ARCH_ABI
arm64-v8a armeabi-v7a armeabi-v6 armeabi mips mips64 x86 x86_64
。 這個牛逼了,設定abi架構,假如未設定,則使用預設的armeabi
。設定了這個變數系統會自動設定CMAKE_ANDROID_ARCH
,不必手動設定。 -
CMAKE_ANDROID_NDK
這個更牛逼了,使用它來設定ndk的路徑,必須是絕對路徑,到ndk的根目錄即可。
-
CMAKE_ANDROID_NDK_DEPRECATED_HEADERS
設定為true,則會使用每個api level中已經廢棄的標頭檔案,而不會使用統一的標頭檔案。預設為false,使用統一的標頭檔案。
-
CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION
設定NDK編譯鏈的版本,假如不設定,則使用最新的。
-
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。
-
CMAKE_<LANG>_ANDROID_TOOLCHAIN_PREFIX
自動生成的,絕對路徑的字首。
-
CMAKE_<LANG>_ANDROID_TOOLCHAIN_SUFFIX
自動生成的,絕對路徑的字尾。
構建順序
- 假如設定了
CMAKE_ANDROID_NDK
,就會使用該變數指定的NDK路徑 - 假如設定了
CMAKE_ANDROID_STANDALONE_TOOLCHAIN
,而1中的變數未設定,就會使用該獨立的工具鏈編譯。 - 假如設定了
CMAKE_SYSROOT
,1、2未設定,並且路徑形式是<ndk>/platforms/android-<api>/arch-<arch>
,則相當於設定了CMAKE_ANDROID_NDK
,並且會使用該路徑的ndk。 - 假如設定了
CMAKE_SYSROOT
,1、2、3未設定,並且路徑形式是<standalone-toolchain>/sysroot
,則相當於設定了CMAKE_ANDROID_STANDALONE_TOOLCHAIN
並且使用該工具鏈編譯。 - 假如設定了
ANDROID_NDK
,1、2、3、4未設定,則相當於設定了1,並且使用該ndk。 - 假如設定了
ANDROID_STANDALONE_TOOLCHAIN
,1、2、3、4、5未設定,則相當於設定了2,並且使用該工具鏈。 - 假如設定了環境變數
ANDROID_NDK_ROOT
或者ANDROID_NDK
,1、2、3、4、5、6則相當於設定了1,並且使用NDK。 - 假如設定了
ANDROID_STANDALONE_TOOLCHAIN
,1、2、3、4、5、6、7未設定,則相當於設定了2,並且使用該工具鏈。 - 全都沒設定會報錯。
編譯方式
一般需要設定的如下:
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
複製程式碼
效果與上邊是一樣的。