在一個target中包含多個文件
可以利用glob在單個target中包含多個文件,例如:
cc_library(
name = "build-all-the-files",
srcs = glob(["*.cc"])
hdrs = glob(["*.h"]),
)
在這個target中,Bazel會編譯BUILD文件所在目錄下的所有.cc和.h文件(不包括子目錄)。
includes可以進行傳遞
如果一個文件包括頭文件,那麼這個文件的規則也受到頭文件所包含的庫的影響咯?其實,我們只需要指定直接的依賴項爲依賴項即可。比如說,假如sandwich.h包含bread.h,bread.h又包含floor.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"],
)
添加include路徑
有時不能(或不願)讓依賴文件的路徑包含其相對於工作區根目錄的路徑。因爲現有的庫可能已經擁有了與工作區路徑不匹配的目錄。例如,假設有以下目錄結構:
└── my-project
├── third_party
│ └── some_lib
│ ├── BUILD
│ ├── include
│ │ └── some_lib.h
│ └── some_lib.cc
└── WORKSPACE
Bazel 希望some_lib.h被include的時候是以third_party/some_lib/include/some_lib.h這一路徑來include的,但是some_lib.cc包含它的時候用的路徑卻是include/some_lib.h。爲了使包含路徑有效, third_party/some_lib/BUILD需要指定some_lib是一個包含目錄:
cc_library(
name = "some_lib",
srcs = ["some_lib.cc"],
hdrs = ["some_lib.h"],
copts = ["-Ithird_party/some_lib"],
)
這一點對於加入外部依賴項非常有用。
包含外部庫
假設你正在使用Google Test.你可以在WORKSPACE文件中使用一種repo function來下載Google Test並且把它用於你的repo:
http_archive(
name = "gtest",
url = "https://github.com/google/googletest/archive/release-1.7.0.zip",
sha256 = "b58cb7547a28b2c718d1e38aee18a3659c9e3ff52440297e965f5edffe34b6d0",
build_file = "gtest.BUILD",
)
注意,如果目標位置已經包含了一個BUILD文件,則可以使用non-new_函數。
然後創建gtest.BUILD,一個用於編譯Google Test的BUILD文件。Google Test有幾個特殊要求使它的cc_library規則更加複雜:
- googletest-release-1.7.0/src/gtest-all.cc 包含了googletest-release-1.7.0/src/中的所有其他文件,所以我們需要在編譯時去掉它,否則會由於duplicate symbols而出現link errors。
- 所使用的頭文件都是相對於 googletest-release-1.7.0/include/目錄的 (“gtest/gtest.h”),所以我們必須把這個文件加到include路徑中。
- 它還需要link pthread, 所以我們以 linkopt的方式加。
那麼根據以上規則,BUILD文件可以寫成這樣:
cc_library(
name = "main",
srcs = glob(
["googletest-release-1.7.0/src/*.cc"],
exclude = ["googletest-release-1.7.0/src/gtest-all.cc"]
),
hdrs = glob([
"googletest-release-1.7.0/include/**/*.h",
"googletest-release-1.7.0/src/*.h"
]),
copts = [
"-Iexternal/gtest/googletest-release-1.7.0/include"
],
linkopts = ["-pthread"],
visibility = ["//visibility:public"],
)
這看起來有點亂:一切都加了個前綴googletest-1.7.0作爲archive文件結構的副產品。我們可以通過添加strip_prefix屬性使http_archive帶上這個前綴:
、http_archive(
name = "gtest",
url = "https://github.com/google/googletest/archive/release-1.7.0.zip",
sha256 = "b58cb7547a28b2c718d1e38aee18a3659c9e3ff52440297e965f5edffe34b6d0",
build_file = "gtest.BUILD",
strip_prefix = "googletest-release-1.7.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_rules依賴於@gtest/main。
編寫並運行C++測試程序
例如,我們可以創建一個測試程序./test/hello-test.cc:
#include "gtest/gtest.h"
#include "lib/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",
"//lib:hello-greet",
],
)
注意:爲了使hello-greet對於hello-test可見,必須在./lib/BUILD添加"//test:__pkg__"可見屬性。
現在可以用Bazel test運行測試了。