अगर आपने हाल ही में Bazel का इस्तेमाल शुरू किया है, तो कृपया Bazel के ट्यूटोरियल की मदद से, Android डिवाइस बनाना शुरू करें.
खास जानकारी
Bazel कई अलग-अलग बिल्ड कॉन्फ़िगरेशन में चल सकता है. इनमें कई ऐसे कॉन्फ़िगरेशन शामिल हैं जो Android नेटिव डेवलपमेंट किट (एनडीके) टूलचेन का इस्तेमाल करते हैं. इसका मतलब है कि Android के लिए सामान्य cc_library
और cc_binary
नियमों को सीधे Bazel में इकट्ठा किया जा सकता है. Bazel, android_ndk_repository
रिपॉज़िटरी
नियम का इस्तेमाल करके यह काम करता है.
ज़रूरी शर्तें
कृपया पक्का करें कि आपने Android SDK टूल और एनडीके इंस्टॉल किया हो.
SDK टूल और एनडीके सेट अप करने के लिए, अपने 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 और इसके बाद का वर्शन) का नया वर्शन इस्तेमाल किया जा रहा है, तो Starlark android_ndk_repository
वर्शन को लागू करें.
इसके README
में दिए गए निर्देशों का पालन करें.
तुरंत शुरू करने का तरीका
अगर आपको Android के लिए C++ बनाना है, तो अपने
android_binary
या android_library
नियमों में cc_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
Bazel सभी cc_libraries को एक ही शेयर किए गए ऑब्जेक्ट (.so
) फ़ाइल में इकट्ठा करता है. इसे डिफ़ॉल्ट रूप से, armeabi-v7a
एबीआई के लिए टारगेट किया गया है. इसे बदलने या एक साथ कई एबीआई के
बिल बनाने के लिए, टारगेट एबीआई को कॉन्फ़िगर
करने वाला सेक्शन देखें.
सेटअप का उदाहरण
यह उदाहरण Bazel के उदाहरण स्टोर करने की जगह में उपलब्ध है.
BUILD.bazel
फ़ाइल में, android_binary
,
android_library
, और cc_library
नियमों के साथ तीन टारगेट तय किए गए हैं.
android_binary
टॉप-लेवल टारगेट, APK बनाता है.
cc_library
टारगेट में एक C++ सोर्स फ़ाइल होती है, जिसमें JNI फ़ंक्शन लागू होता है:
#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
को लोड करता है और JNI फ़ंक्शन के लिए मेथड सिग्नेचर के बारे में बताता है:
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:arm |
arm64-v8a |
@platforms//cpu:arm64 |
x86 |
@platforms//cpu:x86_32 |
x86_64 |
@platforms//cpu:x86_64 |
साथ ही, एक से ज़्यादा आर्किटेक्चर वाले APK के लिए, एक से ज़्यादा लेबल पास किए जाते हैं. जैसे: --android_platforms=//:arm64,//:x86_64
(यह मानते हुए कि आपने उन्हें अपनी टॉप-लेवल की BUILD.bazel
फ़ाइल में तय किया है).
Bazel किसी डिफ़ॉल्ट Android प्लैटफ़ॉर्म को नहीं चुन पा रहा है. इसलिए, किसी एक को --android_platforms
के साथ तय करना और बताना ज़रूरी है.
एनडीके में हुए बदलाव और Android एपीआई लेवल के आधार पर, ये एबीआई उपलब्ध होते हैं:
NDK संशोधन | एबीआई |
---|---|
16 और उससे कम | आर्मेबी, Armeabi-v7a, Arm64-v8a, mips, mips64, x86, x86_64 |
17 साल और उससे ज़्यादा उम्र के बच्चों के लिए | Armeabi-v7a, Arm64-v8a, x86, x86_64 |
इन एबीआई के बारे में ज़्यादा जानकारी के लिए, एनडीके के दस्तावेज़ देखें.
एक से ज़्यादा एबीआई फ़ैट APK का सुझाव रिलीज़ बिल्ड के लिए नहीं दिया जाता है, क्योंकि वे APK का आकार बढ़ा देते हैं, लेकिन वे डेवलपमेंट और QA बिल्ड के लिए उपयोगी हो सकते हैं.
C++ स्टैंडर्ड चुनना
C++ स्टैंडर्ड के हिसाब से बनाने के लिए इन फ़्लैग का इस्तेमाल करें:
C++ स्टैंडर्ड | झंडा |
---|---|
C++98 | डिफ़ॉल्ट फ़्लैग की ज़रूरत नहीं है |
C++11 | --cxxopt=-std=c++11 |
C++14 | --cxxopt=-std=c++14 |
C+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_binary
का इस्तेमाल किए बिना, Android के लिए स्टैंडअलोन cc_binary
या cc_library
बनाने के लिए, --platforms
फ़्लैग का इस्तेमाल करें.
उदाहरण के लिए, यह मानते हुए कि आपने
my/platforms/BUILD
में Android प्लैटफ़ॉर्म के बारे में बताया है:
bazel build //my/cc/jni:target \
--platforms=//my/platforms:x86_64
इस तरीके से पूरा बिल्ड ट्री प्रभावित होता है.
इन फ़्लैग को project/.bazelrc
में, 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
के अपने-आप होने वाले कॉन्फ़िगरेशन ट्रांज़िशन पर भरोसा करें, जहां आपको ऐसे बहुत सारे टारगेट बनाने की उम्मीद है जिन पर आपका कंट्रोल नहीं है.