Tại đây, bạn sẽ tìm thấy một số trường hợp sử dụng phổ biến nhất khi xây dựng dự án C++ cùng với Bazel. Nếu bạn chưa làm như vậy, hãy bắt đầu xây dựng C++ dự án cù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++.
Để biết thông tin về tệp tiêu đề cc_library và hdrs, hãy xem cc_library.
Đưa nhiều tệp vào một mục tiêu
Bạn có thể bao gồm nhiều tệp trong một mục tiêu duy nhất bằng toàn cầu. 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ả các tệp .cc
và .h
mà Bazel 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 ngoại động từ bao gồm
Nếu một tệp chứa tiêu đề, thì mọi quy tắc có tệp đó dưới dạng nguồn (tức là
có tệp đó trong thuộc tính srcs
, hdrs
hoặc textual_hdrs
)
phụ thuộc vào quy tắc thư viện của tiêu đề đi kèm. Ngược lại, chỉ giao dịch trực tiếp
phần phụ thuộc cần được chỉ định làm phần phụ thuộc. Ví dụ: giả sử
sandwich.h
bao gồm bread.h
và bread.h
bao gồm flour.h
. sandwich.h
không bao gồm flour.h
(ai muốn có bột mì trong bánh sandwich?), vì vậy, BUILD
tệp 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
trên 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 các đường dẫn tại không gian làm việc thư mục gốc. Các thư viện hiện có có thể đã có thư mục "bao gồm" nhưng không được khớp với đường dẫn trong không gian làm việc của bạn. Ví dụ, giả sử bạn có như sau cấu trúc thư mục:
└── my-project
├── legacy
│ └── some_lib
│ ├── BUILD
│ ├── include
│ │ └── some_lib.h
│ └── some_lib.cc
└── WORKSPACE
Bazel dự kiến sẽ thêm some_lib.h
dưới dạng
legacy/some_lib/include/some_lib.h
, nhưng giả sử some_lib.cc
bao gồm
"some_lib.h"
. Để làm cho đường dẫn bao gồm hợp lệ,
legacy/some_lib/BUILD
sẽ cần chỉ định rằng some_lib/include
thư mục là một thư mục include:
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 với các phần phụ thuộc bên ngoài, vì các tệp tiêu đề của chúng
nếu không thì phải đi kèm với 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 kho lưu trữ trong tệp WORKSPACE
để
tải Google Test xuống và cung cấp trong kho lưu trữ của bạn:
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ố "đặc biệt" các yêu cầu tạo nên quy tắc cc_library
phức tạp hơn:
Tất cả
googletest-release-1.10.0/src/gtest-all.cc
#include
khác các tệp tronggoogletest-release-1.10.0/src/
: loại trừ tệp đó khỏi biên dịch để ngăn lỗi liên kết đối với các ký hiệu trùng lặp.Phương thức này sử dụng các tệp tiêu đề có liên quan đến 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 đường dẫn bao gồm.Cần liên kết trong
pthread
, vì vậy, hãy thêm dưới dạnglinkopt
.
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ó phần rối rắm: mọi thứ đều có tiền tố googletest-release-1.10.0
làm sản phẩm phụ trong cấu trúc kho lưu trữ. Bạn có thể tạo dải http_archive
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",
)
Thì 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 các chương trình kiểm thử của bạn:
cc_test(
name = "hello-test",
srcs = ["hello-test.cc"],
copts = ["-Iexternal/gtest/include"],
deps = [
"@gtest//:main",
"//main:hello-greet",
],
)
Để hello-test
hiển thị hello-greet
, bạn phải thêm
"//test:__pkg__",
cho thuộc tính visibility
trong ./main/BUILD
.
Bây giờ, bạn có thể sử dụng bazel test
để chạy chương trình kiểm thử.
bazel test test:hello-test
Thao tác này sẽ cho 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 trên các thư viện được biên dịch trước
Nếu bạn muốn sử dụng thư viện trong đó bạn chỉ có phiên bản được biên dịch (cho
ví dụ như tiêu đề và tệp .so
) gói nội dung đó vào một 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.