在Bazel官方文档中,有一个example解释了如何创建一个由常规java文件构建的Java库和由gen_java_srcs规则生成的文件。为了便于阅读,我在这里重写了这段代码:
java_library(
name = "mylib",
srcs = glob(["*.java"]) + [":gen_java_srcs"],
deps = "...",
)
genrule(
name = "gen_java_srcs",
outs = [
"Foo.java",
"Bar.java",
],
...
)
现在从C ++的角度来看,我处于genrule生成两种文件的场景:.hpp和.cpp:
genrule(
name = "gen_cpp_srcs",
outs = [
"myFile_1.hpp","myFile_2.hpp",...,"myFile_N.hpp",
"myFile.cpp","myFile_2.cpp",...,"myFile_N.cpp",
],
...
)
其中N是几十。
我的问题/问题是:如何编写cc_library规则,自动将hpp和cpp文件分派到hdrs和srcs字段?
我想要类似的东西:
cc_library(
name = "mylib",
srcs = glob(["*.cpp"]) + (howto: .cpp files of [":gen_cpp_srcs"]),
hdrs = glob(["*.hpp"]) + (howto: .hpp files of [":gen_cpp_srcs"]),
...
)
有些神奇:
output_filter(":gen_cpp_srcs","*.cpp")
会很完美,但我不太了解Bazel让它真实。
答案 0 :(得分:3)
Globs只有在传入规则时才会得到扩展,因此您需要编写一个简单的rule。我会像这样打包它(在一个名为filter.bzl
的文件中):
# The actual rule which does the filtering.
def _do_filter_impl(ctx):
return struct(
files = set([f for f in ctx.files.srcs if f.path.endswith(ctx.attr.suffix)]),
)
_do_filter = rule(
implementation = _do_filter_impl,
attrs = {
"srcs": attr.label_list(
mandatory = True,
allow_files = True,
),
"suffix": attr.string(
mandatory = True,
),
},
)
# A convenient macro to wrap the custom rule and cc_library.
def filtered_cc_library(name, srcs, hdrs, **kwargs):
_do_filter(
name = "%s_hdrs" % name,
visibility = ["//visibility:private"],
srcs = hdrs,
suffix = ".hpp",
)
_do_filter(
name = "%s_srcs" % name,
visibility = ["//visibility:private"],
srcs = srcs,
suffix = ".cpp",
)
native.cc_library(
name = name,
srcs = [ ":%s_srcs" % name ],
hdrs = [ ":%s_hdrs" % name ],
**kwargs
)
这就是我的demo BUILD
文件的样子(我更改了globs,因此它们都包含* .cpp和* .hpp文件;使用genrule的标签将以相同的方式工作):
load("//:filter.bzl", "filtered_cc_library")
filtered_cc_library(
name = "mylib",
srcs = glob(["*.*pp"]),
hdrs = glob(["*.*pp"]),
)
通过更改_do_filter_impl
,可以轻松扩展到更复杂的过滤。特别是,将suffix
更改为attr.string_list以便您可以接受多个C / C ++源/标头扩展,这似乎是一个好主意。
答案 1 :(得分:2)
Depending on the genrule by name (:gen_cpp_srcs
) will give you all of the outputs of the genrule, as you have noted. Instead, you can depend on the individual outputs of the genrule (e.g. hdrs = [:myFile.hpp]
and srcs = [:myFile.cpp]
).
See also the answer to Bazel & automatically generated cpp / hpp files.
答案 2 :(得分:2)
看起来您知道应该生成的文件总数。你能把它们放在自己的变量中,然后在两个目标中重复使用它们。您的BUILD文件中有类似的内容:
output_cpp_files = [
"myFile_1.cpp",
"myFile_2.cpp",
"myFile_3.cpp"
]
output_hpp_files = [
"myFile_1.hpp",
"myFile_2.hpp",
"myFile_3.hpp"
]
genrule(
name = "gen_cpp_srcs",
outs = output_cpp_files + output_hpp_files,
cmd = """
touch $(OUTS)
"""
)
cc_library(
name = "mylib",
srcs = output_cpp_files,
hdrs = output_hpp_files
)