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

문제 신고 소스 보기 1박 · 7.2 · 7.1 · 7.0 · 6.5 · 6.4

여기에서는 C++ 프로젝트 빌드를 위한 가장 일반적인 사용 사례를 확인할 수 있습니다. Bazel을 사용해 보세요 아직 C++ 빌드를 시작하지 않았다면 지금 시작합니다. 튜토리얼을 완료하여 Bazel로 프로젝트 만들기 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.h에는 bread.h가 포함되고 bread.h에는 flour.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 라이브러리는 bread 라이브러리에 종속되며 이 라이브러리에는 (flour 라이브러리)

포함 경로 추가

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

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

Bazel은 some_lib.h이 다음과 같이 포함될 것으로 예상합니다. legacy/some_lib/include/some_lib.h이지만 some_lib.cc가 다음을 포함한다고 가정하겠습니다. "some_lib.h"입니다. 포함 경로를 유효하게 만들려면 legacy/some_lib/BUILDsome_lib/include가 include 디렉터리는

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

헤더 파일이 포함되어 있기 때문에 외부 종속 항목에 특히 유용합니다. 그렇지 않으면 / 접두사와 함께 포함되어야 합니다.

외부 라이브러리 포함

Google Test를 사용한다고 가정해 보겠습니다. WORKSPACE 파일의 저장소 함수 중 하나를 사용하여 다음 작업을 할 수 있습니다. Google Test를 다운로드하여 저장소에 제공합니다.

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 규칙을 만드는 요구사항 더 복잡함:

  • 그 외 모든 #include googletest-release-1.10.0/src/gtest-all.ccgoogletest-release-1.10.0/src/의 파일: 다음 항목에서 제외합니다. 컴파일하여 중복 기호에 대한 링크 오류를 방지합니다.

  • 이 파일은 googletest-release-1.10.0/include/ 디렉터리 ("gtest/gtest.h")를 연결하므로 해당 디렉터리를 포함 경로에 추가합니다.

  • 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입니다. 아카이브 구조의 부산물입니다. http_archive 스트립을 만들 수 있습니다. strip_prefix 속성을 추가하여 이 접두사를 추가합니다.

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-greet을(를) hello-test에 공개하려면 다음을 추가해야 합니다. "//test:__pkg__",./main/BUILDvisibility 속성에 추가합니다.

이제 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++ 대상이 이 규칙에 종속될 수 있습니다.