Bazel 빌드 환경

개요

Bazel은 Google에서 개발한 오픈 소스 빌드 및 테스트 자동화 도구입니다[1]. Google의 내부 빌드 시스템인 Blaze를 기반으로 하여 2015년 3월에 처음 공개되었으며[2], 대규모 소프트웨어 프로젝트를 위한 빠르고 신뢰할 수 있는 빌드 환경을 제공합니다.

핵심 특징

1. 빠른 빌드 속도

Bazel은 증분 빌드를 지원하여 변경된 소스 코드만 빌드할 수 있습니다[1]. 이를 통해 불필요한 작업을 최소화하고 빌드 시간을 크게 줄일 수 있습니다. 또한 자동으로 빌드 그래프를 생성하여 의존성 관리를 자동화합니다.

2. 다양한 언어 및 플랫폼 지원

Bazel은 Java, C++, Python, Go, Rust, Swift 등 다양한 프로그래밍 언어를 지원합니다[1]. 또한 Linux, macOS, Windows 등 여러 플랫폼에서 작동하며, 동일한 프로젝트에서 데스크톱, 서버, 모바일을 포함한 여러 플랫폼용 바이너리를 빌드할 수 있습니다.

3. 확장 가능성

Bazel은 사용자 정의 빌드 규칙을 통해 쉽게 확장할 수 있으며[1], 10만 개 이상의 소스 파일로 빌드를 처리하면서도 빠른 속도를 유지할 수 있습니다.

4. 재현 가능한 빌드

Bazel은 정확한 입력 파일 및 빌드 도구를 추적하고 고립된 실행 환경을 사용하여 모든 빌드가 재현 가능하도록 합니다[1]. 이를 통해 안정적이고 일관된 빌드 결과를 얻을 수 있습니다.

5. 캐싱 및 원격 실행

Bazel은 캐싱을 통해 이전에 빌드된 결과물을 재사용할 수 있으며[1], 원격 실행을 통해 클라우드 기반 인프라에서 빌드 및 테스트를 수행할 수 있습니다.

설치 방법

Windows 환경

  1. Microsoft Visual C++ Redistributable package 설치 필요[3]
  2. Bazelisk 사용 권장 – 자동 버전 관리 제공[3]
  3. Chocolatey를 통한 설치:
   choco install bazel

Linux 환경 (Ubuntu)

  1. JDK 설치:
   sudo apt-get install openjdk-8-jdk
  1. 패키지 저장소 추가:
   echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list
   curl https://bazel.build/bazel-release.pub.gpg | sudo apt-key add -
  1. Bazel 설치:
   sudo apt-get update && sudo apt-get install bazel
  1. 바이너리 설치 방법:
   wget https://github.com/bazelbuild/bazel/releases/download/<version>/bazel-<version>-installer-linux-x86_64.sh
   chmod +x bazel-<version>-installer-linux-x86_64.sh
   sudo ./bazel-<version>-installer-linux-x86_64.sh

프로젝트 구조

WORKSPACE 파일

WORKSPACE 파일은 Bazel 프로젝트의 루트 디렉터리에 위치하며, 프로젝트를 정의하고 외부 종속성을 관리합니다[4].

# WORKSPACE 파일 예시
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
    name = "com_google_googletest",
    sha256 = "d1663e2d7e0f1d1eaf59a5d16e5f5c0e9a8ee3c3e47862a0e8b8eb1da7f1a0d5",
    strip_prefix = "googletest-release-1.11.0",
    urls = ["https://github.com/google/googletest/archive/refs/tags/release-1.11.0.tar.gz"],
)

BUILD 파일

BUILD 파일은 프로젝트의 구성요소를 정의하고 빌드 규칙을 작성합니다[4]. 각 패키지(BUILD 파일이 있는 디렉터리)는 독립적인 빌드 단위가 됩니다.

# BUILD 파일 예시
cc_binary(
    name = "hello-world",
    srcs = ["hello-world.cc"],
)

cc_library(
    name = "greeter",
    srcs = ["greeter.cc"],
    hdrs = ["greeter.h"],
    visibility = ["//visibility:public"],
)

cc_test(
    name = "hello_test",
    srcs = ["hello_test.cc"],
    deps = [":greeter"],
)

주요 명령어

기본 빌드 명령어

명령어설명
bazel build소스 코드를 빌드하여 실행 가능한 출력물을 생성
bazel test테스트를 실행하고 결과를 보고
bazel run빌드 후 실행 가능한 타겟을 실행
bazel clean이전 빌드 결과물을 삭제
bazel infoBazel 빌드 시스템에 대한 정보를 출력

쿼리 명령어

명령어설명
bazel query빌드 시스템의 정보를 쿼리
bazel cquery구성된 타겟을 쿼리
bazel aquery액션 그래프를 쿼리

사용 예시

# 프로젝트 전체 빌드
bazel build //...

# 특정 타겟 빌드
bazel build //main:hello-world

# 테스트 실행
bazel test //...

# 특정 타겟 실행
bazel run //main:hello-world

# 종속성 그래프 확인
bazel query 'deps(//main:hello-world)'

빌드 규칙 (Rules)

언어별 규칙

Bazel은 다양한 언어별 규칙을 제공합니다[5]:

Java 규칙:

  • java_binary: Java 바이너리 생성
  • java_library: Java 라이브러리 생성
  • java_test: Java 테스트 실행

C++ 규칙:

  • cc_binary: C++ 바이너리 생성
  • cc_library: C++ 라이브러리 생성
  • cc_test: C++ 테스트 실행

Python 규칙:

  • py_binary: Python 바이너리 생성
  • py_library: Python 라이브러리 생성
  • py_test: Python 테스트 실행

타겟 참조 방법

타겟은 라벨을 통해 참조됩니다[6]:

//path/to/package:target-name

예시:

  • //:ProjectRunner – 루트 패키지의 ProjectRunner 타겟
  • //src/main/java/com/example/cmdline:runner – cmdline 패키지의 runner 타겟

Starlark 언어

개요

Starlark는 Bazel에서 사용되는 도메인 특화 언어로, Python의 하위 집합입니다[7]. BUILD 파일, 매크로, 빌드 규칙을 작성할 때 사용됩니다.

특징

  • Python3의 문법을 기반으로 함
  • 불변성(immutability)을 선호
  • 병렬 실행을 위한 컨텍스트 격리
  • 함수형 프로그래밍 지원

기본 문법

def fizz_buzz(n):
    """Print Fizz Buzz numbers from 1 to n."""
    for i in range(1, n + 1):
        s = ""
        if i % 3 == 0:
            s += "Fizz"
        if i % 5 == 0:
            s += "Buzz"
        print(s if s else i)

fizz_buzz(20)

성능 최적화

메모리 최적화

메모리 사용량을 제한하고 줄이는 방법[8]:

# 메모리 제한 설정
bazel --host_jvm_args=-Xmx2g build //...

# 메모리 최적화 플래그
bazel build --discard_analysis_cache \
             --nokeep_state_after_build \
             --notrack_incremental_state //...

빌드 속도 최적화

빌드 속도를 향상시키는 방법[9]:

  1. 로컬 캐시 사용:
   build --disk_cache=/path/to/cache/directory
  1. 병렬 빌드:
   bazel build --jobs=4 //...
  1. 원격 캐시 사용:
   build --remote_cache=https://cache.example.com

CI/CD 통합

GitHub Actions 예시

name: C++ CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Install Bazel
      run: |
        curl -L https://github.com/bazelbuild/bazel/releases/download/5.0.0/bazel-5.0.0-installer-linux-x86_64.sh -o bazel-installer.sh
        chmod +x bazel-installer.sh
        ./bazel-installer.sh --user
    - name: Build
      run: bazel build //...
    - name: Test
      run: bazel test //...

Docker 통합

Bazel을 Docker 환경에서 사용하는 방법[10]:

# Docker 컨테이너에서 Bazel 실행
docker run \
  -e USER="$(id -u)" \
  -u="$(id -u)" \
  -v /src/workspace:/src/workspace \
  -v /tmp/build_output:/tmp/build_output \
  -w /src/workspace \
  gcr.io/google/bazel:latest \
  --output_user_root=/tmp/build_output \
  build //...

외부 종속성 관리

http_archive 사용

웹에서 압축된 파일을 다운로드하여 종속성으로 사용:

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
    name = "bazel_skylib",
    sha256 = "1c531376ac7e5a180e0237938a2536de0c54d93f5c278634818e0efc952dd56c",
    urls = ["https://github.com/bazelbuild/bazel-skylib/releases/download/1.0.3/bazel-skylib-1.0.3.tar.gz"],
)

git_repository 사용

Git 저장소를 종속성으로 사용:

load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")

git_repository(
    name = "com_github_gflags_gflags",
    remote = "https://github.com/gflags/gflags.git",
    tag = "v2.2.2",
)

디버깅 및 문제 해결

일반적인 디버깅 옵션

# 상세한 빌드 정보 출력
bazel build --verbose_failures //...

# 샌드박스 디버깅
bazel build --sandbox_debug //...

# 빌드 프로파일링
bazel build --profile=/tmp/profile.json //...

캐시 문제 해결

# 캐시 정리
bazel clean --expunge

# 캐시 히트율 확인
bazel build --remote_cache=... --experimental_collect_system_network_usage //...

고급 기능

멀티 플랫폼 빌드

Bazel은 크로스 플랫폼 빌드를 지원합니다:

# 플랫폼별 빌드 설정
config_setting(
    name = "linux_x86_64",
    values = {"cpu": "k8"},
)

cc_binary(
    name = "hello",
    srcs = ["hello.cc"],
    linkopts = select({
        ":linux_x86_64": ["-static"],
        "//conditions:default": [],
    }),
)

커스텀 규칙 작성

Starlark를 사용하여 커스텀 빌드 규칙을 작성할 수 있습니다:

# custom_rule.bzl
def _custom_rule_impl(ctx):
    output = ctx.actions.declare_file(ctx.label.name + ".out")
    ctx.actions.run_shell(
        inputs = ctx.files.srcs,
        outputs = [output],
        command = "cat {} > {}".format(" ".join([f.path for f in ctx.files.srcs]), output.path),
    )
    return [DefaultInfo(files = depset([output]))]

custom_rule = rule(
    implementation = _custom_rule_impl,
    attrs = {
        "srcs": attr.label_list(allow_files = True),
    },
)

실제 사용 예시

Java 프로젝트 예시

# BUILD 파일
java_binary(
    name = "ProjectRunner",
    srcs = glob(["src/main/java/com/example/*.java"]),
    main_class = "com.example.ProjectRunner",
    deps = [":greeter"],
)

java_library(
    name = "greeter",
    srcs = ["src/main/java/com/example/Greeting.java"],
    visibility = ["//visibility:public"],
)

java_test(
    name = "greeter_test",
    srcs = ["src/test/java/com/example/GreetingTest.java"],
    deps = [
        ":greeter",
        "@junit_junit//jar",
    ],
    test_class = "com.example.GreetingTest",
)

C++ 프로젝트 예시

# BUILD 파일
cc_binary(
    name = "hello-world",
    srcs = ["hello-world.cc"],
    deps = [":hello-lib"],
)

cc_library(
    name = "hello-lib",
    srcs = ["hello-lib.cc"],
    hdrs = ["hello-lib.h"],
)

cc_test(
    name = "hello_test",
    srcs = ["hello_test.cc"],
    deps = [
        ":hello-lib",
        "@com_google_googletest//:gtest_main",
    ],
)

Bazel은 대규모 프로젝트에서 빠르고 안정적인 빌드 환경을 제공하는 강력한 도구입니다. 초기 설정이 복잡할 수 있지만, 한번 구성하면 일관되고 재현 가능한 빌드 환경을 제공하여 개발 생산성을 크게 향상시킬 수 있습니다.

출처
[1] Bazel이 그렇게 좋다는데 왜 좋은걸까? – Dak.so https://www.dak.so/bazel/what-is
[2] 바젤 (소프트웨어) – 위키백과, 우리 모두의 백과사전 https://ko.wikipedia.org/wiki/%EB%B0%94%EC%A0%A4_(%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4)
[3] [ Bazel ] Windows 환경에서 설치하기 | bazelisk https://mdpapa.tistory.com/205
[4] [Bazel 튜토리얼] Bazel 프로젝트 구성해보기: WORKSPACE & BUILD https://www.dak.so/bazel/organize
[5] [Bazel 튜토리얼] Bazel의 Rules & Targets 사용 방법 – Dak.so https://www.dak.so/bazel/rules-and-targets
[6] Bazel 튜토리얼: 자바 프로젝트 빌드 https://bazel.build/versions/7.3.0/start/java
[7] Starlark 언어 – Bazel https://bazel.build/versions/7.3.0/rules/language
[8] 메모리 최적화 – Bazel https://bazel.build/versions/7.3.0/advanced/performance/memory
[9] 반복 속도 최적화 – Bazel https://bazel.build/advanced/performance/iteration-speed
[10] Bazel Docker 컨테이너 시작하기 https://bazel.build/versions/6.5.0/install/docker-container
[11] Bazel 설치 사용법 – HiSEON https://hiseon.me/c/bazel-tutorial/
[12] Bazel 빌드 툴 명령어 정리 – Dak.so https://www.dak.so/bazel/commands
[13] Bazel 소개 https://bazel.build/versions/7.3.0/about/intro
[14] [Bazel 튜토리얼] Bazel 시작하기 – Dak.so https://www.dak.so/bazel/startup
[15] Bazel을 사용하여 프로그램 빌드 https://bazel.build/run/build
[16] Bazel이란? – butter_shower – 티스토리 https://butter-shower.tistory.com/232
[17] 명령어 및 옵션 – Bazel https://bazel.build/versions/6.5.0/docs/user-manual
[18] 빌드 시스템을 사용해야 하는 이유 | Bazel https://bazel.build/basics/build-systems
[19] 리눅스(Ubuntu)환경에서 Bazel 설치하기 – 아는대로 쓰는 블로그 https://jaeseolee3754.tistory.com/14
[20] 규칙 튜토리얼 – Bazel https://bazel.build/rules/rules-tutorial
[21] [ Linux ] ubuntu 20.04 버전 bazel( 바젤리스크 / 바젤 ) 설치 방법 https://hermeak1.tistory.com/22
[22] [Bazel 개념] Bazel 빌드 최적화를 하는 4가지 방법 – Dak.so https://www.dak.so/bazel/optimize
[23] 빌드 기본사항 | Bazel https://bazel.build/versions/7.1.0/basics
[24] Windows에 Bazel 설치 https://bazel.build/install/windows
[25] Windows에서 Bazel 사용 https://bazel.build/versions/7.0.0/configure/windows
[26] Bazel 빌드 툴에 대해서. – 조대협의 블로그 https://bcho.tistory.com/1160
[27] Ubuntu에 Bazel 설치 https://bazel.build/versions/7.0.0/install/ubuntu
[28] 작업공간, 패키지, 대상 – Bazel https://bazel.build/versions/6.3.0/concepts/build-ref
[29] Bazel – 낙타씨의 개발로그 – 티스토리 https://rudecamel.tistory.com/33
[30] BUILD 파일 | Bazel https://bazel.build/versions/7.0.0/concepts/build-files
[31] 외부 종속 항목 다루기 – Bazel https://bazel.build/versions/6.2.0/build/external
[32] Bazel을 사용하여 프로그램 빌드 https://bazel.build/versions/8.3.0/run/build
[33] WORKSPACE 파일 | Bazel https://bazel.build/versions/7.2.0/rules/lib/globals/workspace
[34] 규칙 https://bazel.build/versions/8.1.0/extending/rules
[35] Workspace 규칙 – Bazel https://bazel.build/versions/7.2.0/reference/be/workspace
[36] 규칙 https://bazel.build/extending/rules
[37] Bazel C++ 빌드 해보기 https://mullue.github.io/tools/2018/01/07/bazel-Cpp-build.html
[38] 일반 규칙 – Bazel https://bazel.build/versions/8.0.0/reference/be/general
[39] bazel – velog https://velog.io/@jk01019/bazel
[40] 플랫폼 및 도구 모음 규칙 – Bazel https://bazel.build/reference/be/platforms-and-toolchains
[41] BUILD 파일 – Bazel https://bazel.build/versions/7.0.0/rules/lib/globals/build
[42] 명령줄 참조 | Bazel https://bazel.build/versions/7.4.0/reference/command-line-reference
[43] 명령줄 참조 | Bazel https://bazel.build/versions/6.2.0/reference/command-line-reference
[44] macOS에 Bazel 설치 https://bazel.build/versions/6.0.0/install/os-x
[45] 명령어 및 옵션 – Bazel https://bazel.build/docs/user-manual
[46] 명령줄 참조 | Bazel https://bazel.build/reference/command-line-reference
[47] Docker Sandbox를 사용한 Bazel 원격 실행 문제 해결 https://bazel.build/remote/sandbox
[48] mod 명령어 | Bazel https://bazel.build/versions/7.1.0/external/mod-command
[49] 빌드 성능 측정항목 추출 – Bazel https://bazel.build/versions/7.6.0/advanced/performance/build-performance-metrics
[50] Bazel 잠금 파일 https://bazel.build/versions/7.1.0/external/lockfile
[51] bazelrc 구성 파일 작성 | Bazel https://bazel.build/run/bazelrc
[52] 빌드 성능 분석 – Bazel https://bazel.build/versions/8.1.0/advanced/performance/build-performance-breakdown
[53] 자주 묻는 질문(FAQ) – Bazel https://bazel.build/external/faq
[54] 일반 규칙 – Bazel https://bazel.build/reference/be/general
[55] 실적 최적화 | Bazel https://bazel.build/rules/performance
[56] Starlark – Kurtosis Docs https://docs.kurtosis.com/advanced-concepts/starlark
[57] http_archive/git_repository 기반 bazel 예제 구현하기 https://opencpps.tistory.com/922
[58] Starlark in Go – Google Open Source https://chromium.googlesource.com/external/github.com/google/starlark-go/+/HEAD/README.md
[59] Bazel 튜토리얼: C++ 프로젝트 빌드 https://bazel.build/versions/7.4.0/start/cpp
[60] 명령어 및 옵션 – Bazel https://bazel.build/versions/7.4.0/docs/user-manual
[61] Starlark 로드맵 | Bazel https://bazel.build/community/roadmaps-starlark
[62] Bazel 튜토리얼: 자바 프로젝트 빌드 https://bazel.build/start/java
[63] CodeQL 분석을 위한 코드 준비 – GitHub Enterprise Server 3.14 Docs https://docs.github.com/ko/enterprise-server@3.14/code-security/codeql-cli/getting-started-with-the-codeql-cli/preparing-your-code-for-codeql-analysis
[64] Bazel Starlark rules for multiplatform C/C++ builds – GitHub https://github.com/ljessendk/rules_multiplatform_cc
[65] 외부 의존성이 있는 bazel 기본 예제 구현하기 https://opencpps.tistory.com/919
[66] 알고리즘 https://documentation.blackduck.com/ko-KR/bundle/coverity-docs-2025.3/page/customizing_coverity/topics/crypto_primitives/r_crypto_enum_algorithm.html
[67] .bzl 스타일 가이드 | Bazel https://bazel.build/rules/bzl-style
[68] 일반적인 C++ 빌드 사용 사례 – Bazel https://bazel.build/versions/7.4.0/tutorials/cpp-use-cases
[69] ‘Develop’ 카테고리의 글 목록 – Good Yunmorning – 티스토리 https://yunmorning.tistory.com/category/Develop
[70] int | Bazel https://bazel.build/versions/6.5.0/rules/lib/int
[71] [Bazel 개념] 기존 CI/CD Pipeline과 통합하는 방법 – Dak.so https://www.dak.so/bazel/use-ci-cd
[72] Tensorflow Lite 를 C/C++로 빌드하기(bazel) https://cppmagister.tistory.com/58
[73] C++ 프로젝트 자동화: CI/CD 파이프라인 구축 – 재능넷 https://www.jaenung.net/tree/12993
[74] Docker환경에서 bazel로 Tensorflow Serving 빌드하고 학습모델 배포 … https://bjo9280.github.io/tensorflowserving/serving-docker_tensorflow_serving/
[75] Google Cloud Build를 사용한 CI/CD – 어쩐지 오늘은 https://zzsza.github.io/gcp/2020/05/09/google-cloud-build/
[76] 로컬 실행을 위한 원격 캐시 적중 디버깅 – Bazel https://bazel.build/remote/cache-local
[77] [Bazel 튜토리얼] Bazel이 강력한 20가지 특징 – Dak.so https://www.dak.so/bazel/features
[78] 규칙 배포 – Bazel https://bazel.build/rules/deploying
[79] 원격 실행 규칙을 테스트하도록 Bazel CI 구성 https://bazel.build/versions/8.0.0/remote/ci
[80] Bazel 튜토리얼: Android 앱 빌드 https://bazel.build/versions/8.0.0/start/android-app
[81] Add Bazel to a docker image – Stack Overflow https://stackoverflow.com/questions/74937159/add-bazel-to-a-docker-image
[82] Bazel을 사용하여 빌드 https://documentation.blackduck.com/ko-KR/bundle/coverity-docs-2024.3/page/coverity-analysis/topics/building_with_bazel.html
[83] 샌드박스 기능 | Bazel https://bazel.build/versions/8.3.0/docs/sandboxing
[84] FAQ – Bazel https://bazel.build/versions/7.0.0/about/faq

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다