Новичок в bazel, так что терпите меня :) У меня есть genrule
, который в основном загружает и распаковывает пакет:
genrule(
name = "extract_pkg",
srcs = ["@deb_pkg//file:pkg.deb"],
outs = ["pkg_dir"],
cmd = "dpkg-deb --extract $< $(@D)/pkg_dir",
)
Естественно, pkg_dir
это каталог. Существует еще одно правило, которое использует это правило в качестве входных данных для создания исполняемого файла, но главное, что теперь мне нужно добавить правило (или что-то еще), которое позволит мне использовать некоторые заголовки из этого пакета. Это правило используется в качестве входных данных для cc_library
, который затем используется в других частях репозитория для получения доступа к заголовкам. Пробовал вот так:
genrule(
name = "pkg_headers",
srcs = [":extract_pkg"],
outs = [
"pkg_dir/usr/include/pkg/h1.h",
"pkg_dir/usr/include/pkg/h2.h"
]
)
Но, похоже, Базелю не нравится тот факт, что оба правила используют один и тот же каталог в качестве вывода, хотя второе ничего не делает (?):
output file 'pkg_dir' of rule 'extract_pkg' conflicts with output file 'pkg_dir/usr/include/pkg/h1.h' of rule 'pkg_headers'
Он отлично работает, если я использую другой каталог «root» для обоих правил, но я думаю, что должен быть какой-то лучший способ сделать это.
EDIT I пробовал использовать declare_directory
следующим образом (скомпилировано из разных источников):
unpack_deb.bzl:
def _unpack_deb_impl(ctx):
input_deb_file = ctx.file.deb
output_dir = ctx.actions.declare_directory(ctx.attr.name + ".cc")
print(input_deb_file.path)
print(output_dir.path)
ctx.actions.run_shell(
inputs = [ input_deb_file ],
outputs = [ output_dir ],
arguments = [ input_deb_file.path, output_dir.path ],
progress_message = "Unpacking %s to %s" % (input_deb_file.path, output_dir.path),
command = "dpkg-deb --extract \"$1\" \"$2\"",
)
return [DefaultInfo(files = depset([output_dir]))]
unpack_deb = rule(
implementation = _unpack_deb_impl,
attrs = {
"deb": attr.label(
mandatory = True,
allow_single_file = True,
doc = "The .deb file to be unpacked",
),
},
doc = """
Unpacks a .deb file and returns a directory.
""",
)
BUILD.bazel:
load(":unpack_deb.bzl", "unpack_deb")
unpack_deb(
name = "pkg_dir",
deb = "@deb_pkg//file:pkg.deb"
)
cc_library(
name = "headers",
linkstatic = True,
srcs = [ "pkg_dir" ],
hdrs = ["pkg_dir.cc/usr/include/pkg/h1.h",
"pkg_dir.cc/usr/include/pkg/h2.h"],
strip_include_prefix = "pkg_dir.cc/usr/include",
)
Уловка с добавление .cc
, чтобы ввод мог быть принят cc_library
, был украден из , этот ответ . Однако команда не работает на
ERROR: missing input file 'blah/blah/pkg_dir.cc/usr/include/pkg/h1.h'
из библиотеки.
Когда я запускаю с отладкой, я вижу, что команда «выполняется» (странно, что я не всегда вижу эту распечатку):
SUBCOMMAND: # //blah/pkg:pkg_dir [action 'Unpacking tmp/deb_pkg/file/pkg.deb to blah/pkg/pkg_dir.cc', configuration: xxxx]
(cd /home/user/.../execroot/src && \
exec env - \
/bin/bash -c 'dpkg-deb --extract "$1" "$2"' '' tmp/deb_pkg/file/pkg.deb bazel-out/.../pkg/pkg_dir.cc)
После выполнения bazel-out/.../pkg/pkg_dir.cc
существует, но пусто. Если я запускаю команду вручную, она правильно извлекает файлы. В чем может быть причина? Кроме того, правильно ли, что после bash
строки командной строки стоит пустая строка?