Отдельные действия компиляции и компоновки с помощью Bazel

Я хотел бы знать, есть ли способ выполнить компиляцию и связывание действий с Bazel отдельными шагами. Если я выполню команду

bazel build -s //main:hello-world

печатаются все ПОДКОМАНДЫ bazel. Я знаю, что эти подкоманды можно выполнить из командной строки, но я хотел бы знать, как использовать Bazel для выполнения, например, только действия компиляции и только действия связывания в отдельных шагах. Спасибо заранее за любую помощь!

В моем случае я хотел бы разобрать (некоторые) объектные файлы для анализа. Запустите их через проход objcopy. Запрос через aquery. Жаль, кажется, что все скрыто.

Andreas 21.10.2021 21:32

Можете ли вы использовать genrule() для дизассемблирования, которое принимает в качестве входных данных выходные объектные файлы правила компиляции (just_compile), описанного ниже?

Fed 27.10.2021 16:18

Моя текущая идея состоит в том, чтобы иметь правило, извлекающее объектные файлы из библиотек (ar x), а затем иметь правила с этими объектными файлами в качестве входных данных.

Andreas 27.10.2021 16:40
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
3
923
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Я думаю, что невозможно выполнить компиляцию и компоновку в два отдельных шага с помощью Bazel с rules_cc по умолчанию.

Самое близкое, что вы можете получить.

Существует опция --nobuild, которая останавливает сборку перед выполнением действий по сборке (например, компиляция, компоновка и т. д.).

Вы можете использовать aquery для запроса действий в графе сборки.

Это даст вам ту же информацию, что и -s, но без фактического вызова команд.

Другой подход может заключаться в том, чтобы придумать собственные правила, например.

cc_binary_compilation(
    name = "...",
    srcs = [...]
)

cc_binary_linking(...)

Здравствуйте, спасибо за ответ. Знаете ли вы, можно ли также выполнить компиляцию и компоновку в два отдельных этапа через Bazel? На данный момент единственный способ сделать это — повторно выполнить ПОДКОМАНДЫ из командной строки, но для этого не требуется использовать Bazel.

Fed 18.12.2020 17:54

Или, в качестве альтернативы, также может быть полезен способ выполнения подкоманд одну за другой из командной строки после выполнения сборки Bazel с параметром --nobuild. На данный момент я могу повторно выполнить команды только после успешной и полной сборки, но не выполнять их одну за другой после выполнения --nobuild. Я получаю сообщение об ошибке «env: bazel/toolchains/mingw: нет такого файла или каталога», даже если этот каталог присутствует в моем рабочем пространстве.

Fed 18.12.2020 18:06

Я думаю, что невозможно выполнить компиляцию и компоновку в два отдельных шага с помощью Bazel с rules_cc по умолчанию.

Vertexwahn 18.12.2020 23:00

Я вижу, в конце концов мне пришлось использовать реализацию собственных правил, и это сработало. Танков много за вашу помощь :)

Fed 19.12.2020 11:56
Ответ принят как подходящий

Не уверен, что именно вам нужно, но, по сути, вы можете написать собственное правило, которое вы передаете cc_* target в качестве источника, и пытаетесь отделить его действия, получая только те результаты, которые вас интересуют, например:

def _impl(ctx):
    outs = []
    for src in ctx.attr.srcs:
        if hasattr(src, "actions"):
            for action in src.actions:
                if action.mnemonic == "CppCompile":
                    outs.append(action.outputs)
    return DefaultInfo(files = depset(transitive = outs))

just_compile = rule(
    _impl,
    attrs = {
        "srcs": attr.label_list(mandatory = True),
    },

)      

Если у меня есть следующий файл BUILD:

load("//:just_compile.bzl", "just_compile")

just_compile(
    name = "compile_hello",
    srcs = [":hello"],
)

cc_binary(
    name = "hello",
    srcs = ["hello.cpp"],
)

И вы бежите (можно добавить -s, чтобы смотреть):

bazel build compile_hello

Вы получите только выполненный шаг компиляции (поскольку мы на самом деле не запрашивали цель hello и нет ничего, что требовалось бы связывать в дереве, как запрошено) и полученные результаты:

bazel-bin/
bazel-bin/_objs
bazel-bin/_objs/hello
bazel-bin/_objs/hello/hello.pic.d
bazel-bin/_objs/hello/hello.pic.o

Связывающая мнемоника CppLink.

Так что да, вы можете привязаться к конкретным действиям. И ради обсуждения, это был бы по крайней мере один вариант, который я знаю, чтобы сделать это. Но опять же, я не совсем уверен, что именно вы на самом деле ищете, какую проблему вы пытаетесь решить.

Вы можете легко выполнить компиляцию с помощью пользовательского правила . Вам нужно будет использовать API-интерфейсы cc_common , чтобы делать обычные вещи, которые делает cc_library, но возвращая все файлы в поставщике DefaultInfo.files.

Для ссылки я бы просто использовал cc_binary. Вы также можете сделать что-то подобное с пользовательским правилом, чтобы разделить части, если хотите.

Что-то вроде этого:

load("@rules_cc//cc:action_names.bzl", "C_COMPILE_ACTION_NAME")
load("@rules_cc//cc:toolchain_utils.bzl", "find_cpp_toolchain")

def _my_c_compile_impl(ctx):
    cc_toolchain = find_cpp_toolchain(ctx)
    source_file = ctx.file.src
    output_file = ctx.actions.declare_file(ctx.label.name + ".o")
    feature_configuration = cc_common.configure_features(
        ctx = ctx,
        cc_toolchain = cc_toolchain,
        requested_features = ctx.features,
        unsupported_features = DISABLED_FEATURES + ctx.disabled_features,
    )
    _, outputs = cc_common.compile(
        actions = ctx.actions,
        cc_toolchain = cc_toolchain,
        srcs = [source_file],
        name = ctx.label.name,
    )
    return [
        DefaultInfo(files = depset(direct = outputs.objects)),
    ]

my_c_compile = rule(
    implementation = _my_c_compile_impl,
    attrs = {
        "src": attr.label(mandatory = True, allow_single_file = True),
        "_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")),
    },
    toolchains = ["@bazel_tools//tools/cpp:toolchain_type"],
    incompatible_use_toolchain_transition = True,
    fragments = ["cpp"],
)

Пример rules_cc my_c_archive — хорошая отправная точка, если вы хотите настроить вещи больше, чем позволяет cc_common.compile.

Если вы хотите сделать это общим инструментом отладки, вы можете упаковать аналогичную логику в виде аспекта, чтобы применить ее к произвольным правилам.

Для быстрой отладки --save_temps — еще одна техника.

Вы можете указать получать только определенную группу выходных данных. Итак, чтобы посмотреть, какие группы вывода используются:

bazel cquery //my_target --output=starlark --starlark:expr = "[str(og) for og in target.output_groups]"

Затем, чтобы построить только эту группу вывода, она предназначена только для компиляции С++ (без ссылки):

bazel build //my_target --output_groups=compilation_outputs

Хитрость заключается в том, чтобы не использовать + или - в output_groups, это изменяет группу вывода по умолчанию.

Другие вопросы по теме