Bazel'i kullanmaya yeni başladıysanız lütfen Bazel ile Android geliştirme eğitimiyle 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 Android için doğrudan Bazel'da derlenebileceği anlamına gelir. Bazel, bunu android_ndk_repository
depo kuralını kullanarak yapar.
Ön koşullar
Lütfen Android SDK'sını ve NDK'yı yüklediğinizden emin olun.
SDK'yı ve NDK'yı ayarlamak için WORKSPACE
dosyanı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 Build Ansiklopedisi girişine bakın.
Android NDK'nın son sürümünü (r22 ve sonraki sürümler) kullanıyorsanız android_ndk_repository
için Starlark uygulamasını kullanın.
README dosyasında yer alan talimatları uygulayın.
Hızlı başlangıç
Android için C++ derlemek istiyorsanız android_binary
veya android_library
kurallarınıza cc_library
bağımlılıkları eklemeniz yeterlidir.
Örneğin, bir Android uygulaması için aşağıdaki BUILD
dosyası verilmiştir:
# 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ılıkları olan Android projesinin grafiğini oluşturun.
Uygulamayı derlemek için şunları çalıştırmanız yeterlidir:
bazel build //app/src/main:app
bazel build
komutu, Java dosyalarını, Android kaynak dosyalarını ve cc_library
kurallarını derleyip her şeyi bir APK'ya 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 dosyalarını varsayılan olarak armeabi-v7a
ABI'yi hedefleyen tek bir paylaşılan nesne (.so
) dosyasında derleyebilir. Bunu değiştirmek veya aynı anda birden fazla ABI için derleme yapmak istiyorsanız hedef ABI'yi yapılandırma bölümüne bakın.
Örnek kurulum
Bu örnek, Bazel örnekleri deposunda yer almaktadır.
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şlev uygulamasını 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
hedefine olan bağımlılığı belirtir. Bu örnekte MainActivity.java
, paylaşılan nesne dosyasını libapp.so
yükler ve JNI işlevinin 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şareti gibi, --android_platforms
'a iletilen değerler de cihazınızı tanımlamak için standart kısıtlama değerlerini kullanan platform
hedeflerinin etiketleridir.
Örneğin, 64 bit ARM işlemciye sahip 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
OS kısıtlamasını kullanmalıdır. CPU kısıtlamasını taşımak için bu grafiği kontrol edin:
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 iletmeniz gerekir. Örneğin: --android_platforms=//:arm64,//:x86_64
(bunları üst düzey BUILD.bazel
dosyanızda tanımladığınız varsayılır).
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 sürümü | ABI'lar |
---|---|
16 yaş ve altı | armeabi, armeabi-v7a, arm64-v8a, mips, mips64, x86, x86_64 |
17 ve üzeri | armeabi-v7a, arm64-v8a, x86, x86_64 |
Bu ABI'ler hakkında daha fazla bilgi için NDK dokümanlarına bakın.
Çoklu ABI'li büyük APK'lar, APK'nın boyutunu artırdığından sürüm derlemeleri için önerilmez ancak geliştirme ve kalite kontrol derlemeleri için yararlı olabilir.
C++ standardı seçme
C++ standardına göre derlemek 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
Derleyici ve bağlayıcı işaretlerini --cxxopt
, --copt
ve --linkopt
ile iletme hakkında daha fazla bilgiyi Kullanıcı Kılavuzu'nda bulabilirsiniz.
Derleyici ve bağlayıcı işaretleri, copts
ve linkopts
kullanılarak cc_library
içinde ö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şımda tüm yapı ağacı etkilenir.
Bu işaretler, project/.bazelrc
içinde bir bazelrc
yapılandırmasına (her ABI için bir adet) yerleştirilebilir:
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 bir 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, cc_library
gibi alt düzey hedefler için veya ne oluşturduğunuzu tam olarak bildiğiniz durumlarda kullanın. Kontrol etmediğiniz çok sayıda hedef oluşturmayı beklediğiniz üst düzey hedefler için android_binary
tarafından yapılan otomatik yapılandırma geçişlerini kullanın.