Двойное создание макроса 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__"],
)
Я получаю две ошибки таким образом:
- Как это, Базель не может найти
realFile.txt
: он пытается прочитать его как цель:
нет такого пакета '//path/to/the/file/realFile.txt': файл BUILD не найден ни в одном из следующих каталогов. Добавьте файл BUILD в каталог, чтобы пометить его как пакет.
Если я скопирую файл в текущую папку пакета, он сможет его прочитать.
- 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
в теле, поэтому вызывающий макрос может объединять вещи в списки по своему усмотрению.