빌드 스타일 가이드

문제 신고 소스 보기

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() 함수

  • 규칙 및 매크로 호출

빌드 도구는 요소에 연결된 독립형 주석과 댓글을 구분합니다. 주석이 특정 요소에 연결되어 있지 않으면 그 뒤에 빈 줄을 사용합니다. 이러한 구분은 자동 변경 (예: 규칙 삭제 시 주석을 유지 또는 삭제)할 때 중요합니다.

# 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.cc의 경우 cc_library의 이름을 chat로, DirectMessage.java의 경우 java_library의 이름을 direct_message로 지정할 수 있음).

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

이름이 같은 타겟 (//x:x 대신 //x 사용)을 언급할 때는 짧은 이름을 사용하는 것이 좋습니다. 동일한 패키지를 사용 중인 경우 로컬 참조 (//x가 아닌 :x)를 사용하는 것이 좋습니다.

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

일반적인 팀 규칙이 없는 경우 Google에서 광범위하게 사용되는 다음과 같은 구속력 없는 권장사항이 있습니다.

  • 일반적으로 "snake_case"
    • src이 하나 있는 java_library의 경우 확장자가 없는 파일 이름과 동일하지 않은 이름을 사용합니다.
    • 자바 *_binary*_test 규칙에는 "Upper CamelCase"를 사용합니다. 이렇게 하면 타겟 이름이 src 중 하나와 일치하게 됩니다. java_test의 경우 test_class 속성을 타겟 이름에서 유추할 수 있습니다.
  • 특정 타겟의 변형이 여러 개 있는 경우 서픽스를 추가하여 구별합니다 (예: :foo_dev, :foo_prod 또는 :bar_x86, :bar_x64)
  • _test, _unittest, Test 또는 Tests로 대상 _test개 서픽스 추가
  • _library 타겟과 해당 _binary 간의 충돌을 방지하기 위해 필요한 경우가 아니라면 _lib_library와 같은 무의미한 접미사는 사용하지 않아야 합니다.
  • 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자보다 길더라도 분할해서는 안 됩니다. 라벨은 가능할 때마다 문자열 리터럴이어야 합니다. 이유: 찾기 쉽고 교체하기가 쉽습니다. 또한 가독성도 개선됩니다.

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

  • 부울 유형 속성을 설정할 때는 정수 값이 아닌 부울 값을 사용합니다. 기존 규칙으로 인해 필요에 따라 규칙에서 여전히 정수를 부울로 변환하지만, 이 방법은 권장되지 않습니다. 사유: flaky = 1는 '한 번 다시 실행하여 이 대상을 손실 처리'하라고 잘못 인식할 수 있습니다. flaky = True는 '이 테스트는 불안정합니다'라고 분명히 말합니다.

Python 스타일의 차이점 가이드

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

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

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

  • 규칙의 키워드 인수에 = 기호 주위의 공백을 사용합니다. 이유: 이름이 지정된 인수는 Python보다 빈도가 훨씬 높으며 항상 별도의 줄에 있습니다. 스페이스를 사용하면 가독성이 향상됩니다. 이 규칙은 오랫동안 사용되어 왔으며 기존의 모든 BUILD 파일을 수정할 필요가 없습니다.

  • 기본적으로 문자열에 큰따옴표를 사용하세요. 사유: Python 스타일 가이드에 명시되어 있지 않지만 일관성을 권장합니다. 따라서 큰따옴표로 된 문자열만 사용하기로 했습니다. 많은 언어에서 문자열 리터럴에 큰따옴표를 사용합니다.

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