Наличие двух зависимых действий в одном правиле

#bazel #bazel-rules

#bazel #bazel-правила

Вопрос:

Редактировать: приведенный ниже пример действительно сработал, я неверно истолковал вывод, который дал мне компилятор. Ответ все еще может быть полезен для некоторых.

Есть ли способ для действия в правиле сгенерировать файл, который используется более поздним действием в том же правиле?

Например.:

 def _example_rule_impl(ctx):
  thefile = ctx.actions.declare_file("required_file.json")

  ctx.actions.write(
    output = thefile,
    content = "CONTENT",
  )

  args = ctx.actions.args()
  args.add("--config", thefile)

  ctx.actions.run(
    inputs = ctx.files.srcs   ctx.files.deps   [thefile],
    outputs = outs,
    arguments = [args],
    progress_message = "Compiling...",
    executable = ctx.executable._compiler,
  )
 

Основная проблема с этим, по-видимому, заключается в том, что все выходные данные действия, похоже, записываются в bazel-out, но для выполнения действия требуется, чтобы сгенерированный файл был записан рядом с файлами srcs и deps в execroot, чтобы он работал. Есть ли способ записать действие в execroot или это неправильный подход?

Ответ №1:

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

См. https://docs.bazel.build/versions/main/output_directories.html

Кроме того, относительно этой строки:

 inputs = ctx.files.srcs   ctx.files.deps   [thefile],
 

В зависимости от того, что вам нужно сделать, вы можете захотеть использовать depsets по соображениям производительности. См.
https://docs.bazel.build/versions/main/skylark/depsets.html и, в частности, в конце https://docs.bazel.build/versions/main/skylark/depsets.html#performance

Комментарии:

1. Спасибо! Оказалось, что это работало все время, и я просто неверно истолковал ошибку, которую выдал мне компилятор. Что касается depsets: я использовал один, но избавился от него, пытаясь найти проблему. Однако я не уверен, правильно ли я его использовал. Я бы просто поместил все файлы в один файл? входные данные = depset(ctx.files.srcs ctx.files.deps [thefile])? Или мне создать depset для каждого из них и добавить их к транзитивным зависимостям друг друга?

2. Это зависит от того, как структурированы ваши правила. Depsets в основном предназначены для предотвращения квадратичного использования памяти / конкатенации в структурах данных между целями. Например, foo(name=»a», deps= [«b»]) foo(name=»b», deps = [«c»]) foo(name= «c», deps = [«d»]) без depsets может привести к [a, b, c, d], [b, c, d], [c, d], [d], если foo использует списки. Однако, если вы не объединяете подобные элементы по «слоям» графика построения, для inputs этого вам не обязательно нужны depsets.