Как я могу получить свое пользовательское правило шаблона заголовка, чтобы передать его выходные данные по нисходящей зависимости cc_binary / cc_library? - PullRequest
0 голосов
/ 29 марта 2019

Я пытаюсь создать правило для 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(){
}

Ответы [ 2 ]

1 голос
/ 29 марта 2019

Ответ выглядит так:

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(

                # pass out the include path for finding this header
                includes=depset([ctx.outputs.out.dirname]),

                # and the actual header here.
                headers=depset([ctx.outputs.out])
            ))
        ]

в другом месте:

header_template(
    name = "some_header",
    extension = ".hpp",
    template = "some_header.hpp.in",
    vars = {
        "@SOMEVAR@": "value",
        "{ANOTHERVAR}": "another_value",
    },
)

cc_library(
   name = "foo",
   srcs = ["foo.cpp"],
   deps = [":some_header"],
   ...
)

cc_binary(
   name = "bar",
   srcs = ["bar.cpp"],
   deps = [":foo"],
)
0 голосов
/ 29 марта 2019

Если ваш заголовок имеет общее имя (например, config.h), и вы хотите, чтобы оно было частным (то есть srcs вместо hdrs), вам может потребоваться другой подход. Я видел эту проблему для gflags, которые «просочились» в config.h и затронули зависящие от него библиотеки ( issue ).

Конечно, в обоих случаях самое простое решение - генерировать и фиксировать заголовочные файлы для платформ, на которые вы ориентируетесь.

В качестве альтернативы вы можете установить copts для правила cc_library, которое использует сгенерированный закрытый заголовок:

cc_library(
   name = "foo",
   srcs = ["foo.cpp", "some_header.hpp"],
   copts = ["-I$(GENDIR)/my/package/name"],
   ...
)

Если вы хотите, чтобы это работало, когда ваш репозиторий включен в качестве внешнего репозитория, у вас есть немного больше работы для вас из-за проблемы bazel # 4463 .

PS. Возможно, вы захотите узнать, подходит ли вам cc_fix_config из https://github.com/antonovvk/bazel_rules. Это просто оболочка для perl, но я нашел это полезным.

...