หมายเหตุ: การใช้ Bazel เพื่อสร้างแอป Android มีข้อจํากัดที่ทราบ โปรดไปที่ team-Android hotlist ของ GitHub เพื่อดูรายการปัญหาที่ทราบ แม้ว่าทีม Bazel และผู้มีส่วนร่วมในซอฟต์แวร์โอเพนซอร์ส (OSS) จะพยายามแก้ไขปัญหาที่ทราบแล้ว แต่ผู้ใช้ควรทราบว่า Android Studio ไม่รองรับโปรเจ็กต์ Bazel อย่างเป็นทางการ
บทแนะนำนี้ครอบคลุมวิธีสร้างแอป Android แบบง่ายโดยใช้ Bazel
Bazel รองรับการสร้างแอป Android โดยใช้กฎ Android
บทแนะนำนี้มีไว้สำหรับผู้ใช้ Windows, macOS และ Linux และไม่จําเป็นต้องมีประสบการณ์ด้าน Bazel หรือการพัฒนาแอป Android คุณไม่จำเป็นต้องเขียนโค้ด Android ในบทแนะนำนี้
สิ่งที่คุณจะได้เรียนรู้
ในบทแนะนำนี้ คุณจะได้เรียนรู้วิธีทำสิ่งต่อไปนี้
- ตั้งค่าสภาพแวดล้อมโดยการติดตั้ง Bazel และ Android Studio รวมถึงดาวน์โหลดโปรเจ็กต์ตัวอย่าง
- ตั้งค่า workspace ของ Bazel ที่มีซอร์สโค้ดสําหรับแอปและไฟล์
WORKSPACE
ที่ระบุระดับบนสุดของไดเรกทอรี workspace - อัปเดตไฟล์
WORKSPACE
ให้อ้างอิงถึงทรัพยากร Dependency ภายนอกที่จําเป็น เช่น Android SDK - สร้างไฟล์
BUILD
- สร้างแอปด้วย Bazel
- ติดตั้งใช้งานและเรียกใช้แอปในโปรแกรมจำลอง Android หรืออุปกรณ์จริง
ก่อนเริ่มต้น
ติดตั้ง Bazel
ก่อนเริ่มบทแนะนำ ให้ติดตั้งซอฟต์แวร์ต่อไปนี้
- บาเซล ทำตามวิธีการติดตั้งเพื่อติดตั้ง
- Android Studio หากต้องการติดตั้ง ให้ทำตามขั้นตอนเพื่อดาวน์โหลด Android Studio เรียกใช้วิซาร์ดการตั้งค่าเพื่อดาวน์โหลด SDK และกำหนดค่าสภาพแวดล้อม
- (ไม่บังคับ) Git ใช้
git
เพื่อดาวน์โหลดโปรเจ็กต์แอป Android
รับโปรเจ็กต์ตัวอย่าง
สำหรับโปรเจ็กต์ตัวอย่าง ให้ใช้โปรเจ็กต์แอป Android พื้นฐานในที่เก็บตัวอย่างของ Bazel
แอปนี้มีปุ่มเดียวที่แสดงคําทักทายเมื่อมีการคลิก
รูปที่ 1 คําทักทายของปุ่มแอป Android
โคลนที่เก็บด้วย git
(หรือดาวน์โหลดไฟล์ ZIP โดยตรง) ดังนี้
git clone https://github.com/bazelbuild/examples
โปรเจ็กต์ตัวอย่างสำหรับบทแนะนำนี้อยู่ใน examples/android/tutorial
คุณจะเรียกใช้คําสั่งในไดเรกทอรีนี้ตลอดบทแนะนําที่เหลือ
ตรวจสอบไฟล์ต้นฉบับ
ดูไฟล์ต้นฉบับของแอป
.
├── README.md
└── src
└── main
├── AndroidManifest.xml
└── java
└── com
└── example
└── bazel
├── AndroidManifest.xml
├── Greeter.java
├── MainActivity.java
└── res
├── layout
│ └── activity_main.xml
└── values
├── colors.xml
└── strings.xml
ไฟล์และไดเรกทอรีหลักมีดังนี้
ชื่อ | ตำแหน่ง |
---|---|
ไฟล์ Manifest ของ Android | src/main/AndroidManifest.xml และ src/main/java/com/example/bazel/AndroidManifest.xml |
ไฟล์ต้นฉบับของ Android | src/main/java/com/example/bazel/MainActivity.java และ Greeter.java |
ไดเรกทอรีไฟล์ทรัพยากร | src/main/java/com/example/bazel/res/ |
บิลด์ด้วย Bazel
ตั้งค่าพื้นที่ทํางาน
พื้นที่ทํางานคือไดเรกทอรีที่มีไฟล์ซอร์สโค้ดสําหรับโปรเจ็กต์ซอฟต์แวร์อย่างน้อย 1 โปรเจ็กต์ และมีไฟล์ WORKSPACE
ที่รูท
ไฟล์ WORKSPACE
อาจว่างเปล่าหรือมีการอ้างอิงไปยังทรัพยากร Dependency ภายนอกที่จำเป็นต่อการสร้างโปรเจ็กต์
ก่อนอื่น ให้เรียกใช้คําสั่งต่อไปนี้เพื่อสร้างไฟล์ WORKSPACE
ว่าง
ระบบปฏิบัติการ | คำสั่ง |
---|---|
Linux, macOS | touch WORKSPACE |
Windows (Command Prompt) | type nul > WORKSPACE |
Windows (PowerShell) | New-Item WORKSPACE -ItemType file |
ใช้งาน Bazel
ตอนนี้คุณจะตรวจสอบได้ว่า Bazel ทำงานอย่างถูกต้องหรือไม่ด้วยคำสั่งต่อไปนี้
bazel info workspace
หาก Bazel พิมพ์เส้นทางของไดเรกทอรีปัจจุบัน แสดงว่าคุณพร้อมใช้งาน หากไม่มีไฟล์ WORKSPACE
อยู่ คุณอาจเห็นข้อความแสดงข้อผิดพลาดอย่างเช่น
ERROR: The 'info' command is only supported from within a workspace.
ผสานรวมกับ Android SDK
Bazel ต้องใช้ Android SDK เพื่อทำเครื่องมือสร้างของ Android เพื่อบิลด์แอป ซึ่งหมายความว่าคุณต้องเพิ่มข้อมูลบางอย่างลงในไฟล์ WORKSPACE
เพื่อให้ Bazel รู้ว่าจะหาข้อมูลเหล่านั้นได้จากที่ใด
เพิ่มบรรทัดต่อไปนี้ลงในไฟล์ WORKSPACE
android_sdk_repository(name = "androidsdk")
ซึ่งจะใช้ Android SDK ในเส้นทางที่อ้างอิงโดยตัวแปรสภาพแวดล้อม ANDROID_HOME
และตรวจหา API ระดับสูงสุดและเครื่องมือสร้างเวอร์ชันล่าสุดที่ติดตั้งภายในตำแหน่งนั้นโดยอัตโนมัติ
คุณสามารถตั้งค่าตัวแปร ANDROID_HOME
เป็นตำแหน่งของ Android SDK ค้นหาเส้นทางไปยัง SDK ที่ติดตั้งโดยใช้ SDK Manager ของ Android Studio
สมมติว่าติดตั้ง SDK ไว้ในตำแหน่งเริ่มต้น คุณสามารถใช้คำสั่งต่อไปนี้เพื่อตั้งค่าตัวแปร ANDROID_HOME
ระบบปฏิบัติการ | คำสั่ง |
---|---|
Linux | export ANDROID_HOME=$HOME/Android/Sdk/ |
macOS | export ANDROID_HOME=$HOME/Library/Android/sdk |
Windows (Command Prompt) | set ANDROID_HOME=%LOCALAPPDATA%\Android\Sdk |
Windows (PowerShell) | $env:ANDROID_HOME="$env:LOCALAPPDATA\Android\Sdk" |
คำสั่งข้างต้นจะตั้งค่าตัวแปรสำหรับเซสชันเชลล์ปัจจุบันเท่านั้น หากต้องการทำให้ค่าดังกล่าวมีผลถาวร ให้เรียกใช้คำสั่งต่อไปนี้
ระบบปฏิบัติการ | คำสั่ง |
---|---|
Linux | echo "export ANDROID_HOME=$HOME/Android/Sdk/" >> ~/.bashrc |
macOS | echo "export ANDROID_HOME=$HOME/Library/Android/Sdk/" >> ~/.bashrc |
Windows (Command Prompt) | setx ANDROID_HOME "%LOCALAPPDATA%\Android\Sdk" |
Windows (PowerShell) | [System.Environment]::SetEnvironmentVariable('ANDROID_HOME', "$env:LOCALAPPDATA\Android\Sdk", [System.EnvironmentVariableTarget]::User) |
นอกจากนี้ คุณยังระบุเส้นทางสัมบูรณ์ของ Android SDK, ระดับ API และเวอร์ชันของเครื่องมือสร้างที่จะใช้อย่างชัดแจ้งได้ด้วยการรวมแอตทริบิวต์ path
, api_level
และ build_tools_version
หากไม่ได้ระบุ api_level
และ build_tools_version
กฎ android_sdk_repository
จะใช้เวอร์ชันล่าสุดที่เกี่ยวข้องซึ่งมีอยู่ใน SDK คุณสามารถระบุการผสมผสานแอตทริบิวต์เหล่านี้ได้ ตราบใดที่แอตทริบิวต์ดังกล่าวมีอยู่ใน SDK เช่น
android_sdk_repository(
name = "androidsdk",
path = "/path/to/Android/sdk",
api_level = 25,
build_tools_version = "30.0.3"
)
ใน Windows โปรดทราบว่าแอตทริบิวต์ path
ต้องใช้เส้นทางแบบผสม กล่าวคือ เส้นทาง Windows ที่มีเครื่องหมายทับ
android_sdk_repository(
name = "androidsdk",
path = "c:/path/to/Android/sdk",
)
ไม่บังคับ: หากต้องการคอมไพล์โค้ดเนทีฟลงในแอป Android คุณยังต้องดาวน์โหลด Android NDK และบอก Bazel ว่าจะค้นหาโค้ดดังกล่าวได้จากที่ใดโดยเพิ่มบรรทัดต่อไปนี้ลงในไฟล์ WORKSPACE
android_ndk_repository(name = "androidndk")
ระบบจะอนุมานเส้นทางไปยัง Android NDK จากตัวแปรสภาพแวดล้อม ANDROID_NDK_HOME
โดยค่าเริ่มต้น ซึ่งคล้ายกับ android_sdk_repository
นอกจากนี้ คุณยังระบุเส้นทางอย่างชัดเจนได้ด้วยแอตทริบิวต์ path
ใน android_ndk_repository
ดูข้อมูลเพิ่มเติมได้ที่การใช้ Android Native Development Kit กับ Bazel
api_level
คือเวอร์ชันของ Android API ที่ SDK และ NDK กำหนดเป้าหมาย เช่น 23 สำหรับ Android 6.0 และ 25 สำหรับ Android 7.1 หากไม่ได้ตั้งค่าอย่างชัดเจน api_level
จะมีค่าเริ่มต้นเป็นระดับ API สูงสุดที่ใช้ได้สำหรับ android_sdk_repository
และ android_ndk_repository
คุณไม่จำเป็นต้องตั้งค่าระดับ API เป็นค่าเดียวกันสำหรับ SDK และ NDK หน้านี้ มีแผนที่ตั้งแต่เวอร์ชัน Android ไปจนถึงระดับ API ที่ NDK รองรับ
สร้างไฟล์ BUILD
ไฟล์ BUILD
จะอธิบายความสัมพันธ์ระหว่างชุดเอาต์พุตของบิลด์ เช่น ทรัพยากร Android ที่คอมไพล์แล้วจาก aapt
หรือไฟล์คลาสจาก javac
กับทรัพยากรที่ต้องพึ่งพา ทรัพยากร Dependency เหล่านี้อาจเป็นไฟล์ซอร์ส (Java, C++) ในพื้นที่ทำงานหรือเอาต์พุตอื่นๆ ของบิลด์ ไฟล์ BUILD
เขียนด้วยภาษาที่เรียกว่า Starlark
ไฟล์ BUILD
เป็นส่วนหนึ่งของแนวคิดใน Bazel ซึ่งเรียกกันว่าลำดับชั้นของแพ็กเกจ
ลำดับชั้นแพ็กเกจเป็นโครงสร้างเชิงตรรกะที่ซ้อนทับโครงสร้างไดเรกทอรีในพื้นที่ทำงาน แพ็กเกจแต่ละรายการคือไดเรกทอรี (และไดเรกทอรีย่อย) ที่มีชุดไฟล์ต้นทางที่เกี่ยวข้องและไฟล์ BUILD
แพ็กเกจนี้ยังรวมไดเรกทอรีย่อยทั้งหมดด้วย ยกเว้นไดเรกทอรีย่อยที่มีไฟล์ BUILD
ของตัวเอง ชื่อแพ็กเกจคือเส้นทางไปยังไฟล์ BUILD
ที่สัมพันธ์กับ WORKSPACE
โปรดทราบว่าลําดับชั้นของแพ็กเกจ Bazel แตกต่างกับลําดับชั้นของแพ็กเกจ Java ในไดเรกทอรีแอป Android ที่มีไฟล์ BUILD
อยู่ แม้ว่าไดเรกทอรีจะจัดระเบียบเหมือนกันก็ตาม
สําหรับแอป Android แบบง่ายในบทแนะนํานี้ ไฟล์ต้นฉบับใน src/main/
จะประกอบกันเป็นแพ็กเกจ Bazel เดียว โปรเจ็กต์ที่ซับซ้อนมากขึ้นอาจมีแพ็กเกจที่ฝังอยู่หลายรายการ
เพิ่มกฎ android_library
ไฟล์ BUILD
มีการประกาศหลายประเภทสำหรับ Bazel ประเภทที่สำคัญที่สุดคือกฎการสร้าง ซึ่งจะบอกวิธีการสร้างเอาต์พุตของซอฟต์แวร์ระดับกลางหรือขั้นสุดท้ายจากชุดไฟล์ต้นทางหรือทรัพยากร Dependency อื่นๆ Bazel มีกฎการสร้าง 2 รายการ ได้แก่ android_library
และ android_binary
ซึ่งคุณใช้สร้างแอป Android ได้
ในบทแนะนํานี้ คุณจะใช้android_library
กฎเพื่อบอก Bazel ให้สร้างโมดูลไลบรารี Android จากซอร์สโค้ดของแอปและไฟล์ทรัพยากร จากนั้นคุณจะใช้กฎ android_binary
เพื่อบอก Bazel ถึงวิธีสร้างแพ็กเกจแอปพลิเคชัน Android
สร้างไฟล์ BUILD
ใหม่ในไดเรกทอรี src/main/java/com/example/bazel
และประกาศเป้าหมาย android_library
ใหม่ ดังนี้
src/main/java/com/example/bazel/BUILD
:
package(
default_visibility = ["//src:__subpackages__"],
)
android_library(
name = "greeter_activity",
srcs = [
"Greeter.java",
"MainActivity.java",
],
manifest = "AndroidManifest.xml",
resource_files = glob(["res/**"]),
)
กฎการสร้าง android_library
มีชุดแอตทริบิวต์ที่ระบุข้อมูลที่ Bazel ต้องใช้ในการสร้างโมดูลไลบรารีจากไฟล์ต้นฉบับ
โปรดทราบว่าชื่อของกฎคือ greeter_activity
คุณจะอ้างอิงกฎโดยใช้ชื่อนี้เป็นทรัพยากรในกฎ android_binary
เพิ่มกฎ android_binary
กฎ android_binary
จะสร้างแพ็กเกจแอปพลิเคชัน Android (ไฟล์ .apk
) สําหรับแอปของคุณ
สร้างไฟล์ BUILD
ใหม่ในไดเรกทอรี src/main/
และประกาศเป้าหมาย android_binary
ใหม่
src/main/BUILD
:
android_binary(
name = "app",
manifest = "AndroidManifest.xml",
deps = ["//src/main/java/com/example/bazel:greeter_activity"],
)
ในที่นี้ แอตทริบิวต์ deps
จะอ้างอิงเอาต์พุตของกฎ greeter_activity
ที่เพิ่มลงในไฟล์ BUILD
ด้านบน ซึ่งหมายความว่าเมื่อ Bazel บิลด์เอาต์พุตของกฎนี้ ระบบจะตรวจสอบก่อนว่ามีการบิลด์เอาต์พุตของกฎไลบรารี greeter_activity
ไว้แล้วและเป็นเวอร์ชันล่าสุดหรือไม่ แต่หากไม่เป็นเช่นนั้น Bazel จะสร้างไฟล์
และใช้เอาต์พุตนั้นเพื่อสร้างไฟล์แพ็กเกจแอปพลิเคชัน
ทีนี้บันทึกและปิดไฟล์
สร้างแอป
ลองสร้างแอปเลย เรียกใช้คําสั่งต่อไปนี้เพื่อสร้างเป้าหมาย android_binary
bazel build //src/main:app
คำสั่งย่อย build
จะสั่งให้ Bazel บิลด์เป้าหมายที่ตามมา เป้าหมายจะระบุเป็นชื่อกฎการสร้างภายในไฟล์ BUILD
พร้อมกับเส้นทางแพ็กเกจที่สัมพันธ์กับไดเรกทอรีเวิร์กスペース ในตัวอย่างนี้ เป้าหมายคือ app
และเส้นทางแพ็กเกจคือ //src/main/
โปรดทราบว่าในบางครั้งคุณอาจละเว้นเส้นทางแพ็กเกจหรือชื่อเป้าหมายได้ ทั้งนี้ขึ้นอยู่กับไดเรกทอรีการทำงานปัจจุบันที่บรรทัดคำสั่งและชื่อของเป้าหมาย ดูรายละเอียดเพิ่มเติมเกี่ยวกับป้ายกำกับและเส้นทางเป้าหมายได้ในป้ายกำกับ
Bazel จะเริ่มสร้างแอปตัวอย่าง ระหว่างขั้นตอนการสร้าง เอาต์พุตของแอปจะมีลักษณะคล้ายกับด้านล่างนี้
INFO: Analysed target //src/main:app (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //src/main:app up-to-date:
bazel-bin/src/main/app_deploy.jar
bazel-bin/src/main/app_unsigned.apk
bazel-bin/src/main/app.apk
ค้นหาเอาต์พุตของบิลด์
Bazel จะใส่เอาต์พุตของทั้งการดำเนินการบิลด์ขั้นกลางและขั้นสุดท้ายไว้ในชุดไดเรกทอรีเอาต์พุตต่อผู้ใช้ต่อเวิร์กสเปซ ไดเรกทอรีเหล่านี้เป็นลิงก์สัญลักษณ์จากตำแหน่งต่อไปนี้ที่ระดับบนสุดของไดเรกทอรีโปรเจ็กต์ โดยที่ WORKSPACE
คือ
bazel-bin
จัดเก็บไฟล์ปฏิบัติการของไบนารีและเอาต์พุตบิลด์อื่นๆ ที่เรียกใช้ได้bazel-genfiles
จัดเก็บไฟล์ต้นฉบับสื่อกลางที่สร้างขึ้นโดยกฎ Bazelbazel-out
จัดเก็บเอาต์พุตบิลด์ประเภทอื่นๆ
Bazel จะจัดเก็บไฟล์ .apk
ของ Android ที่สร้างขึ้นโดยใช้กฎ android_binary
ในไดเรกทอรี bazel-bin/src/main
โดยที่ชื่อไดเรกทอรีย่อย src/main
จะมาจากชื่อแพ็กเกจ Bazel
ที่พรอมต์คำสั่ง ให้แสดงรายการเนื้อหาของไดเรกทอรีนี้และค้นหาไฟล์ app.apk
ระบบปฏิบัติการ | คำสั่ง |
---|---|
Linux, macOS | ls bazel-bin/src/main |
Windows (Command Prompt) | dir bazel-bin\src\main |
Windows (PowerShell) | ls bazel-bin\src\main |
เรียกใช้แอป
คุณทำให้แอปใช้งานได้ในอุปกรณ์ Android ที่เชื่อมต่อหรือโปรแกรมจำลองจากบรรทัดคำสั่งโดยใช้คำสั่ง bazel
mobile-install
ได้แล้ว คำสั่งนี้ใช้ Android Debug Bridge (adb
) เพื่อสื่อสารกับอุปกรณ์ คุณต้องตั้งค่าอุปกรณ์ให้ใช้ adb
โดยทำตามวิธีการใน Android Debug Bridge ก่อนทำให้ใช้งานได้ นอกจากนี้ คุณยังเลือกติดตั้งแอปในโปรแกรมจำลอง Android ที่รวมอยู่ใน Android Studio ได้ด้วย ตรวจสอบว่าโปรแกรมจําลองทํางานอยู่ก่อนเรียกใช้คําสั่งด้านล่าง
ป้อนข้อมูลต่อไปนี้
bazel mobile-install //src/main:app
ต่อไป ให้ค้นหาและเปิด "แอปบทแนะนำ Bazel"
รูปที่ 2 แอปบทแนะนำ Bazel
ยินดีด้วย คุณเพิ่งติดตั้งแอป Android ที่สร้าง Bazel แอปแรกของคุณ
โปรดทราบว่าคำสั่งย่อย mobile-install
ยังรองรับแฟล็ก --incremental
ที่สามารถใช้เพื่อติดตั้งใช้งานเฉพาะส่วนของแอปที่มีการเปลี่ยนแปลงนับตั้งแต่การทำให้ใช้งานได้ครั้งล่าสุด
นอกจากนี้ ยังรองรับ Flag --start_app
เพื่อเริ่มแอปทันทีที่ติดตั้ง
อ่านเพิ่มเติม
ดูรายละเอียดเพิ่มเติมได้ที่หน้าต่อไปนี้
- ปัญหาที่ยังไม่ดำเนินการใน GitHub
- ข้อมูลเพิ่มเติมเกี่ยวกับ mobile-install
- ผสานรวมการพึ่งพาภายนอก เช่น AppCompat, Guava และ JUnit จากที่เก็บ Maven โดยใช้ rules_jvm_external
- ทำการทดสอบ Robolectric ด้วยการผสานรวม robolectric-bazel
- การทดสอบแอปด้วยการทดสอบเครื่องมือวัดประสิทธิภาพของ Android
- การผสานรวมโค้ด C และ C++ เข้ากับแอป Android ด้วย NDK
- ดูโปรเจ็กต์ตัวอย่าง Bazel เพิ่มเติมของภาษาต่อไปนี้
ขอให้สนุกกับการสร้าง