Bazel के साथ Android नेटिव डेवलपमेंट किट का इस्तेमाल करना

किसी समस्या की शिकायत करें सोर्स देखें रात · 7.3 · 7.2 · 7.1 · 7.0 · 6.5

अगर आप बाज़ार में नए हैं, तो कृपया Android ऐप्लिकेशन बनाने के साथ-साथ, Basel का ट्यूटोरियल.

खास जानकारी

Basel को कई अलग-अलग बिल्ड कॉन्फ़िगरेशन में इस्तेमाल किया जा सकता है. इनमें, ऐसे कई कॉन्फ़िगरेशन भी शामिल हैं जो Android नेटिव डेवलपमेंट किट (NDK) टूलचेन. इसका मतलब है कि सामान्य Android के लिए cc_library और cc_binary नियमों को सीधे इसमें इकट्ठा किया जा सकता है बेज़ल. Basel ने android_ndk_repository डेटा स्टोर करने की जगह का इस्तेमाल करके यह लक्ष्य पूरा किया नियम.

ज़रूरी शर्तें

कृपया पक्का करें कि आपने Android SDK और NDK इंस्टॉल किया हो.

SDK टूल और एनडीके (NDK) सेट अप करने के लिए, अपने WORKSPACE में यह स्निपेट जोड़ें:

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 नियम के बारे में ज़्यादा जानकारी के लिए, बिल्ड देखें एन्साइक्लोपीडिया एंट्री.

अगर आपके पास Android एनडीके का नया वर्शन (r22 या इसके बाद का वर्शन) है, तो android_ndk_repository का स्टारलार्क लागू करना. इसमें दिए गए निर्देशों का पालन करें इसे रीडमी करें.

तुरंत शुरू करना

Android के लिए C++ बनाने के लिए, अपनेcc_library android_binary या android_library नियम.

उदाहरण के लिए, किसी Android ऐप्लिकेशन के लिए, यह BUILD फ़ाइल दी गई है:

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

इस BUILD फ़ाइल के नतीजे नीचे दिया गया टारगेट ग्राफ़ है:

परिणामों के उदाहरण

पहला डायग्राम. cc_library डिपेंडेंसी के साथ Android प्रोजेक्ट का ग्राफ़ बनाएं.

ऐप्लिकेशन बनाने के लिए, बस इसे चलाएं:

bazel build //app/src/main:app

bazel build कमांड, Java फ़ाइलों, Android रिसॉर्स फ़ाइलों, और cc_library नियम और सब कुछ एक APK में पैकेज कर देता है:

$ 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

Basel की सभी cc_libraries को शेयर किए गए एक ऑब्जेक्ट (.so) फ़ाइल में इकट्ठा किया जाता है, डिफ़ॉल्ट रूप से, armeabi-v7a एबीआई को टारगेट करता है. इसे बदलने या इसके लिए बिल्ड बनाने के लिए एक साथ कई एबीआई, टारगेट कॉन्फ़िगर करने से जुड़ा सेक्शन देखें एबीआई.

सेटअप का उदाहरण

यह उदाहरण बेज़ल के उदाहरणों में उपलब्ध है डेटा स्टोर करने की जगह के लिए.

BUILD.bazel फ़ाइल में, android_binary की मदद से तीन टारगेट तय किए गए हैं, android_library और cc_library नियम.

android_binary का टॉप लेवल टारगेट, APK बनाता है.

cc_library टारगेट में, JNI फ़ंक्शन वाली एक C++ सोर्स फ़ाइल मौजूद है लागू करना:

#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 टारगेट में Java सोर्स, रिसॉर्स फ़ाइलें, और यह cc_library टारगेट पर निर्भर है. इस उदाहरण के लिए, MainActivity.java लोड होता है शेयर की गई ऑब्जेक्ट फ़ाइल libapp.so और जेएनआई के लिए मेथड सिग्नेचर तय करता है फ़ंक्शन:

public class MainActivity extends AppCompatActivity {

    static {
        System.loadLibrary("app");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
       // ...
    }

    public native String stringFromJNI();

}

टारगेट एबीआई को कॉन्फ़िगर करना

टारगेट एबीआई को कॉन्फ़िगर करने के लिए, --android_platforms फ़्लैग का इस्तेमाल इस तरह करें:

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

--platforms फ़्लैग की तरह ही, --android_platforms को पास की गई वैल्यू platform के लेबल टारगेट तय करें. इसके लिए, वे स्टैंडर्ड कंस्ट्रेंट वैल्यू का इस्तेमाल करते हैं जो आपके डिवाइस के बारे में बताती हैं.

उदाहरण के लिए, 64-बिट ARM प्रोसेसर वाले Android डिवाइस के लिए, का इस्तेमाल कैसे करते हैं:

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

हर Android platform को @platforms//os:android का इस्तेमाल करना चाहिए ओएस कंस्ट्रेंट. सीपीयू कंस्ट्रेंट को माइग्रेट करने के लिए, यह चार्ट देखें:

सीपीयू की वैल्यू प्लैटफ़ॉर्म
armeabi-v7a @platforms//cpu:armv7
arm64-v8a @platforms//cpu:arm64
x86 @platforms//cpu:x86_32
x86_64 @platforms//cpu:x86_64

और हां, एक से ज़्यादा आर्किटेक्चर वाले APK के लिए, आप एक से ज़्यादा लेबल पास करते हैं उदाहरण: --android_platforms=//:arm64,//:x86_64 (यह मानते हुए कि आपने उन्हें आपकी टॉप-लेवल BUILD.bazel फ़ाइल).

Baज़ल, डिफ़ॉल्ट Android प्लैटफ़ॉर्म नहीं चुन सकता, इसलिए एक तय करना ज़रूरी है और --android_platforms के साथ तय किया गया.

एनडीके वर्शन और Android एपीआई लेवल के आधार पर, ये एबीआई उपलब्ध:

एनडीके (NDK) में बदलाव एबीआई
16 और उससे कम Armeabi, Armeabi-v7a, arm64-v8a, mips, mips64, x86, x86_64
17 साल और इससे ज़्यादा Armeabi-v7a, arm64-v8a, x86, x86_64

NDK दस्तावेज़ देखें देखें.

ऐप्लिकेशन की रिलीज़ के लिए, मल्टी-एबीआई फ़ैट APK का सुझाव नहीं दिया जाता, क्योंकि इन APK में बढ़ोतरी होती है APK का साइज़ बड़ा है, लेकिन यह डेवलपमेंट और QA बिल्ड के लिए मददगार हो सकता है.

C++ स्टैंडर्ड चुनना

C++ स्टैंडर्ड के हिसाब से बनाने के लिए, इन फ़्लैग का इस्तेमाल करें:

C++ स्टैंडर्ड झंडा
सी++98 डिफ़ॉल्ट, फ़्लैग ज़रूरी नहीं है
सी++11 --cxxopt=-std=c++11
सी++14 --cxxopt=-std=c++14
सी++17 --cxxopt=-std=c++17

उदाहरण के लिए:

bazel build //:app --cxxopt=-std=c++11

--cxxopt, --copt, और किसी कंपाइलर और लिंकर फ़्लैग को पास करने के बारे में ज़्यादा जानें इस्तेमाल के लिए गाइड में --linkopt के बारे में बताया गया है.

कंपाइलर और लिंकर फ़्लैग को भी cc_library में एट्रिब्यूट के तौर पर बताया जा सकता है copts और linkopts का इस्तेमाल करके. उदाहरण के लिए:

cc_library(
    name = "jni_lib",
    srcs = ["cpp/native-lib.cpp"],
    copts = ["-std=c++11"],
    linkopts = ["-ldl"], # link against libdl
)

android_binary का इस्तेमाल किए बिना Android के लिए cc_library बनाना

Android के लिए एक स्टैंडअलोन cc_binary या cc_library बनाने के लिए, android_binary, --platforms फ़्लैग का इस्तेमाल करें.

उदाहरण के लिए, यह मानते हुए कि आपने Android my/platforms/BUILD:

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

इस तरीके से पूरे बिल्ड ट्री पर असर पड़ता है.

इन फ़्लैग को bazelrc कॉन्फ़िगरेशन (हर एबीआई के लिए एक) में रखा जा सकता है 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>

इसके बाद, उदाहरण के लिए, x86 के लिए cc_library बनाने के लिए, यह चलाएं:

bazel build //my/cc/jni:target --config=android_x86

आम तौर पर, इस तरीके का इस्तेमाल कम-लेवल के टारगेट (जैसे, cc_library) के लिए करें या जब आपको अच्छे से पता है कि क्या बनाया जा रहा है; के लिए स्वचालित कॉन्फ़िगरेशन पर निर्भर होते हैं उन हाई-लेवल टारगेट के लिए android_binary से ट्रांज़िशन जिनकी आपको उम्मीद है ताकि आप बहुत सारे टारगेट का इस्तेमाल कर सकें.