Bazel ile Android Yerel Geliştirme Kiti'ni kullanma

Sorun bildir Kaynağı göster Gece · 7,3 · 7,2 · 7,1 · 7,0 · 6,5

Bazel'i kullanmaya yeni başladıysanız lütfen ile Android Geliştirme 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ı, Android için doğrudan Bazel. Bazel, bu işlemi android_ndk_repository deposunu kullanarak gerçekleştirir tıklayın.

Ö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.

Android NDK'nın son sürümünü (r22 ve sonrası) kullanıyorsanız android_ndk_repository için Starlark uygulaması. Şu adresteki talimatları uygulayın: BENİ OKU

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:

Örnek sonuçlar

Ş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();

}

Hedef ABI'yı yapılandırma

Hedef ABI'yı yapılandırmak için --android_platforms işaretini aşağıdaki şekilde kullanın:

bazel build //:app --android_platforms=comma-separated list of platforms

--platforms işaretinde olduğu gibi --android_platforms öğesine iletilen değerler platform etiketleri cihazınızı tanımlamak için standart kısıtlama değerleri kullanarak hedefler.

Örneğin, 64 bit ARM işlemciye sahip bir Android cihaz için aşağıdaki gibi ekleyebilirsiniz:

platform(
    name = "android_arm64",
    constraint_values = [
        "@platforms//os:android",
        "@platforms//cpu:arm64",
    ],
)

Her Android platform @platforms//os:android kullanmalıdır İşletim sistemi kısıtlaması. CPU kısıtlamasını taşımak için şu grafiğe 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 geçirirsiniz. örnek: --android_platforms=//:arm64,//:x86_64 (bunları üst düzey BUILD.bazel dosyanız).

Bazel varsayılan bir Android platformu seçemediği için bir platform tanımlanıp --android_platforms ile belirtilir.

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
C++17 --cxxopt=-std=c++17

Ö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
)

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 için --platforms işaretini kullanın.

Örneğin, Android platformlarını my/platforms/BUILD:

bazel build //my/cc/jni:target \
      --platforms=//my/platforms:x86_64

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

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.