Bazel'i yeni kullanmaya başlıyorsanız lütfen Android'i Bazel ile Oluşturma eğitiminden başlayın.
Genel Bakış
Bazel, Android Native Development Kit (NDK) araç zincirini kullananlar da dahil olmak üzere birçok farklı derleme yapılandırmasında çalışabilir. Bu, normal cc_library
ve cc_binary
kurallarının doğrudan Bazel'de Android için derlenebileceği anlamına gelir. Bazel, bu işlemi android_ndk_repository
repository
rule ve ilgili bzlmod uzantısını kullanarak gerçekleştirir.
Genel Android derlemesi için rules_android
kullanın.
Bu eğitimde, C++ kitaplık bağımlılıklarının Android uygulamalarına nasıl entegre edileceği gösterilmekte ve NDK araç zinciri keşfi ile kaydı için rules_android_ndk
kullanılmaktadır.
Ön koşullar
Lütfen Android SDK ve NDK'yı yüklediğinizden emin olun.
NDK ve SDK kurulumu
Harici depo kurulumu, WORKSPACE veya bzlmod (MODULE.bazel) kullanıp kullanmadığınıza göre değişir. Bzlmod, Bazel 7 ve sonraki sürümler için tercih edilen çözümdür. MODULE.bazel ve WORKSPACE kurulum dizelerinin birbirinden bağımsız olduğunu unutmayın. Bir bağımlılık yönetimi çözümü kullanıyorsanız diğer çözüm için standart kodu eklemeniz gerekmez.
Bzlmod MODULE.bazel kurulumu
MODULE.bazel dosyanıza aşağıdaki snippet'i ekleyin:
# NDK
bazel_dep(name = "rules_android_ndk", version = "0.1.3")
android_ndk_repository_extension = use_extension("@rules_android_ndk//:extension.bzl", "android_ndk_repository_extension")
use_repo(android_ndk_repository_extension, "androidndk")
register_toolchains("@androidndk//:all")
# SDK
bazel_dep(name = "rules_android", version = "0.6.6")
register_toolchains(
"@rules_android//toolchains/android:android_default_toolchain",
"@rules_android//toolchains/android_sdk:android_sdk_tools",
)
android_sdk_repository_extension = use_extension("@rules_android//rules/android_sdk_repository:rule.bzl", "android_sdk_repository_extension")
use_repo(android_sdk_repository_extension, "androidsdk")
register_toolchains("@androidsdk//:sdk-toolchain", "@androidsdk//:all")
Eski WORKSPACE kurulumu
WORKSPACE
dosyanıza aşağıdaki snippet'i ekleyin:
load("@rules_android//rules:rules.bzl", "android_sdk_repository")
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.
)
load("@rules_android_ndk//:rules.bzl", "android_ndk_repository")
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.
)
WORKSPACE ile ilgili uyumluluk notları:
- Hem
rules_android
hem derules_android_ndk
kuralları, yukarıdaki WORKSPACE snippet'inde gösterilmeyen ek standart metin gerektirir. Güncel ve tam olarak oluşturulmuş bir örnekleme stanza'sı içinrules_android_ndk
'ın temel örnek uygulamasının WORKSPACE dosyasına bakın.
android_ndk_repository
kuralı hakkında daha fazla bilgi için docstring'ine bakın.
Hızlı başlangıç
Android için C++ oluşturmak üzere cc_library
bağımlılıklarını android_binary
veya android_library
kurallarınıza eklemeniz yeterlidir.
Örneğin, bir Android uygulaması için aşağıdaki BUILD
dosyası verildiğinde:
# In <project>/app/src/main/BUILD.bazel
load("@rules_cc//cc:cc_library.bzl", "cc_library")
load("@rules_android//rules:rules.bzl", "android_binary", "android_library")
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 grafiği oluşturur:
1.şekil cc_library bağımlılıklarıyla Android projesinin grafiğini oluşturun.
Uygulamayı oluşturmak için şu komutu çalıştırmanız yeterlidir:
bazel build //app/src/main:app --android_platforms=<your platform>
--android_platforms
belirtmezseniz derlemenizin, eksik JNI üstbilgileriyle ilgili hatalar nedeniyle başarısız olacağını unutmayın.
bazel build
komutu Java dosyalarını, Android kaynak dosyalarını ve cc_library
kurallarını derler ve her şeyi bir APK'da 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, --android_platforms
tarafından belirtilen mimarileri hedefleyerek tüm cc_libraries'i tek bir paylaşılan nesne (.so
) dosyasında derler.
Daha fazla bilgi için hedef ABI'yi yapılandırma bölümüne bakın.
Örnek kurulum
Bu örneği Bazel örnekleri deposunda bulabilirsiniz.
BUILD.bazel
dosyasında android_binary
, android_library
ve cc_library
kurallarıyla üç hedef tanımlanmıştır.
android_binary
üst düzey hedefi, APK'yı oluşturur.
cc_library
hedefi, JNI işlevi uygulaması içeren tek bir C++ kaynak dosyası içerir:
#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
hedefindeki bağımlılığı belirtir. Bu örnekte, MainActivity.java
paylaşılan nesne dosyasını yükler libapp.so
ve JNI işlevi için yöntem imzasını tanımlar:
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("app");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// ...
}
public native String stringFromJNI();
}
Hedef ABI'yi yapılandırma
Hedef ABI'yi yapılandırmak için --android_platforms
işaretini aşağıdaki gibi kullanın:
bazel build //:app --android_platforms=comma-separated list of platforms
--platforms
işaretinde olduğu gibi, --android_platforms
'ye iletilen değerler, cihazınızı tanımlamak için standart kısıtlama değerlerini kullanan platform
hedeflerinin etiketleridir.
Örneğin, 64 bit ARM işlemcili bir Android cihaz için platformunuzu şu şekilde tanımlarsınız:
platform(
name = "android_arm64",
constraint_values = [
"@platforms//os:android",
"@platforms//cpu:arm64",
],
)
Her Android platform
, @platforms//os:android
işletim sistemi kısıtlamasını kullanmalıdır. CPU kısıtlamasını taşımak için bu tabloya bakın:
CPU Değeri | Platform |
---|---|
armeabi-v7a |
@platforms//cpu:armv7 |
arm64-v8a |
@platforms//cpu:arm64 |
x86 |
@platforms//cpu:x86_32 |
x86_64 |
@platforms//cpu:x86_64 |
Elbette, çok mimarili bir APK için birden fazla etiket iletirsiniz. Örneğin: --android_platforms=//:arm64,//:x86_64
(Bunları üst düzey BUILD.bazel
dosyanızda tanımladığınızı varsayarsak).
Bazel, varsayılan bir Android platformu seçemez. Bu nedenle, bir platform tanımlanmalı ve --android_platforms
ile belirtilmelidir.
NDK revizyonuna ve Android API düzeyine bağlı olarak aşağıdaki ABI'ler kullanılabilir:
NDK düzeltmesi | ABI'lar |
---|---|
16 ve daha düşük | armeabi, armeabi-v7a, arm64-v8a, mips, mips64, x86, x86_64 |
17 yaş ve üzeri | armeabi-v7a, arm64-v8a, x86, x86_64 |
Bu ABI'ler hakkında daha fazla bilgi için NDK belgelerine bakın.
Çoklu ABI Fat APK'lar, APK'nın boyutunu artırdığı için yayın derlemeleri için önerilmez ancak geliştirme ve kalite kontrol derlemeleri için yararlı olabilir.
C++ standardı seçme
Bir C++ standardına göre derleme yapmak için aşağıdaki işaretleri kullanın:
C++ Standard | İşaret |
---|---|
C++98 | Varsayılan, işaret gerekmez |
C++11 | --cxxopt=-std=c++11 |
C++14 | --cxxopt=-std=c++14 |
C++17 | --cxxopt=-std=c++17 |
Örneğin:
bazel build //:app --cxxopt=-std=c++11
--cxxopt
, --copt
ve --linkopt
ile derleyici ve bağlayıcı işaretlerini iletme hakkında daha fazla bilgiyi Kullanıcı Kılavuzu'nda bulabilirsiniz.
Derleyici ve bağlayıcı işaretleri, cc_library
içinde copts
ve linkopts
kullanılarak özellik olarak da belirtilebilir. Örneğin:
cc_library(
name = "jni_lib",
srcs = ["cpp/native-lib.cpp"],
copts = ["-std=c++11"],
linkopts = ["-ldl"], # link against libdl
)
android_binary
kullanmadan Android için cc_library
oluşturma
android_binary
kullanmadan Android için bağımsız bir cc_binary
veya cc_library
oluşturmak istiyorsanız --platforms
işaretini kullanın.
Örneğin, my/platforms/BUILD
içinde Android platformlarını tanımladığınızı varsayarsak:
bazel build //my/cc/jni:target \
--platforms=//my/platforms:x86_64
Bu yaklaşımla, derleme ağacının tamamı etkilenir.
Bu işaretler, bazelrc
yapılandırmasına (her ABI için bir tane) yerleştirilebilir. project/.bazelrc
:
common:android_x86 --platforms=//my/platforms:x86
common:android_armeabi-v7a --platforms=//my/platforms:armeabi-v7a
# In general
common:android_<abi> --platforms=//my/platforms:<abi>
Ardından, örneğin x86
için cc_library
oluşturmak üzere şu komutu çalıştırın:
bazel build //my/cc/jni:target --config=android_x86
Genel olarak, bu yöntemi düşük düzeyli hedefler (ör. cc_library
) için veya tam olarak ne oluşturduğunuzu bildiğinizde kullanın. Kontrol etmediğiniz birçok hedef oluşturmayı beklediğiniz yüksek düzeyli hedefler için android_binary
'den otomatik yapılandırma geçişlerini kullanın.