Các trường hợp sử dụng thường xuyên bản dựng C++

Sử dụng bộ sưu tập để sắp xếp ngăn nắp các trang Lưu và phân loại nội dung dựa trên lựa chọn ưu tiên của bạn.
Báo cáo sự cố Xem nguồn

Dưới đây là một số trường hợp sử dụng phổ biến nhất để xây dựng dự án C++ bằng Bazel. Hãy bắt đầu xây dựng dự án C++ bằng Bazel bằng cách hoàn thành phần hướng dẫn Giới thiệu về Bazel: Xây dựng dự án C++ nếu bạn chưa thực hiện.

Để biết thông tin về các tệp tiêu đề cc_library và hdrs, hãy xem cc_library.

Đưa nhiều tệp vào cùng một mục tiêu

Bạn có thể đưa nhiều tệp vào một mục tiêu bằng glob. Ví dụ:

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

Với mục tiêu này, Bazel sẽ tạo tất cả tệp .cc.h tìm thấy trong cùng thư mục với tệp BUILD chứa mục tiêu này (ngoại trừ thư mục con).

Sử dụng bắc cầu bao gồm

Nếu một tệp bao gồm tiêu đề, thì mọi quy tắc có tệp đó dưới dạng nguồn (nghĩa là có tệp đó trong thuộc tính srcs, hdrs hoặc textual_hdrs) sẽ phụ thuộc vào quy tắc thư viện của tiêu đề đi kèm. Ngược lại, bạn chỉ cần chỉ định các phần phụ thuộc trực tiếp làm phần phụ thuộc. Ví dụ: giả sử sandwich.h bao gồm bread.hbread.h bao gồm flour.h. sandwich.h không bao gồm flour.h (người muốn sử dụng bột mì trong bánh mì kẹp của họ?). Vì vậy, tệp BUILD sẽ có dạng như sau:

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"],
)

Ở đây, thư viện sandwich phụ thuộc vào thư viện bread. Thư viện này phụ thuộc vào thư viện flour.

Thêm đường dẫn bao gồm

Đôi khi, bạn không thể (hoặc không muốn) bao gồm đường dẫn ở thư mục gốc của không gian làm việc. Các thư viện hiện tại có thể đã có một thư mục include không khớp với đường dẫn của thư mục đó trong không gian làm việc của bạn. Ví dụ: giả sử bạn có cấu trúc thư mục sau:

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

Bazel sẽ dự kiến some_lib.h được bao gồm dưới dạng legacy/some_lib/include/some_lib.h, nhưng giả sử some_lib.cc sẽ bao gồm "some_lib.h". Để đường dẫn đó bao gồm đường dẫn hợp lệ,legacy/some_lib/BUILD cần chỉ định rằng thư mục some_lib/include là thư mục bao gồm:

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

Điều này đặc biệt hữu ích cho các phần phụ thuộc bên ngoài vì tệp tiêu đề của các phần phụ thuộc đó phải được đưa vào trước tiền tố /.

Bao gồm các thư viện bên ngoài

Giả sử bạn đang sử dụng Google Test. Bạn có thể sử dụng một trong các hàm lưu trữ trong tệp WORKSPACE để tải Google Test xuống và cung cấp trong kho lưu trữ:

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",
)

Sau đó, hãy tạo gtest.BUILD, một tệp BUILD dùng để biên dịch Google Test. Google Test có một số yêu cầu "đặc biệt" khiến quy tắc cc_library trở nên phức tạp hơn:

  • googletest-release-1.10.0/src/gtest-all.cc #include tất cả tệp khác trong googletest-release-1.10.0/src/: loại trừ tệp đó khỏi quá trình biên dịch để ngăn lỗi liên kết ký hiệu.

  • Tệp này sử dụng các tệp tiêu đề tương ứng với thư mục googletest-release-1.10.0/include/ ("gtest/gtest.h"), vì vậy, bạn phải thêm thư mục đó vào các đường dẫn bao gồm.

  • Lớp này cần liên kết trong pthread, vì vậy hãy thêm liên kết đó dưới dạng linkopt.

Do đó, quy tắc cuối cùng sẽ có dạng như sau:

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"],
)

Điều này có vẻ lộn xộn: mọi thứ đều được thêm tiền tố googletest-release-1.10.0 vào làm sản phẩm phụ của cấu trúc kho lưu trữ. Bạn có thể đặt http_archive bỏ tiền tố này bằng cách thêm thuộc tính 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",
)

Khi đó, gtest.BUILD sẽ có dạng như sau:

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"],
)

Hiện tại, các quy tắc cc_ có thể phụ thuộc vào @gtest//:main.

Viết và chạy kiểm thử C++

Ví dụ: bạn có thể tạo một ./test/hello-test.cc kiểm thử, chẳng hạn như:

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

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

Sau đó, hãy tạo tệp ./test/BUILD cho kiểm thử:

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

Để hello-greet hiển thị với hello-test, bạn phải thêm "//test:__pkg__", vào thuộc tính visibility trong ./main/BUILD.

Bây giờ, bạn có thể sử dụng bazel test để chạy kiểm thử.

bazel test test:hello-test

Thao tác này sẽ tạo ra kết quả sau:

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.

Thêm phần phụ thuộc vào thư viện được biên dịch trước

Nếu muốn sử dụng một thư viện mà bạn chỉ có phiên bản được biên dịch (ví dụ: tiêu đề và tệp .so), hãy gói thư viện đó trong quy tắc cc_library:

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

Bằng cách này, các mục tiêu C++ khác trong không gian làm việc của bạn có thể phụ thuộc vào quy tắc này.