일반적인 C++ 빌드 사용 사례

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

Bazel을 사용하여 C++ 프로젝트를 빌드하는 가장 일반적인 사용 사례는 다음과 같습니다. Bazel 소개: C++ 프로젝트 빌드 가이드를 완료하여 Bazel로 C++ 프로젝트 빌드를 시작하세요.

cc_library 및 hdrs 헤더 파일에 관한 자세한 내용은 cc_library를 참고하세요.

타겟에 여러 파일 포함

glob을 사용하여 단일 대상에 여러 파일을 포함할 수 있습니다. 예를 들면 다음과 같습니다.

cc_library(
    name = "build-all-the-files",
    srcs = glob(["*.cc"]),
    hdrs = glob(["*.h"]),
)

이 대상으로 Bazel은 찾은 모든 .cc.h 파일을 이 대상을 포함하는 BUILD 파일 (하위 디렉터리 제외)과 동일한 디렉터리에서 빌드합니다.

전이적 포함 사용

파일에 헤더가 포함되어 있으면 이 파일을 소스로 사용하는 규칙 (즉, srcs, hdrs 또는 textual_hdrs 속성에 이 파일이 있음)은 포함된 헤더의 라이브러리 규칙에 종속되어야 합니다. 반대로 직접 종속 항목만 지정하기만 하면 됩니다. 예를 들어 sandwich.hbread.h가 포함되고 bread.hflour.h가 포함되어 있다고 가정해 보겠습니다. sandwich.h에는 샌드위치에 밀가루를 원하는 flour.h가 포함되어 있지 않으므로 BUILD 파일은 다음과 같습니다.

cc_library(
    name = "sandwich",
    srcs = ["sandwich.cc"],
    hdrs = ["sandwich.h"],
    deps = [":bread"],
)

cc_library(
    name = "bread",
    srcs = ["bread.cc"],
    hdrs = ["bread.h"],
    deps = [":flour"],
)

cc_library(
    name = "flour",
    srcs = ["flour.cc"],
    hdrs = ["flour.h"],
)

여기서 sandwich 라이브러리는 flour 라이브러리에 종속되는 bread 라이브러리에 종속됩니다.

포함 경로 추가

작업공간 루트에서 루트를 포함하는 경로를 포함할 수 없거나 원하지 않을 때가 있습니다. 기존 라이브러리에는 작업공간의 경로와 일치하지 않는 포함 디렉터리가 이미 있을 수 있습니다. 예를 들어 디렉터리 구조가 다음과 같다고 가정해 보겠습니다.

└── my-project
    ├── legacy
    │   └── some_lib
    │       ├── BUILD
    │       ├── include
    │       │   └── some_lib.h
    │       └── some_lib.cc
    └── WORKSPACE

Bazel은 some_lib.hlegacy/some_lib/include/some_lib.h으로 포함될 것으로 예상하지만 some_lib.cc"some_lib.h"이 포함되어 있다고 가정합니다. 포함 경로를 유효하게 만들려면 legacy/some_lib/BUILD에서 some_lib/include 디렉터리가 포함 디렉터리임을 지정해야 합니다.

cc_library(
    name = "some_lib",
    srcs = ["some_lib.cc"],
    hdrs = ["include/some_lib.h"],
    copts = ["-Ilegacy/some_lib/include"],
)

헤더 파일은 반드시 / 접두어와 함께 포함되어야 하므로 외부 종속 항목에 특히 유용합니다.

외부 라이브러리 포함

Google Test를 사용한다고 가정해 보겠습니다. WORKSPACE 파일의 저장소 함수 중 하나를 사용하여 Google 테스트를 다운로드하고 저장소에서 사용할 수 있습니다.

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
    name = "gtest",
    url = "https://github.com/google/googletest/archive/release-1.10.0.zip",
    sha256 = "94c634d499558a76fa649edb13721dce6e98fb1e7018dfaeba3cd7a083945e91",
    build_file = "@//:gtest.BUILD",
)

그런 다음 Google 테스트를 컴파일하는 데 사용되는 BUILD 파일인 gtest.BUILD를 만듭니다. Google 테스트에는 cc_library 규칙을 더 복잡하게 만드는 몇 가지 '특수' 요구사항이 있습니다.

  • googletest-release-1.10.0/src/gtest-all.ccgoogletest-release-1.10.0/src/에 있는 다른 모든 파일을 #include합니다. 중복 기호의 링크 오류를 방지하기 위해 컴파일에서 이를 제외합니다.

  • googletest-release-1.10.0/include/ 디렉터리("gtest/gtest.h")를 기준으로 한 헤더 파일을 사용하므로 이 디렉터리를 include 경로에 추가해야 합니다.

  • pthread에서 연결해야 하므로 linkopt으로 추가합니다.

따라서 최종 규칙은 다음과 같습니다.

cc_library(
    name = "main",
    srcs = glob(
        ["googletest-release-1.10.0/src/*.cc"],
        exclude = ["googletest-release-1.10.0/src/gtest-all.cc"]
    ),
    hdrs = glob([
        "googletest-release-1.10.0/include/**/*.h",
        "googletest-release-1.10.0/src/*.h"
    ]),
    copts = [
        "-Iexternal/gtest/googletest-release-1.10.0/include",
        "-Iexternal/gtest/googletest-release-1.10.0"
    ],
    linkopts = ["-pthread"],
    visibility = ["//visibility:public"],
)

이는 다소 지저분합니다. 모든 항목이 보관 파일 구조의 부산물로 googletest-release-1.10.0로 시작됩니다. strip_prefix 속성을 추가하여 http_archive가 이 프리픽스를 삭제하도록 할 수 있습니다.

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
    name = "gtest",
    url = "https://github.com/google/googletest/archive/release-1.10.0.zip",
    sha256 = "94c634d499558a76fa649edb13721dce6e98fb1e7018dfaeba3cd7a083945e91",
    build_file = "@//:gtest.BUILD",
    strip_prefix = "googletest-release-1.10.0",
)

그러면 gtest.BUILD는 다음과 같습니다.

cc_library(
    name = "main",
    srcs = glob(
        ["src/*.cc"],
        exclude = ["src/gtest-all.cc"]
    ),
    hdrs = glob([
        "include/**/*.h",
        "src/*.h"
    ]),
    copts = ["-Iexternal/gtest/include"],
    linkopts = ["-pthread"],
    visibility = ["//visibility:public"],
)

이제 cc_ 규칙은 @gtest//:main에 종속될 수 있습니다.

C++ 테스트 작성 및 실행

예를 들어 다음과 같은 테스트 ./test/hello-test.cc를 만들 수 있습니다.

#include "gtest/gtest.h"
#include "main/hello-greet.h"

TEST(HelloTest, GetGreet) {
  EXPECT_EQ(get_greet("Bazel"), "Hello Bazel");
}

그런 다음 테스트용 ./test/BUILD 파일을 만듭니다.

cc_test(
    name = "hello-test",
    srcs = ["hello-test.cc"],
    copts = ["-Iexternal/gtest/include"],
    deps = [
        "@gtest//:main",
        "//main:hello-greet",
    ],
)

hello-greethello-test에 표시하려면 ./main/BUILDvisibility 속성에 "//test:__pkg__",를 추가해야 합니다.

이제 bazel test를 사용하여 테스트를 실행할 수 있습니다.

bazel test test:hello-test

그러면 다음과 같이 출력됩니다.

INFO: Found 1 test target...
Target //test:hello-test up-to-date:
  bazel-bin/test/hello-test
INFO: Elapsed time: 4.497s, Critical Path: 2.53s
//test:hello-test PASSED in 0.3s

Executed 1 out of 1 tests: 1 test passes.

사전 컴파일된 라이브러리에 종속 항목 추가

컴파일된 버전만 있는 라이브러리 (예: 헤더 및 .so 파일)를 사용하려면 cc_library 규칙으로 래핑합니다.

cc_library(
    name = "mylib",
    srcs = ["mylib.so"],
    hdrs = ["mylib.h"],
)

이렇게 하면 작업공간의 다른 C++ 대상이 이 규칙에 종속될 수 있습니다.