Базель: genrule, который выводит каталог

Я только начинаю работать с Базелем. Поэтому я заранее прошу прощения за то, что не смог понять это.

Я пытаюсь запустить команду, которая выводит кучу файлов в каталог и делает этот каталог доступным для последующих целей. У меня есть две разные попытки:

  1. Используйте genrule
  2. Напишите мое собственное правило

Я наивно надеялся просто сделать это с 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, и поддерживает вывод каталогов.

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