獨立工具鏈 (已淘汰)

您可以單獨使用 Android NDK 提供的工具鏈,也可以將此工具鏈做為外掛程式與現有 IDE 搭配使用。如果您已經有自己的建構系統,而且只需要叫用跨平台程式碼編譯器,以便為其新增對 Android 的支援,這樣的靈活彈性便對您很有幫助。

選取您的工具鏈

首先,您需要決定獨立工具鏈的目標處理器架構。您可以使用 --arch 旗標完成這項操作。

選取您的 sysroot

接下來,您需要定義 sysroot。sysroot 是包含目標系統標頭和程式庫的目錄。如要定義 sysroot,您必須知道原生支援的目標 Android API 級別;具體可用的原生 API 會因 Android API 級別而異。

$NDK/platforms/ 下有不同 Android API 級別的原生 API 程式庫;每個 API 級別目錄包含不同 CPU 和架構的子目錄。標頭位於 $NDK/sysroot 中。

如要進一步瞭解 Android API 級別,以及各級別支援的對應原生 API,請參閱原生 API

建立工具鏈

NDK 提供 make_standalone_toolchain.py 指令碼,可讓您透過指令列執行自訂工具鏈的安裝作業。

這是用於取代舊版 make-standalone-toolchain.sh 的新工具。此工具已在 Python 中重新實作,因此 Windows 使用者不需安裝 CygwinMSYS,即可使用這個工具。

指令碼位於 $NDK/build/tools/ 目錄,其中 $NDK 是 NDK 的安裝根目錄。

以下是使用此指令碼的範例:

$NDK/build/tools/make_standalone_toolchain.py \
    --arch arm --api 21 --install-dir /tmp/my-android-toolchain

此指令建立名為 /tmp/my-android-toolchain/ 的目錄,其中包含 android-21/arch-arm sysroot 的副本,以及 32 位元 ARM 目標的工具鏈二進位檔的副本。

請注意,此工具鏈二進位檔並未相依於或包含主機專屬路徑。也就是說,您可以在任何位置安裝這些檔案,或視需要移動檔案位置。

--arch 引數是必要項,但 API 級別預設會使用指定架構支援的最低級別 (目前 32 位元架構支援的最低級別為 16,64 位元架構支援的最低級別則為 21)。

自 r18 起,所有獨立工具鏈都會使用 Clang 和 libc++。除非建構靜態執行檔,否則預設使用 libc++ 共用程式庫。如要強制使用靜態程式庫,請在連結時傳遞 -static-libstdc++。此行為與一般主機工具鏈的行為相符。

正如 C++ 程式庫支援中所述,在連結 libc++ 時,通常需要傳遞 -latomic

請注意,如果省略 --install-dir 選項,此工具會在目前的目錄中建立名為 $TOOLCHAIN_NAME.tar.bz2 的 tarball。您可以使用 --package-dir 將 tarball 放入其他目錄。

如需瞭解更多選項和相關詳細資訊,請使用 --help

使用 Clang

獨立工具鏈中會自動加入 Clang 二進位檔。

<install-dir>/bin 下另有兩個名為 clangclang++ 的包裝函式指令碼。這些指令碼會叫用具有正確目標架構旗標的 clang 二進位檔。也就是說,這些指令碼不需要任何修改就能運作,而且只要設定它們的 CCCXX 環境變數,應該就能在建構作業中使用這些指令碼。

此外,名為 gccg++ 的包裝函式指令碼也會呼叫 Clang。 雖然 NDK 不再包含 GCC,但是這些指令碼還是會在一定程度上與明確參照 GCC 的建構檔案相容。很明顯地,如果建構檔案使用 Clang 不支援的指令列選項,您必須移除或替換這些選項。

Clang 以 ARM 為目標

為 ARM 建構時,Clang 會根據是否有 -march=armv7-a 和/或 -mthumb 編譯器旗標來變更目標:

表 1. 可指定的 -march 值及其產生的目標。

-march 產生的目標
-march=armv7-a armv7-none-linux-androideabi
-mthumb thumb-none-linux-androideabi
-march=armv7-a-mthumb thumbv7-none-linux-androideabi

此外,您可視需要覆寫為自己的 -target

clangclang++ 應能輕鬆地替換 makefile 中的 gccg++。如有疑慮,請在叫用編譯器時使用下列選項,驗證編譯器能否正常運作:

  • -v:用於傾印與編譯器驅動程式問題相關的指令
  • -###:用於傾印指令列選項,包括透過隱含方式預先定義的選項。
  • -x c < /dev/null -dM -E:用於傾印預先定義的前置處理器定義
  • -save-temps:用於比較 *.i*.ii 預先處理的檔案。

ABI 相容性

根據預設,ARM Clang 獨立工具鏈的目標會是 armeabi-v7a ABI。 如要覆寫此目標,傳遞適當的 -march-target 選項即可。

建議使用 -mthumb 編譯器旗標來強制產生 16 位元 Thumb-2 指令。如果已省略此指令,工具鏈將發出 32 位元 ARM 指令。

如要使用 NEON 指令,您必須使用 -mfpu 編譯器旗標 -mfpu=neon

請注意,根據 ARM 的規範,這項設定會強制使用 VFPv3-D32

此外,請務必為連結器提供 -march=armv7-a -Wl,--fix-cortex-a8 這兩個旗標。

第一個旗標指示連結器挑選 armv7-a 專屬的工具鏈程式庫。在某些 Cortex-A8 實作中,需要採用第二個旗標做為 CPU 錯誤的解決方法。

如果將其他 ABI 設為目標,則無須使用任何特定的編譯器旗標。

如要進一步瞭解 ABI 支援,請參閱 Android ABI

警告與限制

Windows 支援

Windows 二進位檔並未相依於 Cygwin。這種沒有依附元件的特性讓此類檔案的執行速度更快。然而,代價是 Windows 二進位檔無法像理解 C:/foo/bar 一樣,理解 Cygwin 路徑規範 (例如 cygdrive/c/foo/bar)。

例外狀況、RTTI 及 STL

根據預設,工具鏈二進位檔支援 C++ 例外狀況和 RTTI。如要在建構原始碼時停用 C++ 例外狀況和 RTTI (例如產生更輕量的機器碼),請使用 -fno-exceptions-fno-rtti

C++ STL 支援

獨立工具鏈包含 C++ 標準範本程式庫 (STL) 實作。

  • 使用 -static-libstdc++ 取得靜態程式庫版本的 libc++。這麼做可確保您的最終二進位檔中含有所有必要的 C++ STL 程式碼。如果您按照我們的建議,只產生單一共用程式庫或執行檔,則這個方法是您的理想選擇。

  • 根據預設,系統會使用共用程式庫版本的 libc++。不需要額外的旗標就能連結至共用程式庫。您必須封裝應用程式中的 libc++_shared.so,否則系統將無法載入程式碼。

    表 2 列出此檔案在不同架構中的位置。

    表 2. 可指定的 -march 值及其產生的目標。

    工具鏈 位置
    arm $TOOLCHAIN/arm-linux-androideabi/lib/
    arm64 $TOOLCHAIN/aarch64-linux-android/lib/
    x86 $TOOLCHAIN/i686-linux-android/lib/
    x86_64 $TOOLCHAIN/x86_64-linux-android/lib/

使用獨立工具鏈建構開放原始碼專案

以下是工具鏈範例:

# Create an arm64 API 26 libc++ toolchain.
$NDK/build/tools/make_standalone_toolchain.py \
  --arch arm64 \
  --api 26 \
  --install-dir=my-toolchain

以下示範如何設定環境,以便建構傳統開放原始碼專案:

# Add the standalone toolchain to the search path.
export PATH=$PATH:`pwd`/my-toolchain/bin

# Tell configure what tools to use.
target_host=aarch64-linux-android
export AR=$target_host-ar
export AS=$target_host-clang
export CC=$target_host-clang
export CXX=$target_host-clang++
export LD=$target_host-ld
export STRIP=$target_host-strip

# Tell configure what flags Android requires.
export CFLAGS="-fPIE -fPIC"
export LDFLAGS="-pie"

具有自訂建構系統的專案

以下範例展示在完成上述步驟後,如何建構 toybox:

git clone https://github.com/landley/toybox.git
cd toybox
make defconfig && make

使用 autoconf 的專案

此外,如果是以 autoconf 為基礎的專案,程式碼會類似於以下範例:

tar zxvf make-4.2.tar.gz
cd make-4.2
./configure --host=$target_host && make

請注意,以 autoconf 為基礎的專案在支援跨平台程式碼編譯方面有極大的差異。另請注意,如果您 git clone 以 autoconf 為基礎的專案,則這個專案中不太可能有已簽入的 configure 指令碼,因此,請參閱專案的說明文件,以便瞭解如何啟動。