อย่าลืมนัดของเรา: BazelCon 2023 จะจัดขึ้นในวันที่ 24-25 ตุลาคมที่ Google ที่มิวนิก ดูข้อมูลเพิ่มเติม

บทแนะนําของ 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 (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 สร้างเครื่องมือ เพื่อสร้างแอป ซึ่งหมายความว่าคุณต้องเพิ่มข้อมูลบางอย่างในไฟล์ 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 (Command Prompt) 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 (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_sdk_repository เส้นทางไปยัง Android NDK จะอนุมานจากตัวแปรสภาพแวดล้อม ANDROID_NDK_HOME โดยค่าเริ่มต้น นอกจากนี้ คุณยังระบุเส้นทางให้ชัดเจนได้ด้วยแอตทริบิวต์ path ใน android_ndk_repository

อ่านข้อมูลเพิ่มเติมได้ที่การใช้ชุดพัฒนาซอฟต์แวร์ Android กับ Bazel

api_level คือ API เวอร์ชัน Android ที่ 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 จัดเก็บไฟล์แหล่งที่มาของตัวกลางที่สร้างโดยกฎ 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 ก่อนติดตั้งใช้งาน คุณยังเลือกติดตั้งแอปในโปรแกรมจําลอง Android ที่รวมอยู่ใน Android Studio ได้ด้วย โปรดตรวจสอบว่าโปรแกรมจําลองทํางานอยู่ก่อนเรียกใช้คําสั่งด้านล่าง

ป้อนข้อมูลต่อไปนี้

bazel mobile-install //src/main:app

ต่อไปให้ค้นหาและเปิดตัว "แอปบทแนะนํา Bazel":

แอปบทแนะนํา Bazel

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

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

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

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

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

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

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