외부 종속 항목 작업

컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.
문제 신고 소스 보기

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 타겟에 종속되기를 원하는 경우 /home/user/project2에서 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 저장소에서 아티팩트를 다운로드하고 자바 종속 항목으로 사용할 수 있도록 합니다.

종속 항목 가져오기

기본적으로 외부 종속 항목은 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(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 = "..."
)

종속 항목 AB은 모두 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"}
)

이 메커니즘은 다이아몬드를 연결하는 데에도 사용할 수 있습니다. 예를 들어 AB는 동일한 종속 항목을 가지고 있지만 다른 이름으로 호출한다면 그 종속 항목은 myproject/WORKSPACE에 조인될 수 있습니다.

명령줄에서 저장소 재정의

선언된 저장소를 명령줄에서 로컬 저장소로 재정의하려면 --override_repository 플래그를 사용합니다. 이 플래그를 사용하면 소스 코드를 변경하지 않고 외부 저장소의 콘텐츠가 변경됩니다.

예를 들어 @foo를 로컬 디렉터리 /path/to/local/foo로 재정의하려면 --override_repository=foo=/path/to/local/foo 플래그를 전달합니다.

다음은 몇 가지 사용 사례입니다.

  • 디버깅 문제 예를 들어 http_archive 저장소를 로컬 디렉터리에 재정의하여 더 쉽게 변경할 수 있습니다.
  • 벤더링. 네트워크를 호출할 수 없는 환경에 있는 경우 대신 로컬 기반 저장소 규칙을 가리키도록 네트워크 기반 저장소 규칙을 재정의합니다.

프록시 사용

Bazel은 HTTPS_PROXYHTTP_PROXY 환경 변수에서 프록시 주소를 가져와 이를 사용하여 HTTP/HTTPS 파일을 다운로드합니다 (지정된 경우).

IPv6 지원

IPv6 전용 머신에서 Bazel은 변경사항 없이 종속 항목을 다운로드할 수 있습니다. 그러나 이중 스택 IPv4/IPv6 머신에서 Bazel은 자바와 동일한 규칙을 따릅니다. IPv4가 사용 설정된 경우 IPv4가 선호됩니다. 일부 상황(예: IPv4 네트워크에서 외부 주소를 확인/연결할 수 없는 경우)으로 인해 Network unreachable 예외 및 빌드 실패가 발생할 수 있습니다. 이러한 경우 java.net.preferIPv6Addresses=true 시스템 속성을 사용하여 Bazel의 동작이 IPv6를 선호하도록 재정의할 수 있습니다. 특히 다음에 주의해야 합니다.

  • 예를 들어 .bazelrc 파일에 다음 줄을 추가하여 --host_jvm_args=-Djava.net.preferIPv6Addresses=true 시작 옵션을 사용합니다.

    startup --host_jvm_args=-Djava.net.preferIPv6Addresses=true

  • 인터넷에 연결해야 하는 자바 빌드 타겟도 실행하는 경우 (때로는 통합 테스트에 필요함) 예를 들어 .bazelrc 파일에 다음 줄을 추가하여 --jvmopt=-Djava.net.preferIPv6Addresses=true 도구 플래그를 사용합니다.

    build --jvmopt=-Djava.net.preferIPv6Addresses

  • 예를 들어 rules_jvm_external을 사용하는 경우 종속 항목 버전 확인에도 COURSIER_OPTS 환경 변수에 -Djava.net.preferIPv6Addresses=true를 추가하여 Coursier에 JVM 옵션을 제공합니다.

전이 종속 항목

Bazel은 WORKSPACE 파일에 나열된 종속 항목만 읽습니다. 프로젝트(A)가 WORKSPACE 파일의 세 번째 프로젝트 (C)에 관한 종속 항목을 나열하는 다른 프로젝트 (B)에 종속되는 경우 BC를 모두 프로젝트의 WORKSPACE 파일에 추가해야 합니다. 이 요구사항을 따르면 WORKSPACE 파일 크기가 벌어질 수 있지만, 하나의 라이브러리가 버전 1.0에서 C을 포함하고 다른 라이브러리가 2.0에서 C을 포함할 가능성을 제한합니다.

외부 종속 항목 캐싱

기본적으로 Bazel은 정의가 변경되는 경우에만 외부 종속 항목을 다시 다운로드합니다. bazel에서는 패치에서 정의된 파일 변경사항 (예: 패치 또는 BUILD 파일)도 고려합니다.

강제로 다시 다운로드하려면 bazel sync를 사용합니다.

레이아웃

외부 종속 항목은 모두 출력 기반external 하위 디렉터리 아래에 있는 디렉터리에 다운로드됩니다. 로컬 저장소의 경우 새 디렉터리를 만드는 대신 심볼릭 링크가 만들어집니다. 다음을 실행하여 external 디렉터리를 볼 수 있습니다.

ls $(bazel info output_base)/external

bazel clean를 실행해도 실제로 외부 디렉터리는 삭제되지 않습니다. 모든 외부 아티팩트를 제거하려면 bazel clean --expunge를 사용합니다.

오프라인 빌드

때로는 오프라인 방식으로 빌드를 실행하는 것이 바람직하거나 필요할 수 있습니다. 비행기로 여행하는 등의 간단한 사용 사례에서는 bazel fetchbazel sync로 필요한 저장소를 미리 가져오기로 충분할 수 있습니다. 또한 --nofetch 옵션을 사용하면 빌드 중에 추가 저장소 가져오기를 사용 중지할 수 있습니다.

필요한 파일을 제공하는 것이 bazel과 다른 항목에 의해 이루어지는 실제 오프라인 빌드의 경우 bazel은 --distdir 옵션을 지원합니다. 저장소 규칙이 bazel에 ctx.download 또는 ctx.download_and_extract를 통해 파일을 가져오도록 요청하고 필요한 파일의 해시 합계를 제공하면 bazel은 먼저 제공된 첫 번째 URL의 기본 이름과 일치하는 파일에 대해 지정된 디렉터리로 이동하여 해시가 일치하는 경우 로컬 사본을 사용합니다.

Bazel 자체는 이 기법을 사용하여 배포 아티팩트에서 오프라인으로 부트스트랩합니다. 이렇게 하려면 내부 distdir_tar에서 필요한 모든 외부 종속 항목을 수집합니다.

하지만 bazel에서는 네트워크를 호출하는지 몰라도 저장소 규칙에서 임의의 명령어를 실행할 수 있습니다. 따라서 bazel에는 빌드를 완전히 오프라인으로 시행하는 옵션이 없습니다. 따라서 빌드가 부트스트랩 테스트에서와 마찬가지로 오프라인에서 올바르게 작동하는지 테스트하려면 네트워크에 대한 외부 차단이 필요합니다.

권장사항

저장소 규칙

저장소 규칙은 일반적으로 다음을 담당해야 합니다.

  • 시스템 설정 감지 및 파일에 쓰기
  • 시스템의 다른 위치에서 리소스 찾기
  • URL에서 리소스 다운로드
  • BUILD 파일을 생성하거나 외부 저장소 디렉터리에 심볼릭 링크를 제공합니다.

가능하면 repository_ctx.execute를 사용하지 않습니다. 예를 들어, Bazel이 아닌 C++ 라이브러리를 사용하여 Make를 사용하는 경우 ctx.execute(["make"])를 실행하는 대신 repository_ctx.download()를 사용한 다음 이를 빌드하는 BUILD 파일을 작성하는 것이 좋습니다.

git_repository보다 http_archive를 선호합니다. 이유는 다음과 같습니다.

  • Git 저장소 규칙은 시스템 git(1)에 종속되지만 HTTP 다운로더는 Bazel에 내장되어 있으며 시스템 종속 항목이 없습니다.
  • http_archiveurls 목록을 미러링으로 지원하고 git_repository는 단일 remote만 지원합니다.
  • http_archive저장소 캐시에서 작동하지만 git_repository에서는 작동하지 않습니다. 자세한 내용은 #5116을 참고하세요.

bind()를 사용하지 마세요. 문제 및 대안에 관한 자세한 설명은 '바인드 삭제 고려'를 참고하세요.