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

หมายเหตุ: การใช้ 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

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

  • 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

ตั้งค่าพื้นที่ทํางาน

workspace คือไดเรกทอรีที่มีไฟล์แหล่งที่มาของโปรเจ็กต์ซอฟต์แวร์อย่างน้อย 1 โปรเจ็กต์ และมีไฟล์ WORKSPACE อยู่ที่รูท

ไฟล์ WORKSPACE อาจว่างเปล่าหรือมีการอ้างอิงถึงทรัพยากรภายนอกที่จําเป็นสําหรับการสร้างโปรเจ็กต์

ก่อนอื่นให้เรียกใช้คำสั่งต่อไปนี้เพื่อสร้างไฟล์ WORKSPACE ที่ว่างเปล่า

ระบบปฏิบัติการ คำสั่ง
Linux, macOS touch WORKSPACE
Windows (Command Prompt) 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 เพื่อทำเครื่องมือสร้างของ 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 กับทรัพยากรที่ต้องพึ่งพา ไลบรารีเหล่านี้อาจเป็นไฟล์ซอร์สโค้ด (Java, C++) ในพื้นที่ทํางานหรือเอาต์พุตการสร้างอื่นๆ ไฟล์ BUILD เขียนด้วยภาษาที่เรียกว่า Starlark

ไฟล์ BUILD เป็นส่วนหนึ่งของแนวคิดใน Bazel ที่เรียกว่าลําดับชั้นของแพ็กเกจ ลําดับชั้นของแพ็กเกจเป็นโครงสร้างเชิงตรรกะที่วางซ้อนโครงสร้างไดเรกทอรีในพื้นที่ทํางาน แพ็กเกจแต่ละรายการคือไดเรกทอรี (และไดเรกทอรีย่อย) ที่มีชุดไฟล์ต้นทางที่เกี่ยวข้องและไฟล์ BUILD แพ็กเกจนี้ยังรวมไดเรกทอรีย่อยทั้งหมดด้วย ยกเว้นไดเรกทอรีย่อยที่มีไฟล์ BUILD ของตัวเอง ชื่อแพ็กเกจคือเส้นทางไปยังไฟล์ BUILD ที่สัมพันธ์กับ WORKSPACE

โปรดทราบว่าลําดับชั้นของแพ็กเกจ Bazel แตกต่างกับลําดับชั้นของแพ็กเกจ Java ในไดเรกทอรีแอป Android ที่มีไฟล์ BUILD อยู่ แม้ว่าไดเรกทอรีจะจัดระเบียบเหมือนกันก็ตาม

สําหรับแอป Android แบบง่ายในบทแนะนํานี้ ไฟล์ต้นฉบับใน src/main/ จะประกอบกันเป็นแพ็กเกจ Bazel เดียว โปรเจ็กต์ที่ซับซ้อนมากขึ้นอาจมีแพ็กเกจที่ฝังอยู่หลายรายการ

เพิ่มกฎ android_library

ไฟล์ BUILD มีการประกาศหลายประเภทสําหรับ Bazel ประเภทที่สำคัญที่สุดคือกฎการสร้าง ซึ่งบอก Bazel ว่าจะสร้างเอาต์พุตซอฟต์แวร์ระดับกลางหรือขั้นสุดท้ายจากชุดไฟล์ต้นทางหรือไลบรารีอื่นๆ อย่างไร 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 จัดเก็บไฟล์ต้นฉบับสื่อกลางที่สร้างขึ้นโดยกฎ Bazel
  • bazel-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"

แอปบทแนะนำ Bazel

รูปที่ 2 แอปบทแนะนำ Bazel

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

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

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

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

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

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