我一直在使用 BCR 中的 https://github.com/TendTo/rules_doxygen/tree/main 来生成文档。我正在尝试弄清楚如何让 bazel 遍历目标的依赖关系图,以便我可以提取所有标头的列表以提供给 doxygen 作为文档。 到目前为止,只有当我在一个 glob 中指定所有内容时,我才能让 doxygen 工作 - 但这种情况假设所有内容都位于一个地方。 我想要这样的东西:
cc_binary MAIN - main.cpp
|
cc_library A - A.cpp, A.hpp
|
cc_library B - B.cpp, B.hpp
|
cc_library C - C.cpp, C.hpp
现在 - 像这样的东西有效:
doxygen(
name = "doxygen", # Name of the rule, can be anything
srcs = glob(["A/*.hpp", "B/*.hpp", "C/*.hpp"]),
project_brief = "Example project for doxygen", # Brief description of the project
project_name = "base", # Name of the project
configurations = [ # Additional configurations to add to the Doxyfile
"GENERATE_HTML = YES", # They are the same as the Doxyfile options,
"GENERATE_LATEX = NO", # and will override the default values
"EXTRACT_ALL = YES",
],
tags = ["manual"] # Tags to add to the target. This way the target won't run unless explicitly called
)
但是我应该能够将其包装起来,这样我就可以做类似的事情:
my_doxygen(
name = "my_cool_docs",
deps = [":main"] ( or maybe in a docs folder "//:main" )
)
bazel build //:my_cool_docs or bazel build //docs:my_cool_docs
让它遍历 main 的 deps,保留文件列表,然后在后台提供给 doxygen。
到目前为止,我已经弄清楚如何使用方面在 BUILD 文件内的所有 cc_library 和 cc_binary 文件上进行此操作:
load("//:cc_srcs.bzl", "CcSrcs", "cc_srcs_aspect")
def _gather_src_files_impl(ctx):
srcs = []
hdrs = []
for dep in ctx.attr.deps:
srcs.extend(dep[CcSrcs].srcs.to_list())
hdrs.extend(dep[CcInfo].compilation_context.direct_headers)
hdrs = [h for h in hdrs if h.is_source]
src_list = srcs + hdrs
info = [DefaultInfo(files=depset(src_list))]
return info
_gather_src_files = rule(
implementation = _gather_src_files_impl,
fragments = ["cpp"],
attrs = {
"deps": attr.label_list(providers = [CcInfo], aspects = [cc_srcs_aspect]),
},
toolchains = ["@bazel_tools//tools/cpp:toolchain_type"],
)
def gather_src_files(name = "gather_src_files"):
rule_types = [rule["kind"] for rule in native.existing_rules().values()]
if "_gather_src_files" in rule_types:
fail("rule already defined")
deps = []
for rule_name, rule in native.existing_rules().items():
print(rule_name + ":" + rule["kind"])
if rule["kind"] in ["cc_binary", "cc_library"]:
deps.append(rule_name)
_gather_src_files(
name = name,
deps = deps
)
cc_srcs.bazel
CcSrcs = provider(
fields = {
"srcs": "depset of top-level cpp sources",
"package": "the package root",
},
)
def extract_cc_files(target, ctx):
srcs_target_list = getattr(ctx.rule.attr, "srcs", [])
srcs_file_list = [f for t in srcs_target_list for f in t.files.to_list()]
return srcs_file_list
def extract_cc_srcs(target, ctx):
return [s for s in extract_cc_files(target, ctx) if s.extension in ["c", "cc", "cpp", "cxx", "c++", "C"]]
def _cc_srcs_aspect_impl(target, ctx):
srcs = []
if CcInfo in target: srcs = extract_cc_srcs(target, ctx)
# Get the root name: either ws root for external repos, or package for internal repos
root_name = ctx.label.workspace_root
if not root_name: root_name = ctx.label.package
return [CcSrcs(
srcs = depset(srcs, order = "topological"),
package = depset([root_name]),
)]
cc_srcs_aspect = aspect(
implementation = _cc_srcs_aspect_impl,
)
但是我无法弄清楚如何访问/遍历给定目标的依赖关系图 - 而且我什至不确定此时要在 Bazel 文档中查找哪些术语。
有什么想法吗? 谢谢!
仔细查看示例后 - 我发现我需要做的就是添加:
FileCountInfo = provider(
fields = {
'count' : 'number of files',
'srcs' : 'depset of files' <-----
}
)
def _file_count_aspect_impl(target, ctx):
count = 0
srcs = []
# Make sure the rule has a srcs attribute.
print("Fudge")
if hasattr(ctx.rule.attr, 'srcs'):
# Iterate through the sources counting files
for src in ctx.rule.attr.srcs:
for f in src.files.to_list():
if ctx.attr.extension == '*' or ctx.attr.extension == f.extension:
count = count + 1
srcs.append(f) <-----------
# Get the counts from our dependencies.
for dep in ctx.rule.attr.deps:
count = count + dep[FileCountInfo].count
a = dep[FileCountInfo].srcs
srcs.extend(dep[FileCountInfo].srcs.to_list()) <----------
return [FileCountInfo(count = count, srcs=depset(srcs))] <--------
enter code here
在这和我已经拥有的之间 - 我认为我有一个稍微更坚实的基础。
这是一个过程,我认为 Bazel 还没有遇到尚未通过另一层间接解决的问题。