Bazel Build:Glob模式匹配

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技高一筹。

你可能感兴趣的:(Bazel Build:Glob模式匹配)