บทแนะนำ Bazel: สร้างแอป Android

รายงานปัญหา ดูแหล่งที่มา

หมายเหตุ: การใช้ Bazel เพื่อสร้างแอป Android มีข้อจำกัดที่ทราบ ไปที่รายการด่วนสำหรับทีม Android ของ GitHub เพื่อดูรายการปัญหาที่ทราบ แม้ว่าทีม Bazel และผู้ร่วมให้ข้อมูลซอฟต์แวร์โอเพนซอร์ส (OSS) จะทำงานอย่างแข็งขันเพื่อแก้ไขปัญหาที่ทราบ แต่ผู้ใช้ควรทราบว่า Android Studio ไม่ได้สนับสนุนโครงการของ Bazel อย่างเป็นทางการ

บทแนะนำนี้ครอบคลุมวิธีสร้างแอป Android แบบง่ายๆ โดยใช้ Bazel

Bazel รองรับการสร้างแอป Android โดยใช้กฎของ Android

บทแนะนำนี้มีไว้สำหรับผู้ใช้ Windows, macOS และ Linux และไม่มีประสบการณ์ในการพัฒนาแอป Bazel หรือ Android คุณไม่จำเป็นต้องเขียนโค้ด Android ในบทแนะนำนี้

สิ่งที่คุณจะได้เรียนรู้

ในบทแนะนำนี้ คุณจะได้เรียนรู้วิธีการต่อไปนี้

  • ตั้งค่าสภาพแวดล้อมของคุณโดยการติดตั้ง Bazel และ Android Studio และดาวน์โหลดโปรเจ็กต์ตัวอย่าง
  • ตั้งค่าพื้นที่ทำงานของ Bazel ที่มีซอร์สโค้ดสำหรับแอป และไฟล์ WORKSPACE ที่ระบุระดับบนสุดของไดเรกทอรีพื้นที่ทำงาน
  • อัปเดตไฟล์ WORKSPACE ให้มีการอ้างอิงถึงทรัพยากร Dependency ภายนอกที่จำเป็น เช่น Android SDK
  • สร้างไฟล์ BUILD
  • สร้างแอปด้วย Bazel
  • ทำให้แอปใช้งานได้และเรียกใช้แอปในโปรแกรมจำลอง Android หรืออุปกรณ์จริง

ก่อนเริ่มต้น

ติดตั้ง Bazel

ก่อนที่จะเริ่มบทแนะนำ ให้ติดตั้งซอฟต์แวร์ต่อไปนี้

  • 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 (พร้อมท์คำสั่ง) type nul > WORKSPACE
Windows (PowerShell) New-Item WORKSPACE -ItemType file

บาเซลสำหรับวิ่ง

ตอนนี้คุณสามารถตรวจสอบว่า Bazel ทำงานได้อย่างถูกต้องหรือไม่ด้วยคำสั่งต่อไปนี้

bazel info workspace

หาก Bazel พิมพ์เส้นทางของไดเรกทอรีปัจจุบัน คุณก็พร้อมใช้งาน หากไม่มีไฟล์ WORKSPACE คุณอาจเห็นข้อความแสดงข้อผิดพลาดดังนี้

ERROR: The 'info' command is only supported from within a workspace.

ผสานรวมกับ Android SDK

Bazel จำเป็นต้องเรียกใช้เครื่องมือสร้าง Android SDK เพื่อสร้างแอป ซึ่งหมายความว่าคุณต้องเพิ่มข้อมูลบางส่วนลงในไฟล์ WORKSPACE เพื่อให้ Bazel ทราบว่าจะหาเครื่องมือเหล่านั้นได้ที่ไหน

เพิ่มบรรทัดต่อไปนี้ลงในไฟล์ WORKSPACE

android_sdk_repository(name = "androidsdk")

ซึ่งจะใช้ Android SDK ในเส้นทางที่อ้างอิงโดยตัวแปรสภาพแวดล้อม ANDROID_HOME และตรวจหา API ระดับสูงสุดและเครื่องมือสร้างเวอร์ชันล่าสุดที่ติดตั้งภายในตำแหน่งนั้นโดยอัตโนมัติ

คุณตั้งค่าตัวแปร ANDROID_HOME เป็นตำแหน่งของ Android SDK ได้ ค้นหาเส้นทางไปยัง SDK ที่ติดตั้งโดยใช้เครื่องมือจัดการ SDK ของ Android Studio สมมติว่าติดตั้ง SDK ไว้ในตำแหน่งเริ่มต้นแล้ว คุณจะใช้คำสั่งต่อไปนี้เพื่อตั้งค่าตัวแปร ANDROID_HOME ได้

ระบบปฏิบัติการ คำสั่ง
Linux export ANDROID_HOME=$HOME/Android/Sdk/
macOS export ANDROID_HOME=$HOME/Library/Android/sdk
Windows (พร้อมท์คำสั่ง) set ANDROID_HOME=%LOCALAPPDATA%\Android\Sdk
Windows (PowerShell) $env:ANDROID_HOME="$env:LOCALAPPDATA\Android\Sdk"

คำสั่งข้างต้นจะกำหนดตัวแปรสำหรับเซสชัน Shell ปัจจุบันเท่านั้น หากต้องการทำให้เป็นแบบถาวร ให้เรียกใช้คำสั่งต่อไปนี้

ระบบปฏิบัติการ คำสั่ง
Linux echo "export ANDROID_HOME=$HOME/Android/Sdk/" >> ~/.bashrc
macOS echo "export ANDROID_HOME=$HOME/Library/Android/Sdk/" >> ~/.bashrc
Windows (พร้อมท์คำสั่ง) 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 ที่มาพร้อม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 ทรัพยากร 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 คุณจะอ้างอิงกฎที่ใช้ชื่อนี้เป็นรายการทรัพยากร Dependency ในกฎ 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 จัดเก็บไฟล์แหล่งที่มาตัวกลางที่กฎ Baiel สร้างขึ้น
  • bazel-out จัดเก็บเอาต์พุตของบิลด์ประเภทอื่นๆ

Bazel จัดเก็บไฟล์ Android .apk ที่สร้างขึ้นโดยใช้กฎ android_binary ในไดเรกทอรี bazel-bin/src/main โดยชื่อไดเรกทอรีย่อย src/main ดึงมาจากชื่อแพ็กเกจ Bazel

ที่พรอมต์คำสั่ง ให้ระบุเนื้อหาของไดเรกทอรีนี้และค้นหาไฟล์ app.apk ดังนี้

ระบบปฏิบัติการ คำสั่ง
Linux, macOS ls bazel-bin/src/main
Windows (พร้อมท์คำสั่ง) 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"

แอปบทแนะนำ Bazel

รูปที่ 2 แอปสอนใช้งาน Bazel

ยินดีด้วย คุณเพิ่งติดตั้งแอป Android แอป Bazel ที่สร้างขึ้นเป็นครั้งแรก

โปรดทราบว่าคำสั่งย่อย mobile-install ยังรองรับแฟล็ก --incremental ที่สามารถใช้เพื่อทำให้ใช้งานได้เฉพาะบางส่วนของแอปที่มีการเปลี่ยนแปลงนับตั้งแต่การทำให้ใช้งานได้ครั้งล่าสุด

และยังรองรับแฟล็ก --start_app เพื่อเริ่มแอปทันทีหลังจากที่ติดตั้ง

อ่านเพิ่มเติม

ดูรายละเอียดเพิ่มเติมได้ที่หน้าเหล่านี้

ขอให้สนุกกับการสร้าง