Добавление внешней зависимости с использованием базельского genrule завершается неудачно с ошибкой «Genrules без выходных данных не имеет смысла» - PullRequest
0 голосов
/ 12 января 2019

Я пытаюсь использовать genrule для извлечения и построения внешней зависимости. Установка выглядит следующим образом.

[Root] / WORKSPACE

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
    name = "gsl",
    url = "https://mirror.freedif.org/GNU/gsl/gsl-latest.tar.gz",
    build_file = '@//thirdparty:gsl.BUILD',
)

[Root] / ThirdParty / gsl.BUILD

genrule(
    name = "gsl_genrule",
    srcs = glob([
      "gsl-2.5/**/*.c",
      "gsl-2.5/**/*.h",
    ]),
    outs = glob([
      "gsl-2.5/install/lib/*.so",
      "gsl-2.5/install/include/**/*.h",
    ]),
    cmd = "mkdir install && ./configure --prefix=`pwd`/install && make -j && make install",
)

cc_library(
    name = "gsl",
    srcs = [":gsl_genrule"],
    visibility = ["//visibility:public"],
)

[Root] / SRC / BUILD

cc_binary(
    name = "hello",
    srcs = [
        "hello.cc",
    ],
    deps = [
        "@gsl//:gsl"
    ],
)

Кроме того, у меня есть пустой файл BUILD внутри [Root] / thirdparty, который предотвращает ошибку, при которой bazel не может найти gsl.BUILD. [1]

Когда я запускаю его, genrule дает сбой следующим образом.

$  bazel build -c dbg --sandbox_debug //src:*
INFO: Invocation ID: a698121f-fc3f-449a-9e36-eb2a5f59e06b
INFO: SHA256 (https://mirror.freedif.org/GNU/gsl/gsl-latest.tar.gz) = 0460ad7c2542caaddc6729762952d345374784100223995eb14d614861f2258d
ERROR: /home/buddhika/.cache/bazel/_bazel_buddhika/3fbc2046978475f6bf9fc76463e16ae5/external/gsl/BUILD.bazel:8:12: in outs attribute of genrule rule @gsl//:gsl_genrule: Genrules without outputs don't make sense
ERROR: Analysis of target '//src:hello.dwp' failed; build aborted: Analysis of target '@gsl//:gsl_genrule' failed; build aborted
INFO: Elapsed time: 11.261s
INFO: 0 processes.
FAILED: Build did NOT complete successfully (3 packages loaded, 1689 targets configured)

У меня есть выходные данные для генерации, указанной, как показано в файле gsl.BUILD выше. Есть идеи, что я делаю не так?

[1] https://github.com/bazelbuild/bazel/issues/6873

1 Ответ

0 голосов
/ 12 января 2019

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

Когда bazel анализирует настройки сборки, она (в соответствии с инструкциями) ищет все (существующие) файлы "gsl-2.5/install/lib/*.so" и "gsl-2.5/install/include/**/*.h" и (на момент анализа) не находит ни одного. То есть outs - пустой список, и что касается bazel, то ваше правило действительно не выводит ничего, что делает его бессмысленным жанром.

Вы можете указать список известных вам файлов, которые будут там. Или вам придется использовать пользовательское правило, работающее с TreeArtifacts (выплевывая TreeArtifacts с (всеми) библиотеками и заголовками). Вы также можете предварительно построить зависимость и зависеть от результирующего архива / дерева. Или "газифицировать" свою сборку. (В зависимости от его природы и способа использования, я бы предпочел один из двух последних вариантов.)


РЕДАКТИРОВАТЬ: чуть более подробное объяснение, чтобы обратиться к комментариям.

Базель сначала должен проанализировать и определить, как выглядит дерево сборки. При использовании glob() в outs (что в принципе не имеет смысла), он будет определять outs как список сгруппированных файлов (на этапе анализа) до , когда правило было выполнено.

outs = ["concatenated.txt"]

Хорошо, так как он говорит, что вывод правил - это ровно один файл concatenated.txt. Тем не менее:

outs = glob(["*.txt"])

или даже:

outs = glob(["concatenated.txt"])

совпадает с:

outs = []

, потому что при определении того, что должно быть построено (и когда glob() добирается до конца), ни один из файлов еще не совпадает (вы можете думать об этом как: сказать перед сборкой, что результаты сборки будут точно такими же, как find или ls возврат на выходное дерево, но сейчас, прежде чем я действительно соберу) Отключение, вы, похоже, ожидаете, что outs определит, что делать после , когда правило было запущено (шаг сборки состоялся), но bazel необходимо понять , прежде чем оно выполнится любые правила, какой шаг дает какой результат и, в свою очередь, что нужно сделать для построения запрошенных целей.

TreeArtifacts и Declare_Directory немного ближе к тому, что вы ожидали выше, с точки зрения того, что bazel будет каталог (с вещами в нем) в результате правила.

Вы также можете просто дословно перечислить все файлы *.so и *.h так, как они будут созданы при сборке, и это также решит эту проблему для вас.

Под предварительной сборкой я имел в виду просто скомпилировать вне bazel, упаковать результат и обратиться к архиву с библиотеками и описанием интерфейса (заголовками) из вашей сборки bazel. Этот вариант будет в основном нормальным, если:

  • ваша зависимость не обновляется часто
  • вам не нужно беспокоиться о поддержке широкого или даже неизвестного диапазона целевой системы

В противном случае стоит подумать о том, чтобы «подставить» свою сборку, чтобы она стала частью вашей собственной сборки дерева.

...