Toolchain mandiri (usang)

Anda dapat menggunakan toolchain yang disediakan dengan Android NDK secara mandiri atau sebagai plugin dengan IDE yang ada. Fleksibilitas ini berguna jika Anda sudah memiliki sistem build sendiri, dan hanya memerlukan kemampuan untuk memanggil lintas compiler agar dapat menambahkan dukungan untuknya ke Android.

Memilih toolchain

Pertama-tama, Anda harus memutuskan arsitektur prosesor yang akan ditargetkan oleh toolchain mandiri. Untuk melakukannya, gunakan flag --arch.

Memilih sysroot

Langkah berikutnya yang harus dilakukan adalah menentukan sysroot. Sysroot adalah direktori yang memuat header dan library sistem untuk target Anda. Untuk menentukan sysroot, Anda harus mengetahui API level Android yang ingin ditargetkan untuk dukungan native; API native yang tersedia bervariasi sesuai API level Android.

Library untuk API native bagi setiap API level Android berada dalam $NDK/platforms/; kemudian, setiap direktori API level berisi subdirektori untuk berbagai CPU dan arsitektur. Header berada di $NDK/sysroot.

Untuk detail selengkapnya tentang API level Android dan masing-masing API native yang didukungnya, lihat API Native.

Membuat toolchain

NDK menyediakan skrip make_standalone_toolchain.py untuk memungkinkan Anda melakukan penginstalan toolchain yang disesuaikan dari command line.

Ini merupakan alat baru yang menggantikan make-standalone-toolchain.sh lama. Alat ini telah diterapkan ulang di Python sehingga pengguna Windows tidak perlu menginstal Cygwin atau MSYS untuk menjalankannya.

Skripnya terletak dalam direktori $NDK/build/tools/, di mana $NDK adalah root penginstalan untuk NDK.

Berikut adalah contoh penggunaan skrip ini:

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

Perintah ini membuat direktori bernama /tmp/my-android-toolchain/, yang berisi salinan sysroot android-21/arch-arm, dan biner toolchain untuk target ARM 32 bit.

Perlu diketahui bahwa biner toolchain tidak bergantung pada atau berisi jalur khusus host. Dengan kata lain, Anda dapat menginstalnya di lokasi mana pun atau bahkan memindahkannya jika perlu.

Argumen --arch diperlukan, tetapi API level akan ditetapkan secara default ke level minimal yang didukung untuk arsitektur yang ditentukan (saat ini adalah 16 untuk arsitektur 32 bit dan 21 untuk arsitektur 64 bit).

Dimulai dari r18, semua toolchain mandiri menggunakan Clang dan libc++. Library bersama libc++ akan digunakan secara default kecuali Anda akan mem-build executable statis. Untuk memaksa penggunaan library statis, teruskan -static-libstdc++ saat melakukan penautan. Perilaku ini sesuai dengan toolchain host normal.

Sebagaimana disebutkan dalam dukungan library C++, Anda biasanya harus meneruskan -latomic saat menautkan ke libc++.

Perlu diketahui bahwa jika Anda menghilangkan opsi --install-dir, alat tersebut akan membuat tarball dalam direktori saat ini yang bernama $TOOLCHAIN_NAME.tar.bz2. Tarball dapat ditempatkan dalam direktori yang berbeda menggunakan --package-dir.

Untuk opsi dan detail selengkapnya, gunakan --help.

Bekerja dengan Clang

Biner Clang akan otomatis disertakan dalam toolchain mandiri.

Selain itu, ada juga dua skrip wrapper, yang bernama clang dan clang++, pada <install-dir>/bin. Skrip ini memanggil biner clang dengan flag arsitektur target yang benar. Dengan kata lain, skrip tersebut dapat digunakan tanpa modifikasi apa pun, dan dapat digunakan di build Anda sendiri hanya dengan menetapkan variabel lingkungan CC dan CXX agar mengarah ke skrip tersebut.

Kemudian, ada juga skrip wrapper bernama gcc dan g++ yang juga memanggil Clang. Skrip ini berfungsi untuk menyediakan level kompatibilitas bagi file build yang secara eksplisit merujuk ke GCC, meskipun NDK tidak lagi berisi GCC. Tentunya, jika ada file build yang menggunakan opsi command line yang tidak didukung oleh Clang, Anda harus menghapus atau menggantinya.

Target Clang pada ARM

Saat melakukan proses build untuk ARM, Clang mengubah target berdasarkan keberadaan flag compiler -march=armv7-a dan/atau -mthumb:

Tabel 1. Nilai -march yang dapat ditentukan dan target yang dihasilkannya.

Nilai -march Target yang dihasilkan
-march=armv7-a armv7-none-linux-androideabi
-mthumb thumb-none-linux-androideabi
-march=armv7-a dan -mthumb thumbv7-none-linux-androideabi

Anda juga dapat menggantinya dengan -target Anda sendiri jika menginginkannya.

clang dan clang++ harus menjadi pengganti drop-in untuk gcc dan g++ dalam makefile. Jika tidak yakin, gunakan opsi berikut saat memanggil compiler untuk memastikan keduanya berfungsi dengan baik:

  • -v untuk membuang perintah yang terkait dengan masalah driver compiler
  • -### untuk membuang opsi command line, termasuk yang ditentukan sebelumnya secara implisit.
  • -x c < /dev/null -dM -E untuk membuang definisi preprosesor standar
  • -save-temps untuk membandingkan file *.i atau *.ii yang diproses sebelumnya.

Kompatibilitas ABI

Secara default, toolchain mandiri Clang ARM akan menargetkan armeabi-v7a ABI. Anda dapat menggantinya dengan meneruskan opsi -march atau -target yang sesuai.

Sebaiknya gunakan flag compiler -mthumb untuk memaksa pembuatan instruksi Thumb-2 16 bit. Jika dihilangkan, toolchain akan mengeluarkan petunjuk ARM 32 bit.

Untuk menggunakan instruksi NEON, Anda harus menggunakan flag compiler -mfpu: -mfpu=neon.

Perlu diketahui bahwa setelan ini akan memaksa penggunaan VFPv3-D32, sesuai spesifikasi ARM.

Selain itu, pastikan untuk memberikan dua flag berikut pada linker: -march=armv7-a -Wl,--fix-cortex-a8.

Flag pertama memerintahkan linker untuk memilih library toolchain yang dirancang bagi armv7-a. Flag kedua diperlukan sebagai solusi untuk bug CPU pada beberapa implementasi Cortex-A8.

Anda tidak perlu menggunakan flag compiler tertentu saat menargetkan ABI lainnya.

Untuk mempelajari dukungan ABI lebih lanjut, lihat ABI Android.

Peringatan dan batasan

Dukungan Windows

Biner Windows tidak bergantung pada Cygwin. Tidak adanya dependensi ini menjadikannya lebih cepat. Namun, konsekuensinya adalah, biner tersebut tidak memahami spesifikasi jalur Cygwin seperti cygdrive/c/foo/bar, dibandingkan dengan C:/foo/bar.

Pengecualian, RTTI, dan STL

Secara default, biner toolchain mendukung pengecualian C++ dan RTTI. Untuk menonaktifkan pengecualian C++ dan RTTI saat mem-build sumber (misalnya, untuk membuat kode mesin yang lebih ringan), gunakan -fno-exceptions dan -fno-rtti.

Dukungan STL C++

Toolchain mandiri menyertakan implementasi Library Template Standar (STL) C++.

  • Gunakan -static-libstdc++ untuk mendapatkan versi library statis libc++. Dengan demikian, semua kode STL C++ yang diperlukan akan disertakan dalam biner akhir Anda. Metode ini ideal jika Anda hanya menghasilkan satu library bersama atau executable, yang merupakan rekomendasi kami.

  • Secara default, versi library bersama libc++ akan digunakan. Tidak ada flag tambahan yang diperlukan untuk menautkan ke library bersama. Anda harus mengemas libc++_shared.so dalam aplikasi, atau kode Anda tidak akan dimuat.

    Tabel 2 menampilkan lokasi file ini untuk setiap arsitektur.

    Tabel 2. Nilai -march yang dapat ditentukan dan target yang dihasilkannya.

    Toolchain Lokasi
    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/

Membuat project open source dengan toolchain mandiri

Untuk toolchain contoh ini:

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

Berikut ini cara menyiapkan lingkungan untuk digunakan dalam membuat project open source tradisional:

# 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"

Project dengan sistem build kustom

Sebagai contoh, berikut cara membuat toybox setelah menjalankan langkah-langkah sebelumnya:

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

Project dengan autoconf

Sebagai alternatif, project berbasis autoconf akan terlihat seperti ini:

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

Perhatikan bahwa project berbasis autoconf sangat bervariasi dalam dukungannya terhadap kompilasi silang. Selain itu, perlu diperhatikan bahwa jika Anda melakukan git clone pada project berbasis autoconf, project tersebut kemungkinan tidak memiliki skrip configure yang terdaftar, jadi Anda harus mengikuti dokumentasi project tentang cara melakukan bootstrap.