Повторно использовать разные части загруженного пакета (вывод каталога)? - PullRequest
0 голосов
/ 10 июля 2020

Новичок в 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 строки командной строки стоит пустая строка?

1 Ответ

0 голосов
/ 10 июля 2020

Genrule Bazel не очень хорошо работает с выходными данными каталога. См. https://docs.bazel.build/versions/master/be/general.html#general -совет

Bazel в основном работает с отдельными файлами, хотя есть некоторая поддержка работы с каталогами в правилах Starlark с https://docs.bazel.build/versions/master/skylark/lib/actions.html#declare_directory

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

genrule(
    name = "extract_pkg",
    srcs = ["@deb_pkg//file:pkg.deb"],
    outs = [
        "pkg_dir/usr/include/pkg/h1.h",
        "pkg_dir/usr/include/pkg/h2.h",
        "pkg_dir/other_files/file1",
        "pkg_dir/other_files/file2",
    ],
    cmd = "dpkg-deb --extract $< $(@D)/pkg_dir",
)

filegroup(
    name = "pkg_headers",
    srcs = [
        ":pkg_dir/usr/include/pkg/h1.h",
        ":pkg_dir/usr/include/pkg/h2.h",
   ],
)

filegroup(
    name = "pkg_other_files",
    srcs = [
        ":pkg_dir/other_files/file1",
        ":pkg_dir/other_files/file2",
   ],
)

Если вы видели glob, вы может возникнуть соблазн использовать glob(["pkg_dir/usr/include/pkg/*.h"]) или аналогичный для srcs файловой группы, но обратите внимание, что glob работает только с «исходными файлами», что означает файлы, уже находящиеся на диске, а не с выходными данными других правил.

Есть правила для создания дебетов, но я не знаю правил их импорта. Можно написать такие правила с помощью Starlark: https://docs.bazel.build/versions/master/skylark/repository_rules.html

С помощью правил репозитория можно, помимо прочего, избежать явной записи всех файлов, которые вы хотите извлечь. Возможно, вам потребуется больше работы, чем вы хотите.

...