glob模式
glob模式也被常稱之為shell通配符,是一種特殊的模式匹配,通常用于匹配目錄以及文件,而非文本。
# 匹配任意長度任意字符
*
# 匹配任意單個字符
?
# 匹配指定范圍內的單個字符
[list]
# 匹配指定范圍外的單個字符
[^list] [!list] 匹配指定范圍外的任意單個字符或字符集合
# 匹配str1或者集合
{str1,[list]}
# 遞歸的任意目錄
**
glob函數
def glob(include, exclude=[], exclude_directories=1, allow_empty=True)
Bazel中的glob函數是對glob模式匹配實現的簡化版,它在當前包中(不包括子包)匹配所有文件列表。一般地,文件路徑由/
分割為多個路徑段組成;其中,*
匹配路徑段中的零個或多個任意字符,**
匹配任意的路徑段。
目前,Bazel實現的glob函數依舊不夠完善,它僅支持*
和**
的模式匹配,而不支持?
,字符集合,及其大括號等模式。
只能匹配源文件,而不匹配派生文件
java_library(
name = "mylib",
srcs = glob(["*.java"]) + [":gen_java_srcs"],
)
genrule(
name = "gen_java_srcs",
outs = [
"Foo.java",
"Bar.java",
],
}
排除法
在當前包中,匹配testdata
目錄下所有擴展名為txt
的文本文件列表,但排除testdata/experimental.txt
文件。注意,該規則不匹配testdata
子目錄中的文件列表。
sh_test(
name = "mytest",
srcs = ["mytest.sh"],
data = glob(
["testdata/*.txt"],
exclude = ["testdata/experimental.txt"],
),
)
遞歸
在當前包中,匹配testdata
目錄及子目錄中擴展名為txt
的文本文件列表。
sh_test(
name = "mytest",
srcs = ["mytest.sh"],
data = glob(["testdata/**/*.txt"]),
)
如果要匹配當前目錄,及其所有子目錄,則以**
開頭。例如,當前目錄及其子目錄下所有java
文件,當排除路徑名中包括testing
的文件列表。
java_library(
name = "mylib",
srcs = glob(
["**/*.java"],
exclude = ["**/testing/**"],
),
)
動態規則
如下代碼,可動態生成統計測試文件代碼行的規則列表。
# Conveniently, the build language supports list comprehensions.
[genrule(
name = "count_lines_" + f[:-3], # strip ".cc"
srcs = [f],
outs = ["%s-linecount.txt" % f[:-3]],
cmd = "wc -l $< >$@",
) for f in glob(["*_test.cc"])]
此時,通過bazel query
可查詢出動態生成的規則列表。此處,//foo:all
表示foo
包下的所有規則,不包括文件。
$ bazel query '//foo:all' | sort
//foo:count_lines_a_test
//foo:count_lines_b_test
//foo:count_lines_c_test
可構建任意目標。執行如下命令,將統計a_test.cc
文件的代碼行,并將結果重定向至a_test-linecount.txt
之中。
$ bazel build //foo:count_lines_a_test
查看結果,顯示22行。
$ cat bazel-bin/foo/a_test-linecount.txt
22 foo/a_test.cc
Bazel的動態性,再加持Shell
,可擴展的空間特別大,且語法是類Python的,相對Makefile非常易讀。CMake在可擴展性和可讀性,Bazel技高一籌。