Spec-Zone.ru › Bazel 8.0

Функции

Содержание

  • пакет
  • группа пакетов
  • экспортируемые файлы
  • glob
  • выбор
  • подпакеты

Пакет

package(default_deprecation, default_package_metadata, default_testonly, default_visibility, features)

Эта функция объявляет метаданные, которые применяются ко всем правилам в пакете. Она используется не более одного раза в пределах пакета (файл BUILD).

Для объявления метаданных, применяемых ко всем правилам во всём репозитории, используйте функцию repo() в файле REPO.bazel в корне вашего репозитория. Функция repo() принимает те же аргументы, что и package().

Функция package() должна вызываться сразу после всех инструкций load() в начале файла, перед любыми правилами.

Аргументы

Атрибут Описание
default_applicable_licenses

Псевдоним для default_package_metadata.

default_visibility

Список метки; по умолчанию []

Видимость по умолчанию для целей правил верхнего уровня и символических макросов в этом пакете — то есть, целей и символических макросов, которые не объявлены внутри символического макроса. Этот атрибут игнорируется, если цель или макрос указывает значение visibility.

Для получения подробной информации о синтаксисе этого атрибута, см. документацию видимости. Видимость по умолчанию пакета не применяется к экспортируемым файлам, которые по умолчанию публичны.

default_deprecation

Строка; по умолчанию ""

Устанавливает сообщение по умолчанию deprecation для всех правил в этом пакете.

default_package_metadata

Список меток; по умолчанию []

Устанавливает список целевых объектов метаданных по умолчанию, которые применяются ко всем другим целям в пакете. Как правило, это цели, связанные с объявлением пакета и лицензии OSS. Для примеров см. rules_license.

default_testonly

Булево значение; по умолчанию False за исключением случаев, когда указано иначе

Устанавливает свойство по умолчанию testonly для всех правил в этом пакете.

В пакетах под javatests значение по умолчанию True.

features

Список строк; по умолчанию []

Устанавливает различные флаги, которые влияют на семантику этого файла BUILD.

Эта функция в основном используется сотрудниками, работающими над системой сборки, для маркировки пакетов, которые требуют специального обращения. Не используйте её, если это не запрошено кем-либо из сотрудников, работающих над системой сборки.

Примеры

Ниже приведён пример, в котором правила в этом пакете видимы только членам группы пакетов //foo:target. Индивидуальные объявления видимости правила, если они присутствуют, переопределяют это условие.

package(default_visibility = ["//foo:target"])

Группа пакетов

package_group(name, packages, includes)

Эта функция определяет набор пакетов и связывает его с меткой. Эта метка может быть использована в атрибутах visibility.

Группы пакетов в первую очередь используются для управления видимостью. Публичная цель может быть обращена из любого пакета в дереве исходников. Приватная цель может быть обращена только из своего собственного пакета (не из подпакетов). В промежуточных случаях цель может разрешить доступ к своему пакету плюс любые пакеты, описанные одним или несколькими группами пакетов. Более подробное описание системы видимости см. в атрибуте visibility.

Пакет считается частью группы, если он соответствует атрибуту packages, или уже входит в одну из других групп пакетов, упомянутых в атрибуте includes.

Группы пакетов технически являются целями, но они не создаются правилами и не имеют защиты видимости.

Аргументы

Атрибут Описание
name

Имя; обязательно

Уникальное имя для этой цели.

packages

Список строк; по умолчанию []

Список нуля или более спецификаций пакетов.

Каждая строка спецификации пакета может иметь один из следующих форматов:

  1. Полное имя пакета без репозитория, начинающееся с двойного слэша. Например, //foo/bar указывает пакет с таким именем, который находится в том же репозитории, что и группа пакетов.
  2. Как выше, но с добавлением trailing /.... Например, //foo/... указывает набор //foo и все его подпакеты. //... указывает все пакеты в текущем репозитории.
  3. Строки public или private, которые соответственно указывают все пакеты или ни одного пакета. (Этот формат требует установки флага --incompatible_package_group_has_public_syntax.)

Кроме того, первые два типа спецификаций пакетов также могут быть префиксрованы - для указания их отрицания.

Группа пакетов содержит любой пакет, который соответствует хотя бы одной положительной спецификации и ни одной отрицательной. Например, значение [//foo/..., -//foo/tests/...] включает все подпакеты //foo , которые не являются также подпакетами //foo/tests. (//foo включается, а //foo/tests — нет.)

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

Если этот атрибут отсутствует, он эквивалентен установке пустого списка, что также эквивалентно установке списка, содержащего только private.

Примечание: До Bazel 6.0, спецификация //... имела устаревшее поведение, эквивалентное public. Это поведение исправлено при включенном флаге --incompatible_fix_package_group_reporoot_syntax, который является значением по умолчанию после Bazel 6.0.

Примечание: До Bazel 6.0, при сериализации этого атрибута как части bazel query --output=proto (или --output=xml), ведущие слэши опускаются. Например, //pkg/foo/... будет выведено как \"pkg/foo/...\". Это поведение исправлено при включенном флаге --incompatible_package_group_includes_double_slash, который является значением по умолчанию после Bazel 6.0.

includes

Список меток; по умолчанию []

Другие группы пакетов, которые включены в эту.

Метки в этом атрибуте должны ссылаться на другие группы пакетов. Пакеты в ссылающихся группах пакетов считаются частью этой группы пакетов. Это транзитивно — если группа пакетов a включает группу пакетов b, и группа пакетов b включает группу пакетов c, то каждый пакет в c также будет являться членом a.

При совместном использовании с отрицательными спецификациями пакетов обратите внимание, что набор пакетов для каждой группы сначала вычисляется независимо, а затем объединяется. Это означает, что отрицательные спецификации в одной группе не влияют на спецификации в другой группе.

Примеры

Следующее объявление package_group объявляет группу пакетов "тропические" , которая содержит тропические фрукты.

package_group(
    name = "tropical",
    packages = [
        "//fruits/mango",
        "//fruits/orange",
        "//fruits/papaya/...",
    ],
)

Следующие объявления указывают группы пакетов вымышленного приложения:

package_group(
    name = "fooapp",
    includes = [
        ":controller",
        ":model",
        ":view",
    ],
)

package_group(
    name = "model",
    packages = ["//fooapp/database"],
)

package_group(
    name = "view",
    packages = [
        "//fooapp/swingui",
        "//fooapp/webui",
    ],
)

package_group(
    name = "controller",
    packages = ["//fooapp/algorithm"],
)

Экспортируемые файлы

exports_files([label, ...], visibility, licenses)

exports_files() определяет список файлов, принадлежащих этому пакету, которые экспортируются в другие пакеты.

Файл BUILD пакета может ссылаться напрямую только на исходные файлы, принадлежащие другому пакету, если они явно экспортированы с помощью инструкции exports_files(). Подробнее о видимости файлов.

В качестве устаревшего поведения, файлы, упомянутые как входные для правила, также экспортируются с видимостью по умолчанию, пока не переключен флаг --incompatible_no_implicit_file_export. Однако, на это поведение не следует полагаться, и необходимо активно от него отходить.

Аргументы

Аргументом является список имён файлов в текущем пакете. Также может быть указано объявление видимости; в этом случае файлы будут видны указанным целям. Если видимость не указана, файлы будут видны каждому пакету, даже если в функции package была указана видимость по умолчанию пакета. Также можно указать лицензии.

Пример

В следующем примере экспортируется golden.txt, текстовый файл из пакета test_data, чтобы другие пакеты могли его использовать, например, в атрибуте data тестов.

# from //test_data/BUILD

exports_files(["golden.txt"])

glob

glob(include, exclude=[], exclude_directories=1, allow_empty=True)

Функция glob находит все файлы, соответствующие определённым шаблонам путей, и возвращает новый, изменяемый, отсортированный список их путей. Glob ищет только файлы в собственном пакете и только исходные файлы (не сгенерированные файлы и другие цели).

Метка исходного файла включается в результат, если путь файла относительно пакета соответствует одному из include шаблонов и ни одному из exclude шаблонов.

Списки include и exclude содержат шаблоны путей, относительные к текущему пакету. Каждый шаблон может состоять из одного или нескольких сегментов пути. Как обычно в Unix-путях, эти сегменты разделяются /. Сегменты в шаблоне сопоставляются с сегментами пути. Сегменты могут содержать подстановочный знак *: он соответствует любой подстроке в сегменте пути (даже пустой подстроке), исключая разделитель каталогов /. Этот подстановочный знак может использоваться несколько раз в одном сегменте пути. Кроме того, подстановочный знак ** может соответствовать нулю или более полным сегментам пути, но он должен быть объявлен как отдельный сегмент пути.

Примеры:
  • foo/bar.txt соответствует точно файлу foo/bar.txt в этом пакете (если foo/ не является подпакетом)
  • foo/*.txt соответствует каждому файлу в каталоге foo/, если файл заканчивается на .txt (если foo/ не является подпакетом)
  • foo/a*.htm* соответствует каждому файлу в каталоге foo/, который начинается с a, затем имеет произвольную строку (может быть пустой), затем имеет .htm, и заканчивается другой произвольной строкой (если foo/ не является подпакетом); например foo/axx.htm и foo/a.html или foo/axxx.html
  • foo/* соответствует каждому файлу в каталоге foo/ (если foo/ не является подпакетом); он не соответствует самому каталогу foo, даже если exclude_directories установлено в 0
  • foo/** соответствует каждому файлу в каждом подкаталоге (не подпакете) под подкаталогом первого уровня пакета foo/; если exclude_directories установлено в 0, то сам каталог foo также соответствует шаблону; в этом случае ** считается, что соответствует нулю сегментам пути
  • **/a.txt соответствует файлам a.txt в каталоге этого пакета плюс подкаталогам, не являющимся подпакетами.
  • **/bar/**/*.txt соответствует каждому файлу .txt в каждом подкаталоге (не подпакете) этого пакета, если хотя бы один каталог в результирующем пути называется bar, например, xxx/bar/yyy/zzz/a.txt или bar/a.txt (помните, что ** также соответствует нулю сегментам) или bar/zzz/a.txt
  • ** соответствует каждому файлу в каждом подкаталоге (не подпакете) этого пакета
  • foo**/a.txt является недопустимым шаблоном, так как ** должен стоять самостоятельно как сегмент
  • foo/ является недопустимым шаблоном, так как второй сегмент, определенный после /, является пустой строкой

Если аргумент exclude_directories включён (установлен в 1), файлы типа каталог будут исключаться из результатов (по умолчанию 1).

Если аргумент allow_empty установлен в False, функция glob вернёт ошибку, если результат в противном случае был бы пустым списком.

Существуют несколько важных ограничений и замечаний:

  1. Так как glob() выполняется во время оценки файла BUILD, glob() соответствует файлам только в вашей исходной структуре, а не сгенерированным файлам. Если вы строите целевой объект, которому необходимы как исходные, так и сгенерированные файлы, вы должны добавить явный список сгенерированных файлов в glob. См. пример ниже с :mylib и :gen_java_srcs.

  2. Если у правила такое же имя, как у сопоставленного исходного файла, правило "затеняет" файл.

    Чтобы понять это, помните, что glob() возвращает список путей, поэтому использование glob() в атрибуте других правил (например, srcs = glob(["*.cc"])) имеет тот же эффект, что и явное перечисление сопоставленных путей. Если, например, glob() возвращает ["Foo.java", "bar/Baz.java"], но в пакете также есть правило с именем "Foo.java" (что разрешено, хотя Bazel предупреждает об этом), то потребитель glob() будет использовать правило "Foo.java" (его выходные данные), а не файл "Foo.java". См. проблему GitHub #10395 GitHub issue #10395 для получения более подробной информации.

  3. Шаблоны могут соответствовать файлам в подкаталогах. И имена подкаталогов могут быть шаблонами. Однако...
  4. Метки не разрешены для пересечения границы пакета, и шаблон не соответствует файлам в подпакетах.

    Например, выражение шаблона **/*.cc в пакете x не включает x/y/z.cc, если x/y существует как пакет (либо как x/y/BUILD, или где-то ещё в пути пакетов). Это означает, что результат выражения шаблона фактически зависит от существования файлов BUILD — то есть, то же самое выражение шаблона включало бы x/y/z.cc, если бы пакета с именем x/y не существовало или он был помечен как удалённый с помощью флага --deleted_packages.

  5. Вышеуказанное ограничение относится ко всем выражениям шаблонов, независимо от используемых подстановочных знаков.
  6. Скрытый файл с именем, начинающимся с ., полностью соответствует подстановочным знакам ** и *. Если вы хотите сопоставить скрытый файл с составным шаблоном, ваш шаблон должен начинаться с .. Например, * и .*.txt будут соответствовать .foo.txt, но *.txt не будет. Скрытые каталоги также сопоставляются аналогичным образом. Скрытые каталоги могут содержать файлы, которые не требуются в качестве входных данных, и могут увеличивать количество ненужных сопоставленных файлов и потребление памяти. Чтобы исключить скрытые каталоги, добавьте их в аргумент списка "exclude".
  7. Подстановочный знак "**" имеет одно исключение: шаблон "**" не соответствует пути каталога пакета. То есть, glob(["**"], exclude_directories = 0) соответствует всем файлам и каталогам строго внутри текущего каталога пакета (но, конечно, не входит в каталоги подпакетов — см. предыдущее примечание об этом).

В общем случае, вы должны попытаться указать соответствующее расширение (например, *.html) вместо использования простого '*' для шаблона glob. Более явное имя является как самодокументирующим, так и гарантирует, что вы не будете случайно сопоставлять резервные файлы или файлы автосохранения emacs/vi/...

При написании правил сборки вы можете перечислить элементы шаблона. Это позволяет генерировать отдельные правила для каждого входного элемента, например. См. раздел расширенного примера шаблона ниже.

Примеры шаблонов

Создайте библиотеку Java, созданную из всех файлов java в этом каталоге и всех файлов, сгенерированных правилом :gen_java_srcs.

java_library(
    name = "mylib",
    srcs = glob(["*.java"]) + [":gen_java_srcs"],
    deps = "...",
)

genrule(
    name = "gen_java_srcs",
    outs = [
        "Foo.java",
        "Bar.java",
    ],
    ...
)

Включите все файлы txt в каталоге testdata, за исключением experimental.txt. Обратите внимание, что файлы в подкаталогах testdata не будут включены. Если вы хотите включить эти файлы, используйте рекурсивный шаблон (**).

sh_test(
    name = "mytest",
    srcs = ["mytest.sh"],
    data = glob(
        ["testdata/*.txt"],
        exclude = ["testdata/experimental.txt"],
    ),
)

Примеры рекурсивных шаблонов

Заставьте тест зависеть от всех файлов txt в каталоге testdata и всех его подкаталогов (и их подкаталогов, и так далее). Каталоги, содержащие файл BUILD, игнорируются. (См. ограничения и замечания выше.)

sh_test(
    name = "mytest",
    srcs = ["mytest.sh"],
    data = glob(["testdata/**/*.txt"]),
)

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

java_library(
    name = "mylib",
    srcs = glob(
        ["**/*.java"],
        exclude = ["**/testing/**"],
    ),
)

Расширенные примеры шаблонов

Создайте отдельное правило genrule для *_test.cc в текущем каталоге, которое подсчитывает количество строк в файле.

# Conveniently, the build language supports list comprehensions.
[genrule(
    name = "count_lines_" + f[:-3],  # strip ".cc"
    srcs = [f],
    outs = ["%s-linecount.txt" % f[:-3]],
    cmd = "wc -l $< >$@",
 ) for f in glob(["*_test.cc"])]

Если файл BUILD выше находится в пакете //foo, и пакет содержит три соответствующих файла, a_test.cc, b_test.cc и c_test.cc, то запуск bazel query '//foo:all' отобразит все сгенерированные правила:

$ bazel query '//foo:all' | sort
//foo:count_lines_a_test
//foo:count_lines_b_test
//foo:count_lines_c_test

select

select(
    {conditionA: valuesA, conditionB: valuesB, ...},
    no_match_error = "custom message"
)

select() — вспомогательная функция, которая делает атрибут правила настраиваемым. Она может заменить правую часть почти любого присвоения атрибута, так что его значение зависит от флагов Bazel командной строки. Вы можете использовать это, например, для определения платформ-специфичных зависимостей или для встраивания различных ресурсов в зависимости от того, построено ли правило в режиме «разработчик» или «выпуск».

Основное использование следующее:

sh_binary(
    name = "mytarget",
    srcs = select({
        ":conditionA": ["mytarget_a.sh"],
        ":conditionB": ["mytarget_b.sh"],
        "//conditions:default": ["mytarget_default.sh"]
    })
)

Это делает атрибут srcs правила sh_binary настраиваемым, заменяя его обычное присвоение списка меток вызовом select, который сопоставляет условия конфигурации со соответствующими значениями. Каждое условие — это ссылка на метку config_setting или constraint_value, которая «соответствует», если конфигурация целевого объекта соответствует ожидаемому набору значений. Значение mytarget#srcs затем становится тем списком меток, который соответствует текущему вызову.

Примечания:

  • При любом вызове выбирается ровно одно условие.
  • Если несколько условий совпадают, и одно является специализацией других, специализация имеет приоритет. Условие B считается специализацией условия A, если B имеет все те же флаги и значения ограничений, что и A, плюс некоторые дополнительные флаги или значения ограничений. Это также означает, что разрешение специализации не предназначено для создания упорядоченности, как показано в Примере 2 ниже.
  • Если несколько условий совпадают, и одно не является специализацией всех остальных, Bazel завершается с ошибкой, если только все условия не разрешаются до одного и того же значения.
  • Специальный псевдо-метка //conditions:default считается совпадающей, если ни одно другое условие не совпадает. Если это условие пропущено, какое-то другое правило должно совпасть, чтобы избежать ошибки.
  • select может быть вложенным внутри более крупного присваивания атрибута. Таким образом, srcs = ["common.sh"] + select({ ":conditionA": ["myrule_a.sh"], ...}) и srcs = select({ ":conditionA": ["a.sh"]}) + select({ ":conditionB": ["b.sh"]}) являются допустимыми выражениями.
  • select работает со многими, но не со всеми, атрибутами. Несовместимые атрибуты помечены nonconfigurable в их документации.

    Подпакеты

    subpackages(include, exclude=[], allow_empty=True)

    subpackages() — вспомогательная функция, аналогичная glob(), которая перечисляет подпакеты вместо файлов и каталогов. Она использует те же шаблоны путей, что и glob(), и может сопоставлять любой подпакет, являющийся непосредственным потомком текущего загружаемого файла BUILD. См. glob для подробного объяснения и примеров шаблонов включения и исключения.

    Полученный отсортированный список подпакетов содержит пути, относительные к текущему загружаемому пакету, которые соответствуют заданным шаблонам в include, а не в exclude.

    Пример

    Следующий пример перечисляет все непосредственные подпакеты для пакета foo/BUILD

    # The following BUILD files exist:
    # foo/BUILD
    # foo/bar/baz/BUILD
    # foo/bar/but/bad/BUILD
    # foo/sub/BUILD
    # foo/sub/deeper/BUILD
    #
    # In foo/BUILD a call to
    subs1 = subpackages(include = ["**"])
    
    # results in subs1 == ["sub", "bar/baz", "bar/but/bad"]
    #
    # 'sub/deeper' is not included because it is a subpackage of 'foo/sub' not of
    # 'foo'
    
    subs2 = subpackages(include = ["bar/*"])
    # results in subs2 = ["bar/baz"]
    #
    # Since 'bar' is not a subpackage itself, this looks for any subpackages under
    # all first level subdirectories of 'bar'.
    
    subs3 = subpackages(include = ["bar/**"])
    # results in subs3 = ["bar/baz", "bar/but/bad"]
    #
    # Since bar is not a subpackage itself, this looks for any subpackages which are
    # (1) under all subdirectories of 'bar' which can be at any level, (2) not a
    # subpackage of another subpackages.
    
    subs4 = subpackages(include = ["sub"])
    subs5 = subpackages(include = ["sub/*"])
    subs6 = subpackages(include = ["sub/**"])
    # results in subs4 and subs6 being ["sub"]
    # results in subs5 = [].
    #
    # In subs4, expression "sub" checks whether 'foo/sub' is a package (i.e. is a
    # subpackage of 'foo').
    # In subs5, "sub/*" looks for subpackages under directory 'foo/sub'. Since
    # 'foo/sub' is already a subpackage itself, the subdirectories will not be
    # traversed anymore.
    # In subs6, 'foo/sub' is a subpackage itself and matches pattern "sub/**", so it
    # is returned. But the subdirectories of 'foo/sub' will not be traversed
    # anymore.
    

    В целом рекомендуется, чтобы вместо непосредственного вызова этой функции пользователи использовали модуль «subpackages» из skylib.

За исключением случаев, оговоренных в ином порядке, содержимое этой страницы лицензировано по лицензии Creative Commons Attribution 4.0, а примеры кода лицензированы по лицензии Apache 2.0. Подробности см. в Политике сайта Google для разработчиков. Java — зарегистрированный товарный знак Oracle и/или ее аффилированных компаний.

Последнее обновление 2024-12-10 UTC.

Licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License.
https://bazel.build/versions/8.0.0/reference/be/functions

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API