종속 항목

문제 신고 소스 보기

타겟 A는 빌드 또는 실행 시 AB에 필요한 경우 타겟 B종속됩니다. 종속 관계는 타겟을 대상으로 방향성 비순환 그래프(DAG)를 유도하며, 이를 종속 그래프라고 합니다.

타겟의 직접 종속 항목은 종속 항목 그래프에서 길이 1의 경로를 통해 도달할 수 있는 다른 대상입니다. 대상의 전이 종속 항목은 그래프를 통해 임의 길이의 경로를 통해 종속되는 대상입니다.

실제로 빌드와 관련하여 두 가지 종속 항목 그래프가 있습니다. 하나는 실제 종속 항목의 그래프이고 다른 하나는 선언된 종속 항목의 그래프입니다. 대부분의 경우 두 그래프는 매우 유사하여 이를 구분할 필요가 없지만 아래의 설명에서는 유용합니다.

실제 종속 항목 및 선언된 종속 항목

타겟 XX가 올바르게 빌드되기 위해 Y가 있고 빌드되고 최신 상태여야 하는 경우 타겟 Y실제로 종속됩니다. 빌드됨은 생성, 처리, 컴파일, 연결, 보관처리, 압축, 실행 또는 빌드 중에 일상적으로 발생하는 기타 모든 종류의 작업을 의미할 수 있습니다.

X 패키지에 X에서 Y까지의 종속 항목 에지가 있으면 대상 X에 대상 Y선언된 종속 항목이 있습니다.

올바른 빌드의 경우 실제 종속 항목 A의 그래프는 선언된 종속 항목 D 그래프의 하위 그래프여야 합니다. 즉, A에 있는 직접 연결된 모든 노드 x --> yD에 직접 연결되어야 합니다. DA과대적이라고 말할 수 있습니다.

BUILD 파일 작성기는 모든 규칙에 대한 모든 실제 직접적인 종속 항목을 빌드 시스템에 명시적으로 선언해야 하며 그 이상은 필요하지 않습니다.

이 원칙을 준수하지 않으면 정의되지 않은 동작이 발생합니다. 빌드가 실패할 수 있지만 더 심각한 경우 이전 작업 또는 타겟에서 전이 선언된 종속 항목에 종속될 수 있습니다. Bazel은 누락된 종속 항목을 확인하고 오류를 보고하지만 모든 경우에 이 검사를 완료할 수는 없습니다.

실행 시점에 A필요하더라도 간접적으로 가져온 모든 항목을 나열하려고 하면 안 됩니다.

타겟 X를 빌드하는 동안 빌드 도구는 X의 종속 항목의 전체 전이적 닫음을 검사하여 이러한 타겟의 변경사항이 최종 결과에 반영되도록 필요에 따라 중간 항목을 다시 빌드합니다.

종속 항목의 전이적 특성은 흔히 저지르는 실수로 이어집니다. 한 파일의 코드가 선언된 종속 항목 그래프에서 전이적이지만 직접 에지가 아닌 간접 종속 항목에서 제공하는 코드를 사용하는 경우가 있습니다. 간접 종속 항목은 BUILD 파일에 표시되지 않습니다. 이 규칙은 제공업체에 직접 의존하지 않으므로 다음 타임라인 예와 같이 변경사항을 추적할 수 있는 방법은 없습니다.

1. 선언된 종속 항목이 실제 종속 항목과 일치합니다.

처음에는 모든 것이 제대로 작동합니다. a 패키지의 코드는 b 패키지의 코드를 사용합니다. b 패키지의 코드는 패키지 c의 코드를 사용하므로 a가 전이적으로 c에 종속됩니다.

a/BUILD b/BUILD
rule(
    name = "a",
    srcs = "a.in",
    deps = "//b:b",
)
      
rule(
    name = "b",
    srcs = "b.in",
    deps = "//c:c",
)
      
a / a.in b / b.in
import b;
b.foo();
    
import c;
function foo() {
  c.bar();
}
      
a, b, c를 연결하는 화살표가 있는 종속 항목 그래프를 선언함
종속된 종속 항목 그래프
선언된 종속 항목 그래프와 일치하며 화살표가 a, b, c를 연결하는 실제 종속 항목 그래프
실제 종속 항목 그래프

선언된 종속 항목은 실제 종속 항목에 가깝습니다. 모든 것이 좋습니다.

2. 선언되지 않은 종속 항목 추가

누군가 a에 코드를 추가하여 c에 직접적인 실제 종속 항목을 만들지만 빌드 파일 a/BUILD에 선언하지 않은 경우 잠재 위험이 발생합니다.

a / a.in  
        import b;
        import c;
        b.foo();
        c.garply();
      
 
a, b, c를 연결하는 화살표가 있는 종속 항목 그래프를 선언함
종속된 종속 항목 그래프
a, b, c를 연결하는 화살표가 있는 실제 종속 항목 그래프 이제 화살표도 A를 C에 연결합니다. 선언된 종속 항목 그래프와 일치하지 않습니다.
실제 종속 항목 그래프

선언된 종속 항목이 더 이상 실제 종속 항목을 과다 처리하지 않습니다. 두 그래프의 전이적 닫힘이 동일하기 때문에 문제가 되지 않을 수 있지만 문제가 있습니다. ac에 대한 실제적이지만 선언되지 않은 종속 항목이 있기 때문입니다.

3. 선언된 종속 항목과 실제 종속 항목 그래프 간의 차이

위험은 더 이상 c에 종속되지 않도록 b를 리팩터링하면 의도치 않게 자체 오류 없이 a을 중단합니다.

  b/BUILD
 
rule(
    name = "b",
    srcs = "b.in",
    deps = "//d:d",
)
      
  b / b.in
 
      import d;
      function foo() {
        d.baz();
      }
      
a와 b를 연결하는 화살표가 있는 종속 항목 그래프를 선언했습니다.
                  b가 더 이상 c에 연결되지 않아 a의 c 연결이 끊어짐
종속된 종속 항목 그래프
b와 c에 연결하는 것을 보여주지만 b는 더 이상 c에 연결되지 않는 실제 종속 항목 그래프
실제 종속 항목 그래프

선언된 종속 항목 그래프는 이제 전이적으로 닫혀도 실제 종속 항목의 근사치이며 빌드가 실패할 수 있습니다.

2단계에서 도입된 a에서 c까지의 실제 종속 항목이 BUILD 파일에서 제대로 선언되었는지 확인하여 이 문제를 피할 수 있습니다.

종속 항목 유형

대부분의 빌드 규칙에는 여러 유형의 일반 종속 항목을 지정하기 위한 세 가지 속성, srcs, deps, data이 있습니다. 자세한 내용은 아래에 설명되어 있습니다. 자세한 내용은 모든 규칙에 공통된 속성을 참고하세요.

많은 규칙에는 compiler 또는 resources와 같이 규칙별 종속 항목의 추가 속성도 있습니다. 자세한 내용은 백과 빌드에 설명되어 있습니다.

종속 항목 srcs

규칙에서 직접 소비한 파일 또는 소스 파일을 출력하는 규칙

종속 항목 deps

헤더 파일, 기호, 라이브러리, 데이터 등을 제공하는 별도로 컴파일된 모듈을 가리키는 규칙입니다.

종속 항목 data

빌드 타겟이 올바르게 실행되려면 일부 데이터 파일이 필요할 수 있습니다. 이러한 데이터 파일은 소스 코드가 아니며 타겟 빌드 방식에 영향을 주지 않습니다. 예를 들어 단위 테스트에서는 함수의 출력을 파일 콘텐츠와 비교할 수 있습니다. 단위 테스트를 빌드할 때는 파일이 필요하지 않지만 테스트를 실행할 때 필요합니다. 실행 중에 실행되는 도구에도 마찬가지입니다.

빌드 시스템은 data로 나열된 파일만 사용할 수 있는 격리된 디렉터리에서 테스트를 실행합니다. 따라서 바이너리/라이브러리/테스트에서 실행할 파일이 필요한 경우 data에 이들 (또는 그 파일을 포함하는 빌드 규칙)을 지정합니다. 예를 들면 다음과 같습니다.

# I need a config file from a directory named env:
java_binary(
    name = "setenv",
    ...
    data = [":env/default_env.txt"],
)

# I need test data from another directory
sh_test(
    name = "regtest",
    srcs = ["regtest.sh"],
    data = [
        "//data:file1.txt",
        "//data:file2.txt",
        ...
    ],
)

이러한 파일은 상대 경로 path/to/data/file를 사용하여 사용할 수 있습니다. 테스트에서 테스트 소스 디렉터리의 경로와 작업공간 기준 경로(예: ${TEST_SRCDIR}/workspace/path/to/data/file)의 경로를 조인하여 이러한 파일을 참조할 수 있습니다.

라벨을 사용하여 디렉터리 참조

BUILD 파일을 살펴보면 일부 data 라벨이 디렉터리를 참조한다는 것을 알 수 있습니다. 이러한 라벨은 다음 예와 같이 /. 또는 /로 끝나며, 다음은 사용해서는 안 됩니다.

권장하지 않음: data = ["//data/regression:unittest/."]

권장하지 않음: data = ["testdata/."]

권장하지 않음: data = ["testdata/"]

이는 특히 테스트의 경우 편한 것으로 보입니다. 테스트를 통해 디렉터리의 모든 데이터 파일을 사용할 수 있기 때문입니다.

하지만 이렇게 해서는 안 됩니다. 변경 후 올바른 증분 재빌드 (및 테스트 재실행)를 보장하기 위해 빌드 시스템은 빌드 (또는 테스트)의 입력인 전체 파일 세트를 알고 있어야 합니다. 디렉터리를 지정하면 빌드 시스템은 디렉터리 자체가 변경될 때만 (파일 추가 또는 삭제로 인해) 재빌드를 수행하지만 개별 파일에 대한 수정사항은 인클로징 디렉터리에 영향을 주지 않으므로 이를 감지할 수 없습니다. 디렉터리를 빌드 시스템의 입력으로 지정하는 대신 명시적으로 또는 glob() 함수를 사용하여 디렉터리 내에 포함된 파일 집합을 열거해야 합니다. **를 사용하여 glob()를 재귀적으로 강제 적용합니다.

권장: data = glob(["testdata/**"])

안타깝게도 디렉터리 라벨을 사용해야 하는 시나리오가 있습니다. 예를 들어 testdata 디렉터리에 이름이 라벨 구문을 준수하지 않는 파일이 포함되어 있으면 파일을 명시적으로 열거하거나 glob() 함수를 사용하면 잘못된 라벨 오류가 발생합니다. 이 경우 디렉터리 라벨을 사용해야 하지만 위에서 설명한 잘못된 재빌드의 관련 위험에 주의하세요.

디렉터리 라벨을 사용해야 하는 경우 상대 ../ 경로로 상위 패키지를 참조할 수 없습니다. 대신 //data/regression:unittest/.와 같은 절대 경로를 사용하세요.

여러 파일을 사용해야 하는 테스트와 같은 외부 규칙은 모든 파일에 대한 종속 항목을 명시적으로 선언해야 합니다. filegroup()를 사용하여 BUILD 파일에서 파일을 그룹화할 수 있습니다.

filegroup(
        name = 'my_data',
        srcs = glob(['my_unittest_data/*'])
)

그런 다음 my_data 라벨을 테스트의 데이터 종속 항목으로 참조할 수 있습니다.

파일 빌드 가시성