Bazel은 다른 프로젝트의 타겟에 종속될 수 있습니다. 이러한 다른 프로젝트의 종속 항목을 외부 종속 항목이라고 합니다.
작업공간 디렉터리의 WORKSPACE
파일 (또는 WORKSPACE.bazel
파일)은 Bazel에 다른 프로젝트의 소스를 가져오는 방법을 알려줍니다. 이러한 다른 프로젝트에는 자체 타겟이 있는 하나 이상의 BUILD
파일이 포함될 수 있습니다. 기본 프로젝트 내의 BUILD
파일은 WORKSPACE
파일의 이름을 사용하여 이러한 외부 타겟에 종속될 수 있습니다.
예를 들어 시스템에 다음과 같은 두 개의 프로젝트가 있다고 가정해 보겠습니다.
/
home/
user/
project1/
WORKSPACE
BUILD
srcs/
...
project2/
WORKSPACE
BUILD
my-libs/
project1
가 /home/user/project2/BUILD
에 정의된 타겟 :foo
에 종속되려면 project2
라는 저장소가 /home/user/project2
에 있다고 지정하면 됩니다. 그러면 /home/user/project1/BUILD
의 타겟이 @project2//:foo
에 종속될 수 있습니다.
WORKSPACE
파일을 사용하면 사용자가 파일 시스템의 다른 부분에 있는 타겟을 종속하거나 인터넷에서 다운로드할 수 있습니다. BUILD
파일과 동일한 구문을 사용하지만 저장소 규칙 (때로는 작업공간 규칙이라고도 함)이라는 다른 규칙 집합을 허용합니다. Bazel에는 몇 가지 기본 제공 저장소 규칙과 삽입된 Starlark 저장소 규칙이 있습니다. 사용자는 맞춤 저장소 규칙을 작성하여 더 복잡한 동작을 구현할 수도 있습니다.
지원되는 외부 종속 항목 유형
다음과 같은 몇 가지 기본 유형의 외부 종속 항목을 사용할 수 있습니다.
다른 Bazel 프로젝트에 종속
두 번째 Bazel 프로젝트의 타겟을 사용하려면 local_repository
, git_repository
또는 http_archive
를 사용하여 로컬 파일 시스템에서 심볼릭 링크하거나, Git 저장소를 참조하거나, 다운로드할 수 있습니다.
예를 들어 my-project/
프로젝트를 진행 중이고 동료의 프로젝트 coworkers-project/
의 타겟을 사용하려고 한다고 가정해 보겠습니다. 두 프로젝트 모두 Bazel을 사용하므로 동료의 프로젝트를 외부 종속 항목으로 추가한 다음 동료가 정의한 타겟을 자신의 BUILD 파일에서 사용할 수 있습니다. my_project/WORKSPACE
에 다음을 추가합니다.
local_repository(
name = "coworkers_project",
path = "/path/to/coworkers-project",
)
동료에게 //foo:bar
타겟이 있는 경우 프로젝트에서 이를 @coworkers_project//foo:bar
로 참조할 수 있습니다. 외부 프로젝트 이름은 유효한 워크스페이스 이름이어야 합니다.
Bazel이 아닌 프로젝트에 종속
new_
로 시작하는 규칙(예: new_local_repository
)을 사용하면 Bazel을 사용하지 않는 프로젝트에서 타겟을 만들 수 있습니다.
예를 들어 my-project/
프로젝트를 작업 중이고 동료의 프로젝트 coworkers-project/
에 의존하고 싶다고 가정해 보겠습니다. 동료의 프로젝트는 make
를 사용하여 빌드하지만 생성되는 .so 파일 중 하나를 사용하고 싶습니다. 이렇게 하려면 my_project/WORKSPACE
에 다음을 추가하세요.
new_local_repository(
name = "coworkers_project",
path = "/path/to/coworkers-project",
build_file = "coworker.BUILD",
)
build_file
는 기존 프로젝트에 오버레이할 BUILD
파일을 지정합니다. 예를 들면 다음과 같습니다.
cc_library(
name = "some-lib",
srcs = glob(["**"]),
visibility = ["//visibility:public"],
)
그런 다음 프로젝트의 BUILD
파일에서 @coworkers_project//:some-lib
에 종속될 수 있습니다.
외부 패키지에 종속
Maven 아티팩트 및 저장소
rules_jvm_external
규칙을 사용하여 Maven 저장소에서 아티팩트를 다운로드하고 Java 종속 항목으로 사용할 수 있도록 합니다.
종속 항목 가져오기
기본적으로 외부 종속 항목은 bazel build
중에 필요에 따라 가져옵니다. 특정 타겟 집합에 필요한 종속 항목을 미리 가져오려면 bazel fetch
를 사용하세요.
모든 외부 종속 항목을 무조건 가져오려면 bazel sync
를 사용합니다.
가져온 저장소는 출력 베이스에 저장되므로 가져오기는 작업공간별로 발생합니다.
종속 항목 섀도잉
가능하면 프로젝트에 단일 버전 정책을 사용하는 것이 좋습니다. 이는 컴파일하고 최종 바이너리에 포함되는 종속 항목에 필요합니다. 하지만 그렇지 않은 경우에는 종속 항목을 섀도잉할 수 있습니다. 다음 상황을 살펴보세요.
myproject/WORKSPACE
workspace(name = "myproject")
local_repository(
name = "A",
path = "../A",
)
local_repository(
name = "B",
path = "../B",
)
A/WORKSPACE
workspace(name = "A")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "testrunner",
urls = ["https://github.com/testrunner/v1.zip"],
sha256 = "...",
)
B/WORKSPACE
workspace(name = "B")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "testrunner",
urls = ["https://github.com/testrunner/v2.zip"],
sha256 = "..."
)
A
및 B
종속 항목은 모두 testrunner
에 종속되지만 testrunner
의 서로 다른 버전에 종속됩니다. 이러한 테스트 러너가 myproject
내에서 평화롭게 공존하지 못할 이유는 없지만 이름이 동일하므로 서로 충돌합니다. 두 종속 항목을 모두 선언하려면 myproject/WORKSPACE를 업데이트하세요.
workspace(name = "myproject")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "testrunner-v1",
urls = ["https://github.com/testrunner/v1.zip"],
sha256 = "..."
)
http_archive(
name = "testrunner-v2",
urls = ["https://github.com/testrunner/v2.zip"],
sha256 = "..."
)
local_repository(
name = "A",
path = "../A",
repo_mapping = {"@testrunner" : "@testrunner-v1"}
)
local_repository(
name = "B",
path = "../B",
repo_mapping = {"@testrunner" : "@testrunner-v2"}
)
이 메커니즘은 다이아몬드를 결합하는 데도 사용할 수 있습니다. 예를 들어 A
와 B
의 종속 항목이 동일하지만 이름이 다른 경우 이러한 종속 항목은 myproject/WORKSPACE에서 결합될 수 있습니다.
명령줄에서 저장소 재정의
명령줄에서 선언된 저장소를 로컬 저장소로 재정의하려면 --override_repository
플래그를 사용합니다. 이 플래그를 사용하면 소스 코드를 변경하지 않고 외부 저장소의 콘텐츠를 변경할 수 있습니다.
예를 들어 @foo
를 로컬 디렉터리 /path/to/local/foo
로 재정의하려면 --override_repository=foo=/path/to/local/foo
플래그를 전달합니다.
다음은 몇 가지 사용 사례입니다.
- 문제 디버깅 예를 들어
http_archive
저장소를 더 쉽게 변경할 수 있는 로컬 디렉터리로 재정의할 수 있습니다. - 벤더링 네트워크 호출을 할 수 없는 환경에 있는 경우 네트워크 기반 저장소 규칙을 재정의하여 대신 로컬 디렉터리를 가리키세요.
프록시 사용
Bazel은 HTTPS_PROXY
및 HTTP_PROXY
환경 변수에서 프록시 주소를 가져와 이를 사용하여 HTTP/HTTPS 파일을 다운로드합니다 (지정된 경우).
IPv6 지원
IPv6 전용 머신에서는 Bazel이 변경 없이 종속 항목을 다운로드할 수 있습니다. 하지만 이중 스택 IPv4/IPv6 머신에서는 Bazel이 Java와 동일한 규칙을 따릅니다. IPv4가 사용 설정된 경우 IPv4가 우선합니다. 예를 들어 IPv4 네트워크에서 외부 주소를 확인할 수 없거나 외부 주소에 도달할 수 없는 경우와 같은 상황에서는 Network unreachable
예외와 빌드 실패가 발생할 수 있습니다.
이 경우 java.net.preferIPv6Addresses=true
시스템 속성을 사용하여 IPv6를 선호하도록 Bazel의 동작을 재정의할 수 있습니다.
구체적인 내용은 다음과 같습니다.
--host_jvm_args=-Djava.net.preferIPv6Addresses=true
시작 옵션을 사용합니다. 예를 들어.bazelrc
파일에 다음 줄을 추가합니다.startup --host_jvm_args=-Djava.net.preferIPv6Addresses=true
인터넷에 연결해야 하는 Java 빌드 타겟 (통합 테스트에 필요한 경우도 있음)을 실행하는 경우
--jvmopt=-Djava.net.preferIPv6Addresses=true
도구 플래그도 사용합니다. 예를 들어.bazelrc
파일에 다음 줄이 있습니다.build --jvmopt=-Djava.net.preferIPv6Addresses
예를 들어 종속 항목 버전 확인을 위해 rules_jvm_external을 사용하는 경우
COURSIER_OPTS
환경 변수에-Djava.net.preferIPv6Addresses=true
를 추가하여 Coursier에 JVM 옵션을 제공합니다.
전이 종속 항목
Bazel은 WORKSPACE
파일에 나열된 종속 항목만 읽습니다. 프로젝트(A
)가 WORKSPACE
파일에 서드 파티 프로젝트 (C
)에 대한 종속 항목을 나열하는 다른 프로젝트 (B
)에 종속된 경우 프로젝트의 WORKSPACE
파일에 B
과 C
를 모두 추가해야 합니다. 이 요구사항으로 인해 WORKSPACE
파일 크기가 커질 수 있지만 한 라이브러리에는 버전 1.0의 C
이 포함되고 다른 라이브러리에는 버전 2.0의 C
이 포함될 가능성이 제한됩니다.
외부 종속 항목 캐싱
기본적으로 Bazel은 정의가 변경된 경우에만 외부 종속 항목을 다시 다운로드합니다. 정의에서 참조되는 파일 (예: 패치 또는 BUILD
파일)의 변경사항도 Bazel에서 고려합니다.
강제로 다시 다운로드하려면 bazel sync
를 사용합니다.
레이아웃
외부 종속 항목은 모두 출력 기본값의 external
하위 디렉터리 아래 디렉터리에 다운로드됩니다. 로컬 저장소의 경우 새 디렉터리를 만드는 대신 심볼릭 링크가 생성됩니다.
다음을 실행하여 external
디렉터리를 확인할 수 있습니다.
ls $(bazel info output_base)/external
bazel clean
를 실행해도 실제로 외부 디렉터리가 삭제되지는 않습니다. 모든 외부 아티팩트를 삭제하려면 bazel clean --expunge
를 사용합니다.
오프라인 빌드
오프라인 방식으로 빌드를 실행하는 것이 바람직하거나 필요한 경우가 있습니다. 비행기 여행과 같은 간단한 사용 사례의 경우 bazel fetch
또는 bazel sync
로 필요한 저장소를 prefetching하는 것으로 충분할 수 있습니다. 또한 --nofetch
옵션을 사용하면 빌드 중에 추가 저장소 가져오기를 사용 중지할 수 있습니다.
필요한 파일 제공이 bazel과 다른 항목에 의해 이루어지는 진정한 오프라인 빌드의 경우 bazel은 --distdir
옵션을 지원합니다. 저장소 규칙이 Bazel에 ctx.download
또는 ctx.download_and_extract
를 통해 파일을 가져오도록 요청하고 필요한 파일의 해시 합계를 제공할 때마다 Bazel은 먼저 해당 옵션으로 지정된 디렉터리에서 제공된 첫 번째 URL의 기본 이름과 일치하는 파일을 찾고 해시가 일치하면 해당 로컬 복사본을 사용합니다.
Bazel 자체는 이 기법을 사용하여 배포 아티팩트에서 오프라인으로 부트스트랩합니다.
내부 distdir_tar
에서 필요한 모든 외부 종속 항목을 수집하여 이렇게 합니다.
하지만 bazel은 네트워크를 호출하는지 여부를 알지 못한 채 저장소 규칙에서 임의의 명령어를 실행할 수 있습니다. 따라서 Bazel에는 빌드가 완전히 오프라인 상태가 되도록 강제하는 옵션이 없습니다. 따라서 오프라인에서 빌드가 올바르게 작동하는지 테스트하려면 bazel이 부트스트랩 테스트에서 하는 것처럼 네트워크를 외부에서 차단해야 합니다.
권장사항
저장소 규칙
저장소 규칙은 일반적으로 다음을 담당해야 합니다.
- 시스템 설정을 감지하고 파일에 작성합니다.
- 시스템의 다른 곳에서 리소스를 찾습니다.
- URL에서 리소스를 다운로드합니다.
- BUILD 파일을 외부 저장소 디렉터리에 생성하거나 심볼릭 링크합니다.
가능하면 repository_ctx.execute
를 사용하지 마세요. 예를 들어 Make를 사용하여 빌드하는 Bazel이 아닌 C++ 라이브러리를 사용하는 경우 ctx.execute(["make"])
를 실행하는 대신 repository_ctx.download()
를 사용한 다음 빌드하는 BUILD 파일을 작성하는 것이 좋습니다.
git_repository
및 new_git_repository
보다 http_archive
을 선호합니다. 이유는 다음과 같습니다.
- Git 저장소 규칙은 시스템
git(1)
에 종속되는 반면 HTTP 다운로더는 Bazel에 내장되어 있으며 시스템 종속 항목이 없습니다. http_archive
은urls
목록을 미러로 지원하고git_repository
은 단일remote
만 지원합니다.http_archive
는 저장소 캐시와 함께 작동하지만git_repository
와는 함께 작동하지 않습니다. 자세한 내용은 #5116을 참고하세요.
bind()
를 사용하지 마세요. 문제와 대안에 관한 긴 토론은 '바인드 삭제 고려'를 참고하세요.