Bazel 튜토리얼: Android 앱 빌드

참고: Android 앱 빌드에 Bazel을 사용하는 데 알려진 제한사항이 있습니다. rules_android 문제 페이지 를 방문하여 알려진 문제 목록을 확인하세요. Bazel팀과 오픈소스 소프트웨어 (OSS) 기여자가 알려진 문제를 해결하기 위해 적극적으로 노력하고 있지만 사용자는 Android 스튜디오가 Bazel 프로젝트를 공식적으로 지원하지 않는다는 점을 인지해야 합니다.

이 튜토리얼에서는 Bazel을 사용하여 간단한 Android 앱을 빌드하는 방법을 설명합니다.

Bazel은 Android 규칙을 사용하여 Android 앱 빌드를 지원합니다.

이 튜토리얼은 Windows, macOS, Linux 사용자를 대상으로 하며 Bazel 또는 Android 앱 개발 경험이 필요하지 않습니다. 이 튜토리얼에서는 Android 코드를 작성할 필요가 없습니다.

학습할 내용

이 튜토리얼에서는 다음 방법을 알아봅니다.

  • Bazel 및 Android 스튜디오를 설치하고 샘플 프로젝트를 다운로드하여 환경을 설정합니다.
  • 앱의 소스 코드 와 작업공간 디렉터리의 최상위 수준을 식별하는 MODULE.bazel 파일이 포함된 Bazel 작업공간을 설정합니다.
  • Android SDK와 같은 필수 외부 종속 항목에 대한 참조를 포함하도록 MODULE.bazel 파일을 업데이트합니다.
  • BUILD 파일을 만듭니다.
  • Bazel을 사용하여 앱을 빌드합니다.
  • Android 에뮬레이터 또는 실제 기기에 앱을 배포하고 실행합니다.

시작하기 전에

Bazel 설치

튜토리얼을 시작하기 전에 다음 소프트웨어를 설치하세요.

  • Bazel. 설치하려면 설치 안내를 따르세요.
  • Android 스튜디오. 설치하려면 Android 스튜디오 다운로드 단계를 따르세요. 설치 마법사를 실행하여 SDK를 다운로드하고 환경을 구성합니다.
  • (선택사항) Git. git을 사용하여 Android 앱 프로젝트를 다운로드합니다.

샘플 프로젝트 가져오기

샘플 프로젝트의 경우 Bazel의 예시 저장소에 있는 튜토리얼 Android 앱 프로젝트를 사용합니다.

이 앱에는 클릭하면 인사말을 출력하는 단일 버튼이 있습니다.

버튼 인사말

그림 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

주요 파일 및 디렉터리는 다음과 같습니다.

이름 위치
Android 매니페스트 파일 src/main/AndroidManifest.xmlsrc/main/java/com/example/bazel/AndroidManifest.xml
Android 소스 파일 src/main/java/com/example/bazel/MainActivity.javaGreeter.java
리소스 파일 디렉터리 src/main/java/com/example/bazel/res/

Bazel을 사용하여 빌드

작업공간 설정

작업공간은 하나 이상의 소프트웨어 프로젝트의 소스 파일을 포함하는 디렉터리이며 루트에 MODULE.bazel 파일이 있습니다.

MODULE.bazel 파일은 비어 있거나 프로젝트를 빌드하는 데 필요한 외부 종속 항목에 대한 참조를 포함할 수 있습니다.

먼저 다음 명령어를 실행하여 빈 MODULE.bazel 파일을 만듭니다.

OS 명령어
Linux, macOS touch MODULE.bazel
Windows (명령 프롬프트) type nul > MODULE.bazel
Windows (PowerShell) New-Item MODULE.bazel -ItemType file

Bazel 실행

이제 다음 명령어를 사용하여 Bazel이 올바르게 실행되고 있는지 확인할 수 있습니다.

bazel info workspace

Bazel이 현재 디렉터리의 경로를 출력하면 계속 진행할 수 있습니다. MODULE.bazel 파일이 없으면 다음과 같은 오류 메시지가 표시될 수 있습니다.

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

Android SDK와 통합

Bazel은 앱을 빌드하기 위해 Android SDK 빌드 도구 를 실행해야 합니다. 즉, Bazel이 빌드 도구를 찾을 위치를 알 수 있도록 MODULE.bazel 파일에 일부 정보를 추가해야 합니다.

MODULE.bazel 파일에 다음 줄을 추가합니다.

bazel_dep(name = "rules_android", version = "0.6.6")

remote_android_extensions = use_extension(
    "@rules_android//bzlmod_extensions:android_extensions.bzl",
    "remote_android_tools_extensions")
use_repo(remote_android_extensions, "android_tools")

android_sdk_repository_extension = use_extension("@rules_android//rules/android_sdk_repository:rule.bzl", "android_sdk_repository_extension")
use_repo(android_sdk_repository_extension, "androidsdk")

이렇게 하면 ANDROID_HOME 환경 변수가 참조하는 경로에 있는 Android SDK가 사용되고 해당 위치 내에 설치된 최신 API 수준과 최신 버전의 빌드 도구가 자동으로 감지됩니다.

ANDROID_HOME 변수를 Android SDK의 위치로 설정할 수 있습니다. Android 스튜디오의 SDK 관리자를 사용하여 설치된 SDK의 경로를 찾습니다. SDK가 기본 위치에 설치되어 있다고 가정하면 다음 명령어를 사용하여 ANDROID_HOME 변수를 설정할 수 있습니다.

OS 명령어
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"

위의 명령어는 현재 셸 세션에 대해서만 변수를 설정합니다. 영구적으로 설정하려면 다음 명령어를 실행하세요.

OS 명령어
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 앱으로 컴파일하려면 Android NDK도 다운로드하고 MODULE.bazel 파일에 다음 줄을 추가하여 rules_android_ndk를 사용해야 합니다.

bazel_dep(name = "rules_android_ndk", version = "0.1.3")

자세한 내용은 Bazel에서 Android 네이티브 개발 키트 사용 을 참고하세요.

SDK와 NDK의 API 수준을 동일한 값으로 설정할 필요는 없습니다. 이 페이지 에는 Android 출시 버전에서 NDK 지원 API 수준으로의 매핑이 포함되어 있습니다.

BUILD 파일 만들기

A BUILD 파일은 컴파일된 Android 리소스(aapt) 또는 클래스 파일(javac)과 같은 빌드 출력 집합과 종속 항목 간의 관계를 설명합니다. 이러한 종속 항목은 작업공간의 소스 파일 (Java, C++) 또는 기타 빌드 출력일 수 있습니다. BUILD 파일 은 Starlark라는 언어로 작성됩니다.

BUILD 파일은 Bazel의 패키지 계층 구조 라는 개념의 일부입니다. 패키지 계층 구조는 작업공간의 디렉터리 구조를 오버레이하는 논리적 구조입니다. 각 패키지는 관련 소스 파일 집합과 BUILD 파일이 포함된 디렉터리 (및 하위 디렉터리)입니다. 패키지에는 자체 BUILD 파일이 포함된 디렉터리를 제외한 모든 하위 디렉터리도 포함됩니다. 패키지 이름MODULE.bazel 파일을 기준으로 하는 BUILD 파일의 경로입니다.

디렉터리가 동일하게 구성될 수 있지만 Bazel's 패키지 계층 구조는 BUILD 파일이 있는 Android 앱 디렉터리의 Java 패키지 계층 구조와 개념적으로 다릅니다.

이 튜토리얼의 간단한 Android 앱의 경우 소스 파일은 src/main/ 단일 Bazel 패키지를 구성합니다. 더 복잡한 프로젝트에는 여러 중첩된 패키지가 있을 수 있습니다.

android_library 규칙 추가

BUILD 파일에는 Bazel의 여러 가지 선언 유형이 포함되어 있습니다. 가장 중요한 유형은 빌드 규칙으로, Bazel에 소스 파일 집합 또는 기타 종속 항목에서 중간 또는 최종 소프트웨어 출력을 빌드하는 방법을 알려줍니다. Bazel은 Android 앱을 빌드하는 데 사용할 수 있는 두 가지 빌드 규칙, android_libraryandroid_binary을 제공합니다.

이 튜토리얼에서는 먼저 android_library 규칙을 사용하여 Bazel에 Android 라이브러리 모듈을 앱 소스 코드 및 리소스 파일에서 빌드하도록 지시합니다. 그런 다음 android_binary 규칙을 사용하여 Bazel에 Android 애플리케이션 패키지를 빌드하는 방법을 알려줍니다.

BUILD 파일을 src/main/java/com/example/bazel 디렉터리에 만들고 새 android_library 대상을 선언합니다.

src/main/java/com/example/bazel/BUILD:

load("@rules_android//rules:rules.bzl", "android_library")

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 파일)를 빌드합니다.

src/main/ 디렉터리에 새 BUILD 파일을 만들고 새 android_binary 대상을 선언합니다.

src/main/BUILD:

load("@rules_android//rules:rules.bzl", "android_binary")

android_binary(
    name = "app",
    manifest = "//src/main/java/com/example/bazel:AndroidManifest.xml",
    deps = ["//src/main/java/com/example/bazel:greeter_activity"],
)

여기서 deps 속성은 위에 있는 BUILD 파일에 추가한 greeter_activity 규칙 의 출력을 참조합니다. 즉, 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은 중간 및 최종 빌드 작업의 출력을 사용자별, 작업공간별 출력 디렉터리 집합에 배치합니다. 이러한 디렉터리는 `MODULE.bazel` 파일이 있는 프로젝트 디렉터리의 최상위 수준에 있는 다음 위치에서 심볼릭 링크됩니다.MODULE.bazel

  • bazel-bin은 바이너리 실행 파일 및 기타 실행 가능한 빌드 출력을 저장합니다.
  • bazel-genfiles는 Bazel 규칙에 의해 생성되는 중간 소스 파일을 저장합니다.
  • bazel-out은 다른 유형의 빌드 출력을 저장합니다.

Bazel은 Android .apk 파일을 android_binary 규칙 을 사용하여 생성된 bazel-bin/src/main 디렉터리에 저장합니다. 여기서 하위 디렉터리 이름 src/main은 Bazel 패키지의 이름에서 파생됩니다.

명령 프롬프트에서 이 디렉터리의 콘텐츠를 나열하고 app.apk 파일을 찾습니다.

OS 명령어
Linux, macOS ls bazel-bin/src/main
Windows (명령 프롬프트) dir bazel-bin\src\main
Windows (PowerShell) ls bazel-bin\src\main

앱 실행

이제 명령줄에서 bazel mobile-install을 사용하여 연결된 Android 기기 또는 에뮬레이터에 앱을 배포할 수 있습니다. 이 명령어는 Android 디버그 브리지 (adb)를 사용하여 기기와 통신합니다. 배포 전에 Android 디버그 브리지 의 안내에 따라 adb를 사용하도록 기기를 설정해야 합니다. Android 스튜디오에 포함된 Android 에뮬레이터에 앱을 설치할 수도 있습니다. 아래 명령어를 실행하기 전에 에뮬레이터가 실행 중인지 확인하세요.

다음을 입력합니다.

bazel mobile-install //src/main:app \
  --mode=skylark \
  --mobile_install_aspect=@rules_android//mobile_install:mi.bzl \
  --mobile_install_supported_rules=android_binary \
  --java_runtime_version=17 \
  --java_language_version=17 \
  --tool_java_runtime_version=17 \
  --tool_java_language_version=17

모바일 설치에 필요한 추가 플래그는 프로젝트의 bazelrc 파일에 추가할 수 있습니다. 모바일 설치 관련 플래그 (--mode, --mobile_install*)는 Bazel 8.4.0부터 더 이상 필요하지 않습니다. 언어 및 런타임 버전의 다양한 Java 플래그 는 작업공간의 Java 구성에 따라 필요할 수 있습니다. 모바일 설치 하위 도구에는 언어 및 런타임 수준이 17 이상이어야 합니다.

이제 'Bazel 튜토리얼 앱'이 자동으로 설치되고 실행됩니다.

Bazel 튜토리얼 앱

그림 2. Bazel 튜토리얼 앱

축하합니다. 첫 번째 Bazel 빌드 Android 앱을 설치했습니다.

추가 자료

자세한 내용은 다음 페이지를 참고하세요.

즐거운 빌드 되세요.