Порядок `load` в спецификации Базеля или просто из-за реализации? - PullRequest
1 голос
/ 11 марта 2020

Я столкнулся с проблемой при создании проекта Go с Bazel и обнаружил, что причиной root было порядка load для импорта @io_bazel_rules_go.

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

Может кто-нибудь уточнить, если это spe c или нет?

1 Ответ

2 голосов
/ 12 марта 2020

Документация по переопределению внешних репозиториев нечеткая, но https://docs.bazel.build/versions/2.2.0/external.html, вероятно, лучшая ссылка.

Насколько я понимаю, что:

  • Репозитории объявлены в WORKSPACE или в функциях, вызываемых WORKSPACE, вычисляются лениво. Это важно, потому что оценка правил репозитория может быть очень дорогой (они имеют тенденцию загружать большие файлы) и может не потребоваться для многих сборок.
  • Не является ошибкой объявлять репозиторий более одного раза с одним и тем же имя. Если правило хранилища не было оценено, будет использовано последнее объявление.
  • Правило хранилища оценивается, когда разрешена любая метка в хранилище. Это включает:
    • Загрузка файла .bzl с оператором load.
    • Передача метки в атрибуте в другое правило репозитория, которое оценивается.
    • Использование ctx.path на метке в другом правиле репозитория, которое оценивается.
    • (после того, как WORKSPACE полностью решено) создание цели, которая загружает что-то или зависит от чего-либо в репозитории.
  • После оценки правила репозитория оно больше не может быть переопределено. Последующие объявления репозиториев с тем же именем молча игнорируются.

Этот лог c сбивает с толку, и может быть трудно понять, какая версия чего-либо используется, когда правило объявляется несколько раз.

  • В идеале каждое правило должно объявляться один раз в WORKSPACE, чтобы минимизировать путаницу. Конечно, это может быть сложно, если ваши зависимости предоставляют функции для объявления транзитивных зависимостей. В некоторых случаях вы можете в конечном итоге вручную вставить эти функции.
  • Функции зависимости, такие как go_rules_dependencies, должны избегать переопределения всего, что было объявлено с использованием функции _maybe, например:
def _maybe(repo_rule, name, **kwargs):
    if name not in native.existing_rules():
        repo_rule(name = name, **kwargs)
  • Создайте файл WORKSPACE, чтобы гарантировать, что прямые зависимости объявлены и, возможно, разрешены ранее. Это может усложнить группировку связанных объявлений, но семантика оценки будет более понятной.
    • http_archive и git_repository репозитории для наборов правил и прямых зависимостей.
    • load операторы для правил репозитория и функций зависимостей.
    • Другие прямые зависимости (например, go_repository).
    • Вызовы функций зависимостей для транзитивных зависимостей.
    • Регистрация набора инструментов.

Для отладки native.existing_rules функция может быть очень удобной. Он возвращает список всех объявленных репозиториев, а также атрибуты, с которыми они были объявлены. Определите функцию, которая вызывает ее и печатает результат, затем вызывайте эту функцию из любого места в WORKSPACE.

...