Двойное создание макроса Bazel с одним и тем же сгенерированным выходным файлом

Предположим, у меня есть макрос Bazel, который использует правило генератора для создания выходного файла на основе входного файла:

      def my_generator(
        name,
        input_file,
        output_file,
        **kwargs):
    args = []
    args.extend(["--arg1", "$(location %s)" % output_file])
    args.extend(["arg2", "$(locations %s)" % input_file])

    cmd_params = " ".join(args)

    native.genrule(
        name = name,
        srcs = [input_file],
        outs = [output_file],
        cmd = "python $(location //path/to:target_generator) %s" % cmd_params,
        tools = ["/path/to/tool:mytool"],
    )

Затем я ранее использовал этот макрос как:

      my_generator(
    name = "gen1",
    input_file = ":targetToGeneratetextFile",
    output_file = "outputfile.txt",
    visibility = ["//myproject/oath/to/current/package/test:__subpackages__"],
)

где цель передается какinput_file. Это работало.

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

      my_generator(
    name = "gen2",
    input_file = "//path/to/the/file/realFile.txt",
    output_file = "outputfile.txt",
    visibility = ["//myproject/oath/to/current/package/test:__subpackages__"],
)

Я получаю две ошибки таким образом:

  1. Как это, Базель не может найтиrealFile.txt: он пытается прочитать его как цель:

нет такого пакета '//path/to/the/file/realFile.txt': файл BUILD не найден ни в одном из следующих каталогов. Добавьте файл BUILD в каталог, чтобы пометить его как пакет.

Если я скопирую файл в текущую папку пакета, он сможет его прочитать.

  1. Bazel жалуется на это и записывает/перезаписывает один и тот же выходной файлoutputfile.txt:

Ошибка в genrule: сгенерированный файл «outputfile.txt» в правиле «gen2» конфликтует с существующим сгенерированным файлом из правила «gen1», определенного в ...

Как я могу решить эти проблемы?

Я думаю, что проблема в том, что эти два вызова выполняются оба, тогда как я хотел бы, чтобы они выполнялись в зависимости от некоторой цели, т.е. цели A нужно только запуститьgen1и цель Бgen2исключительно. Я не знаю, если это возможно, но, например, перемещение каждого из этих вызовов внутри цели, к которой они принадлежат, может быть решением, позволяющим избежать этой проблемы.

РЕДАКТИРОВАТЬ Я думал как решение сделать что-то вроде:

      my_generator(
    name = "gen2",
    input_file = select({
       ":opt1": [":targetToGeneratetextFile"],
       ":opt2": ["realTextFile.txt"],
       "//conditions:default": [":targetToGeneratetextFile"],
    }),
    output_file = "outputfile.txt",
    visibility = ["//myproject/oath/to/current/package/test:__subpackages__"],
)

с надлежащимconfig_settingа затем вызовите его из цели с правильным флагом, но я получаю сообщение об ошибке:

ожидаемое значение типа "строка" для элемента 0 атрибута "srcs" в правиле "genrule", но получено select({":opt1": [":targetToGeneratetextFile", ":opt2": ["realTextFile.txt"] ,"//условия:по умолчанию": [":targetToGeneratetextFile"], })

1 ответ

Этикетка _ //path/to/the/file/realFile.txtявляется сокращением для//path/to/the/file/realFile.txt:realFile.txt, он же<repository root>/path/to/the/file/realFile.txt/realFile.txt. В зависимости от того, где находится самая глубокая вложенная папка с файлом BUILD (что определяет пакет), вы ищете что-то вроде//path/to/the/file:realFile.txtили//path/to:the/file/realFile.txtвместо.

У вас не может быть двух правил, которые записывают один и тот же файл, потому что тогда Bazel не сможет сказать, каким способом его построить, если выbazel buildфайл. Некоторые альтернативы:

  • Поместите их в отдельные пакеты (также известные как отдельные папки с файлами BUILD)
  • Назовите их по-разному, напримерgen1_outputfile.txtиgen2_outputfile.txt, илиgen1/outputfile.txtиgen2/outputfile.txt. Вы можете автоматизировать это в макросе, напримерsrcs = [name + '/outputfile.txt'].
  • Используйте одно правило, чтобы сгенерировать его с соответствующим выбором, например, с вашим редактированием.

С помощью вы пытаетесь создать что-то вроде этого:

      genrule(
    srcs = select({..., "//conditions:default": [":targetToGeneratetextFile"]}),
    ...
)

но, как написано, вместо этого у вас есть это:

      genrule(
    srcs = [select({..., "//conditions:default": [":targetToGeneratetextFile"]})],
    ...
)

По сути, между списком вselectзначение и тело макроса, вы создаете вложенный список. Я бы изменил ваш аргумент макроса наinput_filesа затем сделатьsrcs = input_filesв теле, поэтому вызывающий макрос может объединять вещи в списки по своему усмотрению.

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