अगर आपने पहले कभी Bazel का इस्तेमाल नहीं किया है, तो कृपया Bazel की मदद से Android बनाना ट्यूटोरियल से शुरुआत करें.
खास जानकारी
Bazel, कई अलग-अलग बिल्ड कॉन्फ़िगरेशन में काम कर सकता है. इनमें से कई ऐसे कॉन्फ़िगरेशन हैं जिनमें Android नेटिव डेवलपमेंट किट (NDK) टूलचेन का इस्तेमाल किया जाता है. इसका मतलब है कि Android के लिए, सामान्य cc_library
और cc_binary
नियमों को सीधे Bazel में संकलित किया जा सकता है. Bazel, 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 NDK के नए वर्शन (r22 और उसके बाद के वर्शन) का इस्तेमाल किया जा रहा है, तो android_ndk_repository
के Starlark वर्शन का इस्तेमाल करें.
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
टारगेट में, 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
को लोड करता है और 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
OS की पाबंदी का इस्तेमाल करना चाहिए. सीपीयू की सीमा को माइग्रेट करने के लिए, यह चार्ट देखें:
सीपीयू वैल्यू | प्लैटफ़ॉर्म |
---|---|
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
फ़ाइल में तय किया है).
Bazel, डिफ़ॉल्ट Android प्लैटफ़ॉर्म नहीं चुन सकता. इसलिए, --android_platforms
के साथ कोई एक प्लैटफ़ॉर्म तय करना ज़रूरी है.
NDK के रिविज़न और Android एपीआई लेवल के हिसाब से, ये एबीआई उपलब्ध हैं:
NDK का रिविज़न | एबीआई |
---|---|
16 और उससे कम | armeabi, armeabi-v7a, arm64-v8a, mips, mips64, x86, x86_64 |
17 साल और उससे ज़्यादा | armeabi-v7a, arm64-v8a, x86, x86_64 |
इन एबीआई के बारे में ज़्यादा जानकारी के लिए, NDK के दस्तावेज़ देखें.
रिलीज़ बंडल के लिए, मल्टी-एबीआई फ़ैट APK का सुझाव नहीं दिया जाता, क्योंकि इससे APK का साइज़ बढ़ जाता है. हालांकि, ये डेवलपमेंट और क्यूए बंडल के लिए काम के हो सकते हैं.
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
के साथ कंपाइलर और लिंकर फ़्लैग पास करने के बारे में ज़्यादा पढ़ें.
copts
और linkopts
का इस्तेमाल करके, cc_library
में कंपाइलर और लिंकर फ़्लैग को एट्रिब्यूट के तौर पर भी दिखाया जा सकता है. उदाहरण के लिए:
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
इस तरीके से, पूरे बिल्ड ट्री पर असर पड़ता है.
इन फ़्लैग को 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
से अपने-आप कॉन्फ़िगर होने वाले ट्रांज़िशन पर भरोसा करें. ऐसा तब करें, जब आपको ऐसे कई टारगेट बनाने हों जिनका कंट्रोल आपके पास न हो.