Я хотел бы знать, есть ли способ выполнить компиляцию и связывание действий с Bazel отдельными шагами. Если я выполню команду
bazel build -s //main:hello-world
печатаются все ПОДКОМАНДЫ bazel. Я знаю, что эти подкоманды можно выполнить из командной строки, но я хотел бы знать, как использовать Bazel для выполнения, например, только действия компиляции и только действия связывания в отдельных шагах. Спасибо заранее за любую помощь!
Можете ли вы использовать genrule() для дизассемблирования, которое принимает в качестве входных данных выходные объектные файлы правила компиляции (just_compile), описанного ниже?
Моя текущая идея состоит в том, чтобы иметь правило, извлекающее объектные файлы из библиотек (ar x
), а затем иметь правила с этими объектными файлами в качестве входных данных.
Я думаю, что невозможно выполнить компиляцию и компоновку в два отдельных шага с помощью Bazel с rules_cc по умолчанию.
Самое близкое, что вы можете получить.
Существует опция --nobuild
, которая останавливает сборку перед выполнением действий по сборке (например, компиляция, компоновка и т. д.).
Вы можете использовать aquery
для запроса действий в графе сборки.
Это даст вам ту же информацию, что и -s
, но без фактического вызова команд.
Другой подход может заключаться в том, чтобы придумать собственные правила, например.
cc_binary_compilation(
name = "...",
srcs = [...]
)
cc_binary_linking(...)
Здравствуйте, спасибо за ответ. Знаете ли вы, можно ли также выполнить компиляцию и компоновку в два отдельных этапа через Bazel? На данный момент единственный способ сделать это — повторно выполнить ПОДКОМАНДЫ из командной строки, но для этого не требуется использовать Bazel.
Или, в качестве альтернативы, также может быть полезен способ выполнения подкоманд одну за другой из командной строки после выполнения сборки Bazel с параметром --nobuild. На данный момент я могу повторно выполнить команды только после успешной и полной сборки, но не выполнять их одну за другой после выполнения --nobuild. Я получаю сообщение об ошибке «env: bazel/toolchains/mingw: нет такого файла или каталога», даже если этот каталог присутствует в моем рабочем пространстве.
Я думаю, что невозможно выполнить компиляцию и компоновку в два отдельных шага с помощью Bazel с rules_cc по умолчанию.
Я вижу, в конце концов мне пришлось использовать реализацию собственных правил, и это сработало. Танков много за вашу помощь :)
Не уверен, что именно вам нужно, но, по сути, вы можете написать собственное правило, которое вы передаете 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
, это изменяет группу вывода по умолчанию.
В моем случае я хотел бы разобрать (некоторые) объектные файлы для анализа. Запустите их через проход objcopy. Запрос через aquery. Жаль, кажется, что все скрыто.