Я пытаюсь создать правило для bazel, которое эмулирует систему шаблонов CMake * .in.
Это имеет две проблемы, первая - генерировать выходные данные шаблона. Второй - сделать вывод доступным для правил genrules
, filegroups
и cc_*
. Третий - сделать так, чтобы эту зависимость транзитивно передавали в последующие правила.
Он генерирует выходной файл version.hpp
в genfiles (или bazel-bin), и я могу получить исходное библиотечное правило, чтобы включить его, но я не могу понять, как сделать мое правило cc_binary, который зависит от cc_library и транзитивно правила header_template для поиска файла заголовка.
У меня есть следующее правило .bzl:
def _header_template_impl(ctx):
# this generates the output from the template
ctx.actions.expand_template(
template = ctx.file.template,
output = ctx.outputs.out,
substitutions = ctx.attr.vars,
)
return [
# create a provider which says that this
# out file should be made available as a header
CcInfo(compilation_context=cc_common.create_compilation_context(
headers=depset([ctx.outputs.out])
)),
# Also create a provider referencing this header ???
DefaultInfo(files=depset(
[ctx.outputs.out]
))
]
header_template = rule(
implementation = _header_template_impl,
attrs = {
"vars": attr.string_dict(
mandatory = True
),
"extension": attr.string(default=".hpp"),
"template": attr.label(
mandatory = True,
allow_single_file = True,
),
},
outputs = {
"out": "%{name}%{extension}",
},
output_to_genfiles = True,
)
в другом месте у меня есть правило cc_library:
load("//:tools/header_template.bzl", "header_template")
# version control
BONSAI_MAJOR_VERSION = '2'
BONSAI_MINOR_VERSION = '0'
BONSAI_PATCH_VERSION = '9'
BONSAI_VERSION = \
BONSAI_MAJOR_VERSION + '.' + \
BONSAI_MINOR_VERSION + '.' + \
BONSAI_PATCH_VERSION
header_template(
name = "bonsai_version",
extension = ".hpp",
template = "version.hpp.in",
vars = {
"@BONSAI_MAJOR_VERSION@": BONSAI_MAJOR_VERSION,
"@BONSAI_MINOR_VERSION@": BONSAI_MINOR_VERSION,
"@BONSAI_PATCH_VERSION@": BONSAI_PATCH_VERSION,
"@BONSAI_VERSION@": BONSAI_VERSION,
},
)
# ...
private = glob([
"src/**/*.hpp",
"src/**/*.cpp",
"proto/**/*.hpp",
])
public = glob([
"include/*.hpp",
":bonsai_version",
])
cc_library(
# target name matches directory name so you can call:
# bazel build .
name = "bonsai",
srcs = private,
hdrs = public,
# public headers
includes = [
"include",
],
# ...
deps = [
":bonsai_version",
# ...
],
# ...
)
Когда я собираю, мои исходные файлы должны иметь возможность:
#include "bonsai_version.hpp"
Я думаю, что ответ включает CcInfo
, но я понимаю в темноте, как это должно быть построено.
Я уже пытался добавить "-I$(GENDIR)/" + package_name()
к коптам, но безрезультатно. Сгенерированный заголовок по-прежнему недоступен.
Я ожидаю, что я смогу вернуть какой-то объект Info, который позволил бы мне добавить зависимость в srcs
. Может быть, это должно быть DefaultInfo
.
Я просмотрел примеры правил Базеля и источник, но мне не хватает чего-то фундаментального, и я не могу найти документацию, которая обсуждает этот конкретный вопрос.
Я бы хотел сделать следующее:
header_template(
name = "some_header",
extension = ".hpp",
template = "some_header.hpp.in",
vars = {
"@SOMEVAR@": "value",
"{ANOTHERVAR}": "another_value",
},
)
cc_library(
name = "foo",
srcs = ["foo.src", ":some_header"],
...
)
cc_binary(
name = "bar",
srcs = ["bar.cpp"],
deps = [":foo"],
)
и включите сгенерированный заголовок так:
#include "some_header.hpp"
void bar(){
}