Bazel은 워크스페이스에 없는 빌드에서 사용되는 소스 파일(텍스트 및 바이너리 모두)인 외부 종속 항목을 지원합니다. 예를 들어 GitHub 저장소에서 호스팅되는 규칙 세트, Maven 아티팩트, 현재 작업공간 외부에 있는 로컬 머신의 디렉터리일 수 있습니다.
Bazel 6.0부터 Bazel로 외부 종속 항목을 관리하는 방법에는 두 가지가 있습니다. 기존의 저장소 중심 WORKSPACE
시스템과 최신 모듈 중심 MODULE.bazel
시스템(코드명: Bzlmod, --enable_bzlmod
플래그로 사용 설정)입니다. 두 시스템은 함께 사용할 수 있지만 향후 Bazel 출시에서는 Bzlmod가 WORKSPACE
시스템을 대체합니다. 이전 방법은 Bzlmod 이전 가이드를 참고하세요.
이 문서에서는 Bazel의 외부 종속 항목 관리와 관련된 개념을 설명한 후 두 시스템을 순서대로 자세히 살펴봅니다.
개념
저장소
Bazel 빌드에 사용할 수 있는 소스 파일이 포함되어 있고 루트에 경계 마커 파일이 있는 디렉터리 트리입니다. repo로 줄여서 부르는 경우가 많습니다.
저장소 경계 마커 파일은 MODULE.bazel
(이 저장소가 Bazel 모듈을 나타냄을 나타냄), REPO.bazel
(아래 참고) 또는 기존 컨텍스트에서는 WORKSPACE
또는 WORKSPACE.bazel
일 수 있습니다. 모든 저장소 경계 마커 파일은 저장소의 경계를 나타냅니다. 이러한 파일은 디렉터리에 여러 개 공존할 수 있습니다.
기본 저장소
현재 Bazel 명령어가 실행되고 있는 저장소입니다.
기본 저장소의 루트는 워크스페이스 루트라고도 합니다.
작업공간
모든 Bazel 명령어에서 공유하는 환경은 동일한 기본 저장소에서 실행됩니다. 기본 저장소와 정의된 모든 외부 저장소 집합을 포함합니다.
이전에는 '저장소'와 '워크스페이스' 개념이 혼동되었습니다. '워크스페이스'라는 용어는 기본 저장소를 지칭하는 데 자주 사용되었으며 '저장소'의 동의어로 사용되기도 했습니다.
표준 저장소 이름
저장소를 주소 지정할 수 있는 표준 이름입니다. 작업공간의 컨텍스트 내에서 각 저장소에는 단일 표준 이름이 있습니다. 표준 이름이 canonical_name
인 저장소 내 타겟은 @@canonical_name//package:target
라벨로 주소를 지정할 수 있습니다(@
가 두 번 표시됨).
기본 저장소에는 항상 빈 문자열이 표준 이름으로 표시됩니다.
표시되는 저장소 이름
특정 다른 저장소의 컨텍스트에서 저장소를 주소 지정할 수 있는 이름입니다.
이는 저장소의 '닉네임'으로 간주할 수 있습니다. 표준 이름 michael
를 사용하는 저장소는 저장소 alice
의 컨텍스트에서 겉보기 이름 mike
을 가질 수 있지만 저장소 bob
컨텍스트에서는 명확한 이름 mickey
을 가질 수 있습니다. 이 경우 michael
내부의 타겟은 alice
의 컨텍스트에서 @mike//package:target
라벨로 처리될 수 있습니다 (단일 @
에 유의).
반대로 이를 저장소 매핑으로 이해할 수 있습니다. 각 저장소는 '명확한 저장소 이름'에서 '표준 저장소 이름'으로의 매핑을 유지합니다.
저장소 규칙
Bazel에 저장소를 구체화하는 방법을 알려주는 저장소 정의의 스키마입니다. 예를 들어 '특정 URL에서 zip 파일을 다운로드하고 추출', '특정 Maven 아티팩트를 가져와 java_import
타겟으로 사용 가능하게 만들', '로컬 디렉터리를 심볼릭 링크로 연결' 등이 될 수 있습니다. 모든 저장소는 적절한 수의 인수를 사용하여 저장소 규칙을 호출하여 정의됩니다.
자체 저장소 규칙을 작성하는 방법에 관한 자세한 내용은 저장소 규칙을 참고하세요.
가장 일반적인 저장소 규칙은 URL에서 보관 파일을 다운로드하고 추출하는 http_archive
와 이미 Bazel 저장소인 로컬 디렉터리를 심볼릭 링크하는 local_repository
입니다.
저장소 가져오기
연결된 저장소 규칙을 실행하여 로컬 디스크에서 저장소를 사용할 수 있도록 하는 작업입니다. 작업공간에 정의된 저장소는 가져오기 전에는 로컬 디스크에서 사용할 수 없습니다.
일반적으로 Bazel은 저장소에서 무언가가 필요할 때만 저장소를 가져오며, 저장소를 아직 가져오지 않았습니다. 저장소가 이전에 이미 가져온 경우 정의가 변경된 경우에만 Bazel에서 다시 가져옵니다.
fetch
명령어는 빌드를 실행하는 데 필요한 저장소, 타겟 또는 모든 저장소의 미리 가져오기를 시작하는 데 사용할 수 있습니다. 이 기능을 사용하면 --nofetch
옵션을 사용하여 오프라인 빌드를 실행할 수 있습니다.
--fetch
옵션은 네트워크 액세스를 관리하는 데 사용됩니다. 기본값은 true입니다.
하지만 false (--nofetch
)로 설정하면 명령어는 종속 항목의 캐시된 버전을 활용하며, 캐시된 버전이 없으면 명령어가 실패합니다.
가져오기 제어에 관한 자세한 내용은 가져오기 옵션을 참고하세요.
디렉터리 레이아웃
가져온 후 저장소는 출력 기반의 하위 디렉터리 external
에 표준 이름으로 표시됩니다.
다음 명령어를 실행하여 표준 이름이 canonical_name
인 저장소의 콘텐츠를 확인할 수 있습니다.
ls $(bazel info output_base)/external/ canonical_name
REPO.bazel 파일
REPO.bazel
파일은 저장소를 구성하는 디렉터리 트리의 최상위 경계를 표시하는 데 사용됩니다. 저장소 경계 파일 역할을 하기 위해 아무것도 포함할 필요는 없지만 저장소 내부의 모든 빌드 대상에 공통 속성을 지정하는 데도 사용할 수 있습니다.
REPO.bazel
파일의 구문은 BUILD
파일과 유사하지만 load
문이 지원되지 않고 단일 함수인 repo()
만 사용할 수 있다는 점이 다릅니다. repo()
는 BUILD
파일의 package()
함수와 동일한 인수를 사용합니다. package()
는 패키지 내의 모든 빌드 타겟에 공통 속성을 지정하는 반면 repo()
는 이와 유사하게 저장소 내의 모든 빌드 타겟에 공통 속성을 지정합니다.
예를 들어 다음 REPO.bazel
파일을 사용하여 저장소의 모든 타겟에 공통 라이선스를 지정할 수 있습니다.
repo(
default_package_metadata = ["//:my_license"],
)
Bzlmod로 외부 종속 항목 관리
새로운 외부 종속 항목 하위 시스템인 Bzlmod는 저장소 정의와 직접 작동하지 않습니다. 대신 모듈에서 종속 항목 그래프를 빌드하고 그래프 위에 확장 프로그램을 실행한 후 그에 따라 저장소를 정의합니다.
Bazel 모듈은 여러 버전을 가질 수 있는 Bazel 프로젝트이며, 각 버전은 종속되는 다른 모듈에 관한 메타데이터를 게시합니다. 모듈의 저장소 루트의 WORKSPACE
파일 옆에 MODULE.bazel
파일이 있어야 합니다. 이 파일은 모듈의 매니페스트로, 이름, 버전, 종속 항목 목록 등 기타 정보를 선언합니다. 다음은 기본 예시입니다.
module(name = "my-module", version = "1.0")
bazel_dep(name = "rules_cc", version = "0.0.1")
bazel_dep(name = "protobuf", version = "3.19.0")
모듈은 Bzlmod가 Bazel 레지스트리(기본적으로 Bazel Central Registry)에서 조회하는 직접 종속 항목만 나열해야 합니다. 레지스트리는 종속 항목의 MODULE.bazel
파일을 제공하므로 Bazel은 버전 확인을 실행하기 전에 전체 전이 종속 항목 그래프를 검색할 수 있습니다.
모듈별로 하나의 버전이 선택되는 버전 확인 후 Bazel은 레지스트리를 다시 참조하여 각 모듈의 저장소를 정의하는 방법을 학습합니다(대부분의 경우 http_archive
사용).
모듈은 태그라는 맞춤설정된 데이터를 지정할 수도 있습니다. 이 태그는 모듈 해상 후 모듈 확장 프로그램에서 사용하여 추가 저장소를 정의합니다. 이러한 확장 프로그램은 저장소 규칙과 유사한 기능을 갖추고 있으므로 파일 I/O 및 네트워크 요청 전송과 같은 작업을 실행할 수 있습니다. 무엇보다도 Bazel이 Bazel 모듈로 빌드된 종속 항목 그래프를 준수하면서 다른 패키지 관리 시스템과 상호작용할 수 있도록 합니다.
Bzlmod의 외부 링크
- bazelbuild/examples의 Bzlmod 사용 예시
- Bazel 외부 종속 항목 개편(원본 Bzlmod 설계 문서)
- Bzlmod에 관한 BazelCon 2021 강연
- Bzlmod에 관한 Bazel 커뮤니티 데이 강연
WORKSPACE
로 저장소 정의
이전에는 WORKSPACE
(또는 WORKSPACE.bazel
) 파일에 저장소를 정의하여 외부 종속 항목을 관리할 수 있습니다. 이 파일은 빌드 규칙 대신 저장소 규칙을 사용하는 BUILD
파일과 유사한 문법을 사용합니다.
다음 스니펫은 WORKSPACE
파일에서 http_archive
저장소 규칙을 사용하는 예입니다.
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "foo",
urls = ["https://example.com/foo.zip"],
sha256 = "c9526390a7cd420fdcec2988b4f3626fe9c5b51e2959f685e8f4d170d1a9bd96",
)
스니펫은 표준 이름이 foo
인 저장소를 정의합니다. WORKSPACE
시스템에서 기본적으로 저장소의 표준 이름은 다른 모든 저장소에 표시되는 이름이기도 합니다.
WORKSPACE
파일에서 사용할 수 있는 함수의 전체 목록을 참조하세요.
WORKSPACE
시스템의 단점
WORKSPACE
시스템이 도입된 이후 사용자는 다음과 같은 여러 문제점을 신고했습니다.
- Bazel은 종속 항목의
WORKSPACE
파일을 평가하지 않으므로 모든 전이 종속 항목은 직접 종속 항목 외에도 기본 저장소의WORKSPACE
파일에 정의되어야 합니다. - 이 문제를 해결하기 위해 프로젝트는 'deps.bzl' 패턴을 채택했습니다. 이 패턴에서는 매크로를 정의하고 매크로가 여러 저장소를 정의하며 사용자에게
WORKSPACE
파일에서 이 매크로를 호출하도록 요청합니다.- 여기에는 자체적인 문제가 있습니다. 매크로는 다른
.bzl
파일을load
할 수 없으므로 이러한 프로젝트에서는 이 'deps' 매크로에 전이 종속 항목을 정의하거나 사용자가 여러 계층의 'deps' 매크로를 호출하도록 하여 이 문제를 해결해야 합니다. - Bazel은
WORKSPACE
파일을 순차적으로 평가합니다. 또한 종속 항목은 버전 정보 없이 URL과 함께http_archive
를 사용하여 지정됩니다. 즉, 다이아몬드 종속 항목의 경우 버전 확인을 실행할 수 있는 안정적인 방법이 없습니다 (A
은B
및C
에 종속되고B
및C
는 모두 서로 다른 버전의D
에 종속됨).
- 여기에는 자체적인 문제가 있습니다. 매크로는 다른
WORKSPACE의 단점으로 인해 Bzlmod는 향후 Bazel 출시에서 기존 WORKSPACE 시스템을 대체할 예정입니다. Bzlmod로 이전하는 방법은 Bzlmod 이전 가이드를 참고하세요.