Bazel'i kullanmaya yeni başladıysanız lütfen Google ile Android Oluşturma Bazel eğitimi.
Genel Bakış
Bazel, birçok farklı derleme yapılandırmasında çalışabilir. Bunlardan bazıları,
Android Yerel Geliştirme Kiti (NDK) araç zincirini kullanıyor. Bu, normal verilerin
cc_library
ve cc_binary
kuralları doğrudan Android için derlenebilir
Bazel. Bazel, bu işlemi android_ndk_repository
deposunu kullanarak gerçekleştirir
kuralı.
Ön koşullar
Lütfen Android SDK ve NDK'yı yüklediğinizden emin olun.
SDK ve NDK'yı ayarlamak için WORKSPACE
cihazınıza aşağıdaki snippet'i ekleyin:
android_sdk_repository(
name = "androidsdk", # Required. Name *must* be "androidsdk".
path = "/path/to/sdk", # Optional. Can be omitted if `ANDROID_HOME` environment variable is set.
)
android_ndk_repository(
name = "androidndk", # Required. Name *must* be "androidndk".
path = "/path/to/ndk", # Optional. Can be omitted if `ANDROID_NDK_HOME` environment variable is set.
)
android_ndk_repository
kuralı hakkında daha fazla bilgi için bkz. Oluşturma
Ansiklopedi girişi.
Hızlı başlangıç
Android için C++ geliştirmek üzere hesabınıza cc_library
bağımlılıkları eklemeniz
android_binary
veya android_library
kuralları.
Örneğin, bir Android uygulaması için aşağıdaki BUILD
dosyasını ele alalım:
# In <project>/app/src/main/BUILD.bazel
cc_library(
name = "jni_lib",
srcs = ["cpp/native-lib.cpp"],
)
android_library(
name = "lib",
srcs = ["java/com/example/android/bazel/MainActivity.java"],
resource_files = glob(["res/**/*"]),
custom_package = "com.example.android.bazel",
manifest = "LibraryManifest.xml",
deps = [":jni_lib"],
)
android_binary(
name = "app",
deps = [":lib"],
manifest = "AndroidManifest.xml",
)
Bu BUILD
dosyası, aşağıdaki hedef grafikle sonuçlanır:
Şekil 1. cc_library bağımlılarını içeren Android projesinin grafiğini oluşturma
Uygulamayı derlemek için şu komutu çalıştırın:
bazel build //app/src/main:app
bazel build
komutu, Java dosyalarını, Android kaynak dosyalarını ve
cc_library
kural oluşturuyor ve her şeyi bir APK olarak paketler:
$ zipinfo -1 bazel-bin/app/src/main/app.apk
nativedeps
lib/armeabi-v7a/libapp.so
classes.dex
AndroidManifest.xml
...
res/...
...
META-INF/CERT.SF
META-INF/CERT.RSA
META-INF/MANIFEST.MF
Bazel, tüm cc_libraries adlı dosyaları tek bir paylaşılan nesne (.so
) dosyasında derler,
varsayılan olarak armeabi-v7a
ABI için hedeflenir. Bunu değiştirmek veya
için birden fazla ABI'yi kullanıyorsanız hedefi yapılandırma
ABI değerleridir.
Örnek kurulum
Bu örnek, Bazel örneklerinde depo.
BUILD.bazel
dosyasında android_binary
ile üç hedef tanımlanmıştır.
android_library
ve cc_library
kuralları.
APK'yı üst düzey android_binary
hedefi oluşturur.
cc_library
hedefi, JNI işlevine sahip tek bir C++ kaynak dosyası içeriyor
uygulama:
#include <jni.h>
#include <string>
extern "C"
JNIEXPORT jstring
JNICALL
Java_com_example_android_bazel_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
android_library
hedefi, Java kaynaklarını, kaynak dosyalarını ve
cc_library
hedefine bağımlılık. Bu örnekte, MainActivity.java
yüklenir
libapp.so
adlı paylaşılan nesne dosyasını kullanır ve JNI için yöntem imzasını tanımlar
işlev:
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("app");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// ...
}
public native String stringFromJNI();
}
STL'yi yapılandırma
C++ STL'yi yapılandırmak için --android_crosstool_top
işaretini kullanın.
bazel build //:app --android_crosstool_top=target label
@androidndk
içinde kullanılabilen STL'ler:
STL | Hedef etiket |
---|---|
STLport | @androidndk//:toolchain-stlport |
libc++ | @androidndk//:toolchain-libcpp |
Gnustl | @androidndk//:toolchain-gnu-libstdcpp |
r16 ve önceki sürümler için varsayılan STL gnustl
'dir. r17 ve üzeri sürümlerde
libc++
Kolaylık sağlaması açısından hedef @androidndk//:default_crosstool
diğer adı ilgili varsayılan STL'lere atanır.
18. sürümden itibaren STLport ve gnustl'ın
,
Böylece libc++
, NDK'daki tek STL'dir.
NDK'ya göz atın belgeleri 'na göz atın.
Hedef ABI'yı yapılandırma
Hedef ABI'yı yapılandırmak için --fat_apk_cpu
işaretini aşağıdaki şekilde kullanın:
bazel build //:app --fat_apk_cpu=comma-separated list of ABIs
Varsayılan olarak Bazel, armeabi-v7a
için yerel Android kodu oluşturur. x86 için derleme
(örneğin emülatörler için) --fat_apk_cpu=x86
değerini geçirin. Birden fazla APK için yağ APK'sı
birden fazla CPU belirtebilirsiniz: --fat_apk_cpu=armeabi-v7a,x86
.
Birden fazla ABI belirtilirse Bazel, paylaşılan bir ABI içeren APK nesnesini ifade eder.
NDK düzeltmesine ve Android API düzeyine bağlı olarak aşağıdaki ABI'ler şunlardır: mevcut:
NDK düzeltmesi | ABI'lar |
---|---|
16 ve altı | armeabi, armeabi-v7a, arm64-v8a, mips, mips64, x86, x86_64 |
17 ve üzeri | armeabi-v7a, arm64-v8a, x86, x86_64 |
NDK dokümanlarına göz atın bu ABI'ler hakkında daha fazla bilgi edinin.
Çoklu ABI Yağ APK'ları, yayın derlemeleri için önerilmez çünkü APK'nın boyutunu değiştirebilir ancak geliştirme ve KG derlemeleri için yararlı olabilir.
C++ standardı seçme
C++ standardına göre derleme yapmak için aşağıdaki flag'leri kullanın:
C++ Standart | İşaret |
---|---|
C++98 | Varsayılan, işaret gerekmez |
C++11 | --cxxopt=-std=c++11 |
C++14 | --cxxopt=-std=c++14 |
Örneğin:
bazel build //:app --cxxopt=-std=c++11
--cxxopt
, --copt
ve bağlayıcı işaretleriyle derleyici ve bağlayıcı işaretlerini iletme hakkında daha fazla bilgi
Kullanıcı Kılavuzu'ndaki --linkopt
Derleyici ve bağlayıcı işaretleri, cc_library
özelliğinde özellik olarak da belirtilebilir.
copts
ve linkopts
kullanılıyor. Örneğin:
cc_library(
name = "jni_lib",
srcs = ["cpp/native-lib.cpp"],
copts = ["-std=c++11"],
linkopts = ["-ldl"], # link against libdl
)
Platformlar ve araç zincirleriyle entegrasyon
Bazel'in yapılandırma modeli,
platformlar ve
araç zincirleri gibidir. Eğer
derleme, mimari veya işletim sistemini seçmek için --platforms
işaretini kullanır
--extra_toolchains
işaretini Bazel'e iletmeniz ve
NDK'yı kullanmak için yeterli.
Örneğin, Google Etiket Yöneticisi'nin sağladığı android_arm64_cgo
araç zinciriyle entegrasyon
emin olmak için, aşağıdaki kurallara ek olarak --extra_toolchains=@androidndk//:all
--platforms
işareti.
bazel build //my/cc:lib \
--platforms=@io_bazel_rules_go//go/toolchain:android_arm64_cgo \
--extra_toolchains=@androidndk//:all
Bunları doğrudan WORKSPACE
dosyasına da kaydedebilirsiniz:
android_ndk_repository(name = "androidndk")
register_toolchains("@androidndk//:all")
Bu araç zincirlerini kaydettiğinizde, Bazel bunları NDK'da BUILD
dosyasını (NDK 20 için) kopyalayın:
toolchain(
name = "x86-clang8.0.7-libcpp_toolchain",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
target_compatible_with = [
"@platforms//os:android",
"@platforms//cpu:x86_32",
],
toolchain = "@androidndk//:x86-clang8.0.7-libcpp",
)
toolchain(
name = "x86_64-clang8.0.7-libcpp_toolchain",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
target_compatible_with = [
"@platforms//os:android",
"@platforms//cpu:x86_64",
],
toolchain = "@androidndk//:x86_64-clang8.0.7-libcpp",
)
toolchain(
name = "arm-linux-androideabi-clang8.0.7-v7a-libcpp_toolchain",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
target_compatible_with = [
"@platforms//os:android",
"@platforms//cpu:arm",
],
toolchain = "@androidndk//:arm-linux-androideabi-clang8.0.7-v7a-libcpp",
)
toolchain(
name = "aarch64-linux-android-clang8.0.7-libcpp_toolchain",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
target_compatible_with = [
"@platforms//os:android",
"@platforms//cpu:aarch64",
],
toolchain = "@androidndk//:aarch64-linux-android-clang8.0.7-libcpp",
)
İşleyiş şekli: Android yapılandırma geçişleri tanıtımı
android_binary
kuralı, Bazel'dan
Android ile uyumlu bir yapılandırma, böylece Bazel derlemesinin arka arkaya çalışması için
için --fat_apk_cpu
ve --android_crosstool_top
haricindeki tüm özel işaretler
ABI ve STL yapılandırması.
Perde arkasında bu otomatik yapılandırma, Android config değiştirilebilir.
android_binary
gibi uyumlu bir kural,
Android yapılandırmasına bağımlıların yapılandırılması. Bu nedenle,
Derlemenin Android'e özgü alt ağaçları bu durumdan etkilenmektedir. Yapının diğer bölümleri
grafiği, üst düzey hedef yapılandırması kullanılarak işlenir. Hatta bir sürü
Bir hedefe giden yollar varsa her iki yapılandırmada da tek bir hedef işleme
bir yapı grafiği oluşturacaksınız.
Bazel, veya daha üst düzeyde bir geçiş noktası nedeniyle yapılandırmada başka değişiklik yapmaz.
Android'e geçişi tetikleyen tek yerleşik konum
yapılandırma, android_binary
öğesinin deps
özelliğidir.
Örneğin, cc_library
ile android_library
hedefi oluşturmaya çalışırsanız
bağımlılığınız yoksa eksik bir JNI hatasıyla ilgili
üstbilgi:
ERROR: project/app/src/main/BUILD.bazel:16:1: C++ compilation of rule '//app/src/main:jni_lib' failed (Exit 1)
app/src/main/cpp/native-lib.cpp:1:10: fatal error: 'jni.h' file not found
#include <jni.h>
^~~~~~~
1 error generated.
Target //app/src/main:lib failed to build
Use --verbose_failures to see the command lines of failed build steps.
İdeal olarak, bu otomatik geçişlerin Bazel'in
neden olur. Ancak, Bazel komut satırındaki hedef zaten
belirli bir geçiş kurallarını test eden C++ geliştiricileri gibi,
cc_library
, ardından özel bir --crosstool_top
kullanılmalıdır.
android_binary
kullanmadan Android için cc_library
oluşturma
Bir uygulama kullanmadan Android için bağımsız bir cc_binary
veya cc_library
oluşturmak istiyorsanız
android_binary
, --crosstool_top
, --cpu
ve --host_crosstool_top
kullanın
işaretidir.
Örneğin:
bazel build //my/cc/jni:target \
--crosstool_top=@androidndk//:default_crosstool \
--cpu=<abi> \
--host_crosstool_top=@bazel_tools//tools/cpp:toolchain
Bu örnekte, üst düzey cc_library
ve cc_binary
hedefleri oluşturulmuştur.
çok kolay bir şekilde
yapabilirsiniz. Ancak bu, Bazel'ın kendi barındırma araçlarının oluşturulmasına neden olur.
olması nedeniyle, ana makine araç zincirinin
hedef araç zincirinden kopyalanır. Bu sorunu çözmek için
@bazel_tools//tools/cpp:toolchain
olarak --host_crosstool_top
ana makinenin C++ araç zincirini açık bir şekilde ayarlamanız gerekir.
Bu yaklaşımda tüm yapı ağacı etkilenir.
Bu flag'ler bir bazelrc
yapılandırmasına (her ABI için bir adet) yerleştirilebilir.
project/.bazelrc
:
common:android_x86 --crosstool_top=@androidndk//:default_crosstool
common:android_x86 --cpu=x86
common:android_x86 --host_crosstool_top=@bazel_tools//tools/cpp:toolchain
common:android_armeabi-v7a --crosstool_top=@androidndk//:default_crosstool
common:android_armeabi-v7a --cpu=armeabi-v7a
common:android_armeabi-v7a --host_crosstool_top=@bazel_tools//tools/cpp:toolchain
# In general
common:android_<abi> --crosstool_top=@androidndk//:default_crosstool
common:android_<abi> --cpu=<abi>
common:android_<abi> --host_crosstool_top=@bazel_tools//tools/cpp:toolchain
Ardından, örneğin x86
için bir cc_library
oluşturmak üzere şu komutu çalıştırın:
bazel build //my/cc/jni:target --config=android_x86
Bu yöntemi genellikle düşük düzeyli hedefler (ör. cc_library
) için veya
tam olarak ne inşa ettiğinizi
bilirsiniz. her gün otomatik olarak
beklediğinizden daha üst düzey hedefler için android_binary
kontrol edemediğiniz çok sayıda hedef oluşturmanıza yardımcı olur.