빌드 스타일 가이드

BUILD 파일 형식 지정은 표준화된 도구가 대부분의 형식 지정 문제를 처리하는 Go와 동일한 접근 방식을 따릅니다. Buildifier는 표준 스타일로 소스 코드를 파싱하고 내보내는 도구입니다. 따라서 모든 BUILD 파일은 동일한 자동화된 방식으로 형식이 지정되므로 코드 검토 중에 형식 지정이 문제가 되지 않습니다. 또한 도구가 이해하고, 수정하고, BUILD 파일을 생성하는 것을 더 쉽게 만듭니다.

BUILD 파일 형식 지정은 buildifier의 출력과 일치해야 합니다.

형식 지정 예시

# Test code implementing the Foo controller.
package(default_testonly = True)

py_test(
    name = "foo_test",
    srcs = glob(["*.py"]),
    data = [
        "//data/production/foo:startfoo",
        "//foo",
        "//third_party/java/jdk:jdk-k8",
    ],
    flaky = True,
    deps = [
        ":check_bar_lib",
        ":foo_data_check",
        ":pick_foo_port",
        "//pyglib",
        "//testing/pybase",
    ],
)

파일 구조

권장사항: 다음 순서를 사용하세요 (모든 요소는 선택사항임).

  • 패키지 설명 (주석)

  • 모든 load()

  • package() 함수

  • 규칙 및 매크로 호출

Buildifier는 독립형 주석과 요소에 연결된 주석을 구분합니다. 주석이 특정 요소에 연결되지 않은 경우 주석 뒤에 빈 줄을 사용합니다. 이 구분은 자동 변경을 실행할 때 (예: 규칙을 삭제할 때 주석을 유지하거나 삭제) 중요합니다.

# Standalone comment (such as to make a section in a file)

# Comment for the cc_library below
cc_library(name = "cc")

현재 패키지의 타겟 참조

파일은 패키지 디렉터리를 기준으로 하는 경로로 참조해야 합니다 (절대 ..와 같은 상위 참조를 사용하지 않음). 생성된 파일에는 소스가 아님을 나타내는 ":" 프리픽스가 붙어야 합니다. 소스 파일 에는 : 프리픽스가 붙으면 안 됩니다. 규칙에는 : 프리픽스가 붙어야 합니다. 예를 들어 x.cc가 소스 파일이라고 가정해 보겠습니다.

cc_library(
    name = "lib",
    srcs = ["x.cc"],
    hdrs = [":gen_header"],
)

genrule(
    name = "gen_header",
    srcs = [],
    outs = ["x.h"],
    cmd = "echo 'int x();' > $@",
)

타겟 이름 지정

타겟 이름은 설명적이어야 합니다. 타겟에 소스 파일이 하나 포함되어 있는 경우 일반적으로 타겟의 이름은 해당 소스에서 파생되어야 합니다 (예: chat.cccc_librarychat로 이름을 지정할 수 있고 DirectMessage.javajava_librarydirect_message로 이름을 지정할 수 있음).

패키지의 동명 타겟 (포함 디렉터리와 이름이 같은 타겟)은 디렉터리 이름으로 설명된 기능을 제공해야 합니다. 이러한 타겟이 없으면 동명 타겟을 만들지 마세요.

동명 타겟을 참조할 때는 짧은 이름을 사용하는 것이 좋습니다 (//x //x:x 대신). 동일한 패키지에 있는 경우 로컬 참조 (:x 대신 //x)를 사용하는 것이 좋습니다.

특별한 의미가 있는 '예약된' 타겟 이름은 사용하지 마세요. 여기에는 all, __pkg__, __subpackages__가 포함됩니다. 이러한 이름에는 특별한 의미가 있으며 사용하면 혼동과 예기치 않은 동작이 발생할 수 있습니다.

일반적인 팀 규칙이 없는 경우 Google에서 널리 사용되는 몇 가지 비구속적 권장사항은 다음과 같습니다.

  • 일반적으로 "snake_case"를 사용합니다.
  • `java_library`가 하나인 `src`의 경우 확장자가 없는 파일 이름과 동일하지 않은 이름을 사용합니다.
    • Java *_binary*_test 규칙의 경우 "Upper CamelCase"를 사용합니다. 이렇게 하면 타겟 이름이 src 중 하나와 일치할 수 있습니다. java_test의 경우 이렇게 하면 test_class 속성을 타겟 이름에서 추론할 수 있습니다.
  • 특정 타겟의 변형이 여러 개 있는 경우 접미사를 추가하여 명확히 합니다 (예: :foo_dev, :foo_prod 또는 :bar_x86, :bar_x64).
  • _test, _unittest, Test 또는 Tests로 접미사 _test 타겟
  • _lib 또는 _library와 같은 의미 없는 접미사는 사용하지 마세요 (_library 타겟과 상응하는 _binary 간의 충돌을 방지하는 데 필요한 경우 제외).
  • proto 관련 타겟의 경우:
    • proto_library 타겟의 이름은 _proto로 끝나야 합니다.
    • 언어별 *_proto_library 규칙은 기본 proto와 일치해야 하지만 _proto를 다음과 같은 언어별 접미사로 바꿔야 합니다.
      • cc_proto_library: _cc_proto
      • java_proto_library: _java_proto
      • java_lite_proto_library: _java_proto_lite

공개 상태

공개 상태는 테스트 및 역방향 종속 항목의 액세스를 허용하면서 최대한 좁은 범위로 지정해야 합니다. 필요에 따라 __pkg____subpackages__를 사용합니다.

패키지 default_visibility//visibility:public으로 설정하지 마세요. //visibility:public은 프로젝트의 공개 API에 있는 타겟에 대해서만 개별적으로 설정해야 합니다. 이러한 타겟은 외부 프로젝트에서 종속되도록 설계된 라이브러리 또는 외부 프로젝트의 빌드 프로세스에서 사용할 수 있는 바이너리일 수 있습니다.

종속 항목

종속 항목은 직접 종속 항목 (규칙에 나열된 소스에 필요한 종속 항목) 으로 제한해야 합니다. 전이 종속 항목을 나열하지 마세요.

패키지 로컬 종속 항목은 먼저 나열해야 하며 위의 현재 패키지의 타겟 참조 섹션과 호환되는 방식으로 참조해야 합니다 (절대 패키지 이름으로 참조하지 않음).

종속 항목을 단일 목록으로 직접 나열하는 것이 좋습니다. 여러 타겟의 "일반" 종속 항목을 변수에 넣으면 유지보수성이 저하되고 도구가 타겟의 종속 항목을 변경할 수 없게 되며 사용되지 않는 종속 항목이 발생할 수 있습니다.

Glob

`[]`로 '타겟 없음'을 나타냅니다. 아무것도 일치하지 않는 glob은 사용하지 마세요. 오류가 발생하기 쉽고 빈 목록보다 명확하지 않습니다.

재귀적

재귀적 glob을 사용하여 소스 파일을 일치시키지 마세요 (예: glob(["**/*.java"])).

재귀적 glob은 BUILD 파일을 추론하기 어렵게 만듭니다. BUILD 파일이 포함된 하위 디렉터리를 건너뛰기 때문입니다.

재귀적 glob은 일반적으로 디렉터리당 BUILD 파일이 있고 그 사이에 종속 항목 그래프가 정의되어 있는 것보다 효율성이 떨어집니다. 이렇게 하면 더 나은 원격 캐싱과 병렬 처리가 가능하기 때문입니다.

각 디렉터리에서 BUILD 파일을 작성하고 그 사이에 종속 항목 그래프를 정의하는 것이 좋습니다.

비재귀적

비재귀적 glob은 일반적으로 허용됩니다.

기타 규칙

  • 상수 (예: GLOBAL_CONSTANT)를 선언할 때는 대문자와 밑줄을 사용하고 변수 (예: my_variable)를 선언할 때는 소문자와 밑줄을 사용합니다.

  • 라벨은 79자(영문 기준)보다 길더라도 절대 분할해서는 안 됩니다. 라벨은 가능하면 문자열 리터럴이어야 합니다. 사유: 찾기 및 바꾸기를 쉽게 만듭니다. 또한 가독성을 개선합니다.

  • name 속성의 값은 리터럴 상수 문자열이어야 합니다 (매크로 제외 ). 사유: 외부 도구는 name 속성을 사용하여 규칙을 참조합니다. 코드를 해석하지 않고 규칙을 찾아야 합니다.

  • 부울 유형 속성을 설정할 때는 정수 값이 아닌 부울 값을 사용합니다. 이전 버전과의 호환성을 위해 규칙은 필요에 따라 정수를 부울로 변환하지만 권장되지는 않습니다. 사유: flaky = 1은 "한 번 다시 실행하여 이 타겟을 deflake"라고 잘못 해석될 수 있습니다. flaky = True는 "이 테스트는 불안정함"이라고 명확하게 말합니다.

Python 스타일 가이드와의 차이점

Python 스타일 가이드와의 호환성이 목표이지만 몇 가지 차이점이 있습니다.

  • 엄격한 줄 길이 제한이 없습니다. 긴 주석과 긴 문자열은 79열로 분할되는 경우가 많지만 필수는 아닙니다. 코드 검토 또는 사전 제출 스크립트에서 적용해서는 안 됩니다. 사유: 라벨은 길어서 이 제한을 초과할 수 있습니다. BUILD 파일은 도구에서 생성하거나 수정하는 경우가 많으며 줄 길이 제한과 잘 맞지 않습니다.

  • 암시적 문자열 연결은 지원되지 않습니다. + 연산자를 사용합니다. 사유: BUILD 파일에는 많은 문자열 목록이 포함되어 있습니다. 쉼표를 잊어버리기 쉽고 완전히 다른 결과가 발생합니다. 이로 인해 과거에 많은 버그가 발생했습니다. 이 토론도 참고하세요.

  • 규칙의 키워드 인수에 = 기호 주위에 공백을 사용합니다. 사유: 명명된 인수는 Python보다 훨씬 더 자주 사용되며 항상 별도의 줄에 있습니다. 공백은 가독성을 개선합니다. 이 규칙은 오랫동안 사용되어 왔으며 기존 BUILD 파일을 모두 수정할 가치가 없습니다.

  • 기본적으로 문자열에는 큰따옴표를 사용합니다. 사유: Python 스타일 가이드에 지정되어 있지는 않지만 일관성을 유지하는 것이 좋습니다. 따라서 큰따옴표로 묶인 문자열만 사용하기로 했습니다. 많은 언어에서 문자열 리터럴에 큰따옴표를 사용합니다.

  • 두 개의 최상위 정의 사이에 빈 줄 하나를 사용합니다. 사유: 파일의 구조는 일반적인 Python 파일과 다릅니다.BUILD 최상위 문만 있습니다. 빈 줄 하나를 사용하면 BUILD 파일이 짧아집니다.