날짜 비워 두기: BazelCon 2023이 10월 24~25일에 Google 뮌헨에서 열립니다. 등록이 시작되었습니다. 자세히 알아보기

Maven에서 Bazel로 마이그레이션

문제 신고 소스 보기

이 페이지에서는 기본 요건 및 설치 단계를 포함하여 Maven에서 Bazel로 이전하는 방법을 설명합니다. Maven과 Bazel의 차이점을 설명하고 Guava 프로젝트를 사용하는 마이그레이션 예시를 제공합니다.

빌드 도구에서 Bazel로 마이그레이션할 때는 개발팀, CI 시스템, 기타 관련 시스템을 완전히 마이그레이션할 때까지 두 빌드 도구를 동시에 실행하는 것이 가장 좋습니다. Maven 및 Bazel을 동일한 저장소에서 실행할 수 있습니다.

시작하기 전에

  • 아직 설치되지 않은 경우 Bazel을 설치합니다.
  • Bazel을 처음 사용하는 경우 이전을 시작하기 전에 Bazel 소개: 자바 빌드 가이드를 진행하세요. 이 가이드에서는 Bazel의 개념, 구조, 라벨 문법을 설명합니다.

Maven과 Bazel의 차이점

  • Maven은 최상위 pom.xml 파일을 사용합니다. Bazel은 BUILD 파일당 여러 빌드 파일과 여러 대상을 지원하므로 Maven보다 증분 빌드가 가능합니다.
  • Maven이 배포 프로세스 단계를 처리합니다. Bazel은 배포를 자동화하지 않습니다.
  • Bazel을 사용하면 언어 간의 종속 항목을 표현할 수 있습니다.
  • Bazel을 사용하여 프로젝트에 새 섹션을 추가할 때 새 BUILD 파일을 추가해야 할 수도 있습니다. 각 새 자바 패키지에 BUILD 파일을 추가하는 것이 좋습니다.

Maven에서 Bazel로 마이그레이션

아래 단계에서는 프로젝트를 Bazel로 이전하는 방법을 설명합니다.

  1. WORKSPACE 파일 만들기
  2. BUILD 파일 한 개 만들기
  3. BUILD 파일 더 만들기
  4. Bazel을 사용하여 빌드

아래 예시는 Guava 프로젝트를 Maven에서 Bazel로 마이그레이션한 것입니다. 사용된 Guava 프로젝트는 v31.1 버전입니다. Guava를 사용하는 예는 이전의 각 단계를 거치지 않지만, 이전을 위해 수동으로 생성되거나 추가되는 파일 및 콘텐츠를 보여줍니다.

$ git clone https://github.com/google/guava.git && cd guava
$ git checkout v31.1

1. WORKSPACE 파일 만들기

프로젝트 루트에 WORKSPACE이라는 파일을 만듭니다. 프로젝트에 외부 종속 항목이 없으면 작업공간 파일을 비울 수 있습니다.

프로젝트가 프로젝트 디렉터리 중 하나에 없는 파일 또는 패키지에 종속되는 경우 작업공간 파일에 이러한 외부 종속 항목을 지정합니다. 작업공간 파일의 외부 종속 항목 목록을 자동화하려면 rules_jvm_external를 사용하세요. 이 규칙 세트를 사용하는 방법은 리드미를 참고하세요.

Guava 프로젝트 예: 외부 종속 항목

rules_jvm_external 규칙 집합을 사용하여 Guava 프로젝트의 외부 종속 항목을 나열할 수 있습니다.

WORKSPACE 파일에 다음 스니펫을 추가합니다.

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

RULES_JVM_EXTERNAL_TAG = "4.3"
RULES_JVM_EXTERNAL_SHA = "6274687f6fc5783b589f56a2f1ed60de3ce1f99bc4e8f9edef3de43bdf7c6e74"

http_archive(
    name = "rules_jvm_external",
    sha256 = RULES_JVM_EXTERNAL_SHA,
    strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG,
    url = "https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip" % RULES_JVM_EXTERNAL_TAG,
)

load("@rules_jvm_external//:defs.bzl", "maven_install")

maven_install(
    artifacts = [
        "com.google.code.findbugs:jsr305:3.0.2",
        "com.google.errorprone:error_prone_annotations:2.11.0",
        "com.google.j2objc:j2objc-annotations:1.3",
        "org.codehaus.mojo:animal-sniffer-annotations:1.20",
        "org.checkerframework:checker-qual:3.12.0",
    ],
    repositories = [
        "https://repo1.maven.org/maven2",
    ],
)

2. BUILD 파일 1개 만들기

이제 작업공간이 정의되고 외부 종속 항목 (해당하는 경우)이 나열되어 있으므로 BUILD 파일을 만들어 프로젝트 빌드 방법을 설명해야 합니다. 하나의 pom.xml 파일을 사용하는 Maven과 달리 Bazel은 많은 BUILD 파일을 사용하여 프로젝트를 빌드할 수 있습니다. 이러한 파일은 Bazel이 증분 빌드를 생성할 수 있는 여러 빌드 대상을 지정합니다.

파일 BUILD개를 단계별로 추가합니다. 먼저 프로젝트 루트에 BUILD 파일 하나를 추가하고 Bazel을 사용하여 초기 빌드를 수행하는 데 사용합니다. 그런 다음 더 세부적인 타겟을 사용하여 BUILD 파일을 더 추가하여 빌드를 구체화합니다.

  1. WORKSPACE 파일과 동일한 디렉터리에서 텍스트 파일을 만들고 이름을 BUILD로 지정합니다.

  2. BUILD 파일에서 적절한 규칙을 사용하여 프로젝트를 빌드할 대상을 만듭니다. 다음은 몇 가지 팁입니다.

    • 적절한 규칙을 사용하세요.

      • 단일 Maven 모듈로 프로젝트를 빌드하려면 다음과 같이 java_library 규칙을 사용합니다.

        java_library(
            name = "everything",
            srcs = glob(["src/main/java/**/*.java"]),
            resources = glob(["src/main/resources/**"]),
            deps = ["//:all-external-targets"],
        )
        
      • 여러 Maven 모듈로 프로젝트를 빌드하려면 다음과 같이 java_library 규칙을 사용합니다.

        java_library(
            name = "everything",
            srcs = glob([
                "Module1/src/main/java/**/*.java",
                "Module2/src/main/java/**/*.java",
                ...
            ]),
            resources = glob([
                "Module1/src/main/resources/**",
                "Module2/src/main/resources/**",
                ...
            ]),
            deps = ["//:all-external-targets"],
        )
        
      • 바이너리를 빌드하려면 java_binary 규칙을 사용합니다.

        java_binary(
            name = "everything",
            srcs = glob(["src/main/java/**/*.java"]),
            resources = glob(["src/main/resources/**"]),
            deps = ["//:all-external-targets"],
            main_class = "com.example.Main"
        )
        
    • 속성을 지정합니다.

      • name: 대상에 의미 있는 이름을 지정합니다. 위의 예시에서는 타겟을 '모두'라고 부릅니다.
      • srcs: globbing을 사용하여 프로젝트의 모든 .java 파일을 나열합니다.
      • resources: globbing을 사용하여 프로젝트의 모든 리소스를 나열합니다.
      • deps: 프로젝트에 필요한 외부 종속 항목을 결정해야 합니다. 예를 들어 generate_workspace 도구를 사용하여 외부 종속 항목 목록을 생성한 경우 java_library의 종속 항목은 generated_java_libraries 매크로에 나열된 라이브러리입니다.
    • Guava 프로젝트 이전에서 이 최상위 BUILD 파일의 아래 예를 살펴보세요.

  3. 이제 프로젝트 루트에 BUILD 파일이 있으므로 프로젝트를 빌드하여 작동하는지 확인합니다. 명령줄의 작업공간 디렉터리에서 bazel build //:everything를 사용하여 Bazel로 프로젝트를 빌드합니다.

    이제 Bazel을 사용하여 프로젝트를 성공적으로 빌드했습니다. 프로젝트의 증분 빌드를 허용하려면 BUILD 파일을 더 추가해야 합니다.

Guava 프로젝트 예: 하나의 BUILD 파일로 시작

Guava 프로젝트를 Bazel로 이전할 때 처음에는 전체 BUILD 파일을 사용하여 전체 프로젝트를 빌드합니다. 작업공간 디렉터리에 있는 이 초기 BUILD 파일의 콘텐츠는 다음과 같습니다.

java_library(
    name = "everything",
    srcs = glob([
        "guava/src/**/*.java",
        "futures/failureaccess/src/**/*.java",
    ]),
    deps = [
        "@maven//:com_google_code_findbugs_jsr305",
        "@maven//:com_google_errorprone_error_prone_annotations",
        "@maven//:com_google_j2objc_j2objc_annotations",
        "@maven//:org_checkerframework_checker_qual",
        "@maven//:org_codehaus_mojo_animal_sniffer_annotations",
    ],
)

3. 더 많은 BUILD 파일 만들기 (선택사항)

첫 번째 빌드를 완료한 후 보듯이 Bazel은 하나의 BUILD file로만 작동합니다. 세분화된 대상이 포함된 BUILD 파일을 더 추가하여 빌드를 더 작은 청크로 분할하는 것을 고려해야 합니다.

타겟이 여러 개인 BUILD 파일이 여러 개 있으면 빌드가 개선되어 다음을 실행할 수 있습니다.

  • 프로젝트의 증분 빌드 증가
  • 빌드의 병렬 실행 증가
  • 향후 사용자를 위한 빌드의 유지보수성 향상
  • 패키지 간 대상의 공개 상태를 제어합니다. 이를 통해 구현 세부정보가 포함된 라이브러리와 같이 공개 API로 누출되는 문제를 방지할 수 있습니다.

BUILD 파일을 더 추가하기 위한 도움말:

  • 먼저 각 자바 패키지에 BUILD 파일을 추가합니다. 종속 항목이 가장 적은 자바 패키지로 시작하여 종속 항목이 가장 많은 패키지로 이동합니다.
  • BUILD 파일을 추가하고 타겟을 지정할 때 이러한 새 타겟을 타겟의 deps 섹션에 추가합니다. glob() 함수는 패키지 경계를 교차하지 않으므로 패키지 수가 커질수록 glob()와 일치하는 파일이 축소됩니다.
  • BUILD 파일을 main 디렉터리에 추가할 때마다 BUILD 파일을 상응하는 test 디렉터리에 추가해야 합니다.
  • 패키지 간의 가시성을 적절히 제한해야 합니다.
  • BUILD 파일 설정의 오류 문제를 단순화하려면 각 빌드 파일을 추가할 때 프로젝트가 Bazel을 사용하여 계속 빌드하도록 합니다. bazel build //...를 실행하여 모든 타겟이 계속 빌드되는지 확인합니다.

4. Bazel을 사용하여 빌드

빌드 설정을 검증하기 위해 BUILD 파일을 추가할 때 Bazel을 사용하여 빌드해 왔습니다.

원하는 세분화 수준으로 BUILD 파일이 있으면 Bazel을 사용하여 모든 빌드를 생성할 수 있습니다.