Базель: genrule, который выводит каталог
Я только начинаю работать с Базелем. Поэтому я заранее прошу прощения за то, что не смог понять это.
Я пытаюсь запустить команду, которая выводит кучу файлов в каталог и делает этот каталог доступным для последующих целей. У меня есть две разные попытки:
- Используйте genrule
- Напишите мое собственное правило
Я наивно надеялся просто сделать это с genrule
, Но, кажется, вы не можете сказать "Я не знаю точно, что эта команда будет выводить" и поместить каталог в outs
, Сейчас я пытаюсь написать правило, которое может использовать ctx.actions.declare_directory
но я не совсем понял Я не могу получить tools
из моего рабочего пространства и в мое правило.
Моя попытка жанру выглядит примерно так:
genrule(
name = "doit",
srcs = [
"doitConfigA",
"doitConfigB",
],
cmd = 'HOME=. ./$(location path/to/doit) install',
# Neither of the below outs work - seems like bazel wants to know
# exactly this list of files. I don't know the files that
# will be output ahead of time.
# This one looks at the `out_dir` that I already have and
# expects the files to be the same which they might not be
outs = glob(["out_dir/**/*.*"]),
# this fails with:
# "declared output 'out_dir' was not
# created by genrule. This is probably because the genrule actually
# didn't create this output, or because the output was a directory
# and the genrule was run remotely (note that only the contents of
# declared file outputs are copied from genrules run remotely)"
outs = ['out_dir'],
tools = ['path/to/doit'],
)
Моя попытка создания пользовательского правила выглядит примерно так:
def _impl(ctx):
dir = ctx.actions.declare_directory("out_dir")
ctx.actions.run_shell(
outputs=[dir],
progress_message="Running doit install ...",
command="HOME=. ./path/to/doit install",
tools=[ctx.attr.tools],
)
doit = rule(
implementation=_impl,
attrs={
"tools": attr.label_list(allow_files=True),
},
outputs={"out": "out_dir"},
)
Затем, чтобы запустить мой doit
правило, мой файл BUILD выглядит так:
doit(
name = 'doit',
tools = ['path/to/doit'],
)
В моем жанре команда запускается, но мне не нравится, когда я пытаюсь использовать каталог в outs
, похоже на то. В моем собственном правиле я не могу сказать Bazel, что я хочу использовать ./path/to/doit
как инструмент из моей рабочей области, например expected type 'File' for 'tools' element but got type 'list' instead
...
Похоже, я, должно быть, упускаю что-то простое, потому что, конечно, это обычная ситуация, когда нужно запустить команду и вывести кучу неизвестных вещей в каталог?
3 ответа
Выход genrule
должен быть фиксированный список файлов. В качестве временного решения вы можете создать zip-архив из выходного каталога.
Я использовал этот подход, чтобы управлять выводом yarn install
где обычный метод оказался нежизнеспособным:
genrule(
name = "node_modules",
srcs = [
"package.json",
"yarn.lock",
],
cmd = " && ".join([
"yarn install --pure-lockfile",
"zip -r $@ node_modules",
]),
outs = [
"node_modules.zip",
],
)
Затем правило, потребляющее zip:
# Rule that generates a list of the folders in node_modules
genrule(
name = "node_modules_ls",
srcs = [
":node_modules",
],
cmd = " && ".join([
"unzip $(location :node_modules) -d . ",
"ls > $@",
]),
outs = [
"out.txt",
],
)
Некоторое время назад я создал этот пример, показывающий, как использовать каталоги с действием skylark: Как создать статическую библиотеку из Сгенерированных исходных файлов, используя Bazel Build. Возможно, это все еще работает:)
Genrule не будет работать, это слишком сложный вариант использования.
https://github.com/aspect-build/bazel-lib/blob/main/docs/run_binary.md имеет API, аналогичный genrule, и поддерживает вывод каталогов.