Bazel 调度C++;将生成的文件转换为SRC和HDR

Bazel 调度C++;将生成的文件转换为SRC和HDR,bazel,Bazel,在Bazel官方文档中,有一个解释如何创建一个Java库,该库由常规Java文件和由:gen_Java_srcs规则生成的文件构建。为了便于阅读,我在此处重写了此代码: java_library( name = "mylib", srcs = glob(["*.java"]) + [":gen_java_srcs"], deps = "...", ) genrule( name = "gen_java_srcs", outs = [ "F

在Bazel官方文档中,有一个解释如何创建一个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++的视角下,我的场景是GEnGrand生成两种文件:.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_库规则,将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了解不够,无法将其实现。

根据genrule的名称(
:gen_cpp_srcs
)将为您提供genrule的所有输出,如您所述。相反,您可以依赖genrule的单独输出(例如,
hdrs=[:myFile.hpp]
srcs=[:myFile.cpp]


另请参见的答案。

看起来您知道应该生成的文件总数。你能把它们放在各自的变量中,然后在两个目标中重用它们吗。在生成文件中类似于以下内容:

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
)

glob只有在被传递到规则中时才会被扩展,所以您需要编写一个简单的。我想这样打包(在一个名为
filter.bzl
的文件中):

这就是我的演示
BUILD
文件的样子(我更改了globs,使它们都包含*.cpp和*.hpp文件;使用genrule的标签将以相同的方式工作):


通过更改
\u do\u filter\u impl
,这很容易扩展到更复杂的过滤。特别是,将
后缀
更改为,这样您就可以接受多个C/C++源代码/标题扩展,这似乎是个好主意。

阅读您的答案后,我才意识到我的问题没有得到清楚的解释。我重新编辑了我的问题,使它更容易理解。总之,我想知道如何将一个规则输出过滤成另一个规则输入,只选择某些类型的文件多谢,你的代码对我学习如何为我的东西扩展Bazel非常有价值(我认为官方文档缺少一些关于Skylark语言的示例/解释),我刚刚看到
returnstruct(…)
已被弃用。我用
return[DefaultInfo(files=…)]
修改了您的代码。不幸的是,我没有关于大小的信息,这就是我希望以编程方式执行此操作的原因。无论如何,谢谢你:我喜欢你的genrule(),这是一个生成假输出的好技巧。
# 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
  )
load("//:filter.bzl", "filtered_cc_library")

filtered_cc_library(
    name = "mylib",
    srcs = glob(["*.*pp"]),
    hdrs = glob(["*.*pp"]),
)