Funções

Reportar um problema Ver a fonte Noturna · 8.0 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

Conteúdo

pacote

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

Essa função declara metadados que se aplicam a todas as regras no pacote. Ele é usado no máximo uma vez em um pacote (arquivo BUILD).

Para a contraparte que declara metadados que se aplicam a todas as regras no repositório, use a função repo() no arquivo REPO.bazel na raiz do repositório. A função repo() usa exatamente os mesmos argumentos que package().

A função package() precisa ser chamada logo após todas as instruções load() na parte de cima do arquivo, antes de qualquer regra.

Argumentos

Atributo Descrição
default_applicable_licenses

Alias para default_package_metadata.

default_visibility

Lista de rótulos; o padrão é []

A visibilidade padrão das regras neste pacote.

Todas as regras neste pacote têm a visibilidade especificada neste atributo, a menos que seja especificado de outra forma no atributo visibility da regra. Para informações detalhadas sobre a sintaxe desse atributo, consulte a documentação de visibilidade. A visibilidade padrão do pacote não se aplica a exports_files, que é pública por padrão.

default_deprecation

String; o padrão é ""

Define a mensagem deprecation padrão para todas as regras neste pacote.

default_package_metadata

Lista de rótulos; o padrão é []

Define uma lista padrão de destinos de metadados que se aplicam a todos os outros destinos no pacote. Geralmente, são destinos relacionados a declarações de licença e pacotes de OSS. Consulte rules_license para conferir exemplos.

default_testonly

Booleano. O padrão é False, exceto quando indicado

Define a propriedade testonly padrão para todas as regras neste pacote.

Em pacotes com javatests, o valor padrão é True.

features

Lista de strings. O padrão é [].

Define várias flags que afetam a semântica desse arquivo BUILD.

Esse recurso é usado principalmente por pessoas que trabalham no sistema de build para marcar pacotes que precisam de algum tipo de tratamento especial. Não use essa opção, a menos que seja explicitamente solicitada por alguém que esteja trabalhando no sistema de build.

Exemplos

A declaração abaixo declara que as regras neste pacote são visíveis apenas para membros do grupo de pacote //foo:target. Declarações de visibilidade individuais em uma regra, se presentes, substituem essa especificação.
package(default_visibility = ["//foo:target"])

package_group

package_group(name, packages, includes)

Essa função define um conjunto de pacotes e associa um rótulo a ele. O rótulo pode ser referenciado nos atributos visibility.

Os grupos de pacotes são usados principalmente para controle de visibilidade. Um destino visível publicamente pode ser referenciado em todos os pacotes na árvore de origem. Um destino particularmente visível só pode ser referenciado no próprio pacote (não em subpacotes). Entre esses extremos, um destino pode permitir o acesso ao próprio pacote e a qualquer um dos pacotes descritos por um ou mais grupos de pacotes. Para uma explicação mais detalhada do sistema de visibilidade, consulte o atributo visibilidade.

Um determinado pacote é considerado como estando no grupo se corresponder ao atributo packages ou já estiver contido em um dos outros grupos de pacotes mencionados no atributo includes.

Os grupos de pacotes são tecnicamente de destino, mas não são criados por regras e não têm proteção de visibilidade.

Argumentos

Atributo Descrição
name

Nome: obrigatório

Um nome exclusivo para essa segmentação.

packages

Lista de strings. O padrão é [].

Uma lista de zero ou mais especificações de pacotes.

Cada string de especificação de pacote pode ter uma das seguintes formas:

  1. O nome completo de um pacote, sem o repositório, começando com uma barra dupla. Por exemplo, //foo/bar especifica o pacote com esse nome e que está no mesmo repositório que o grupo de pacotes.
  2. Como acima, mas com um /... final. Por exemplo, //foo/... especifica o conjunto de //foo e todos os subpacotes dele. //... especifica todos os pacotes no repositório atual.
  3. As strings public ou private, que especificam todos os pacotes ou nenhum. Esse formulário exige que a flag --incompatible_package_group_has_public_syntax seja definida.

Além disso, os dois primeiros tipos de especificações de pacote também podem ter o prefixo - para indicar que são negados.

O grupo de pacotes contém qualquer pacote que corresponda a pelo menos uma das especificações positivas e nenhuma das especificações negativas. Por exemplo, o valor [//foo/..., -//foo/tests/...] inclui todos os subpacotes de //foo que não são também subpacotes de //foo/tests. O //foo em si é incluído, enquanto o //foo/tests não é.

Além da visibilidade pública, não há como especificar diretamente pacotes fora do repositório atual.

Se esse atributo estiver ausente, ele será igual a uma lista vazia, o que também é o mesmo que definir uma lista que contém apenas private.

Observação:antes do Bazel 6.0, a especificação //... tinha um comportamento legado idêntico ao public. Esse comportamento é corrigido quando --incompatible_fix_package_group_reporoot_syntax é ativado, que é o padrão após o Bazel 6.0.

Observação:antes do Bazel 6.0, quando esse atributo é serializado como parte de bazel query --output=proto (ou --output=xml), os caracteres de barra invertida iniciais são omitidos. Por exemplo, //pkg/foo/... será exibido como \"pkg/foo/...\". Esse comportamento é corrigido quando --incompatible_package_group_includes_double_slash é ativado, que é o padrão após o Bazel 6.0.

includes

Lista de rótulos; o padrão é []

Outros grupos de pacotes incluídos neste.

Os rótulos nesse atributo precisam se referir a outros grupos de pacotes. Os pacotes em grupos de pacotes referenciados são considerados parte deste grupo de pacotes. Isso é transitivo. Se o grupo de pacotes a incluir o grupo de pacotes b e b incluir o grupo de pacotes c, todos os pacotes em c também serão membros de a.

Quando usado com especificações de pacotes negadas, o conjunto de pacotes de cada grupo é calculado primeiro de forma independente, e os resultados são unidos. Isso significa que as especificações negadas em um grupo não têm efeito sobre as especificações em outro grupo.

Exemplos

A declaração package_group a seguir especifica um grupo de pacotes chamado "tropical" que contém frutas tropicais.

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

As declarações a seguir especificam os grupos de pacotes de um aplicativo fictício:

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

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

exports_files() especifica uma lista de arquivos pertencentes a este pacote que são exportados para outros pacotes.

O arquivo BUILD de um pacote só pode se referir diretamente a arquivos de origem pertencentes a outro pacote se eles forem exportados explicitamente com uma instrução exports_files(). Leia mais sobre a visibilidade de arquivos.

Como comportamento legado, os arquivos mencionados como entrada de uma regra também são exportados com a visibilidade padrão até que a flag --incompatible_no_implicit_file_export seja invertida. No entanto, não é recomendável confiar nesse comportamento e migrar ativamente dele.

Argumentos

O argumento é uma lista de nomes de arquivos no pacote atual. Uma declaração de visibilidade também pode ser especificada. Nesse caso, os arquivos vão ficar visíveis para os destinos especificados. Se nenhuma visibilidade for especificada, os arquivos vão ficar visíveis para todos os pacotes, mesmo que uma visibilidade padrão de pacote tenha sido especificada na função package. As licenças também podem ser especificadas.

Exemplo

O exemplo a seguir exporta golden.txt, um arquivo de texto do pacote test_data, para que outros pacotes possam usá-lo, por exemplo, no atributo data dos testes.

# from //test_data/BUILD

exports_files(["golden.txt"])

glob

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

O Glob é uma função auxiliar que encontra todos os arquivos que correspondem a determinados padrões de caminho e retorna uma lista nova, mutável e classificada dos caminhos. O glob só pesquisa arquivos no próprio pacote e procura apenas arquivos de origem (não arquivos gerados nem outras metas).

O rótulo de um arquivo de origem é incluído no resultado se o caminho relativo ao pacote do arquivo corresponder a qualquer um dos padrões include e nenhum dos padrões exclude.

As listas include e exclude contêm padrões de caminho relativos ao pacote atual. Cada padrão pode consistir em um ou mais segmentos de caminho. Como de costume com caminhos Unix, esses segmentos são separados por /. Os segmentos podem conter o caractere curinga *: ele corresponde a qualquer substring no segmento de caminho (até mesmo a substring vazia), excluindo o separador de diretório /. Esse caractere curinga pode ser usado várias vezes em um segmento de caminho. Além disso, o caractere curinga ** pode corresponder a zero ou mais segmentos de caminho completos, mas precisa ser declarado como um segmento de caminho independente.

Exemplos:
  • foo/bar.txt corresponde exatamente ao arquivo foo/bar.txt neste pacote
  • foo/*.txt corresponde a todos os arquivos no diretório foo/ se o arquivo terminar com .txt (a menos que foo/ seja um subpacote)
  • foo/a*.htm* corresponde a todos os arquivos no diretório foo/ que começam com a, depois têm uma string arbitrária (pode estar vazia), depois têm .htm e terminam com outra string arbitrária, como foo/axx.htm e foo/a.html ou foo/axxx.html
  • **/a.txt corresponde a todos os arquivos a.txt em todos os subdiretórios desse pacote.
  • **/bar/**/*.txt corresponde a todos os arquivos .txt em todos os subdiretórios desse pacote, se pelo menos um diretório no caminho resultante for chamado de bar, como xxx/bar/yyy/zzz/a.txt ou bar/a.txt (lembre-se de que ** também corresponde a zero segmentos) ou bar/zzz/a.txt.
  • ** corresponde a todos os arquivos em todos os subdiretórios deste pacote
  • foo**/a.txt é um padrão inválido, porque ** precisa ser um segmento independente

Se o argumento exclude_directories estiver ativado (definido como 1), os arquivos do tipo diretório serão omitidos dos resultados (padrão 1).

Se o argumento allow_empty for definido como False, a função glob vai gerar um erro se o resultado for a lista vazia.

Há várias limitações e ressalvas importantes:

  1. Como glob() é executado durante a avaliação de arquivos BUILD, glob() corresponde apenas a arquivos na árvore de origem, nunca a arquivos gerados. Se você estiver criando um destino que exige arquivos de origem e gerados, anexe uma lista explícita de arquivos gerados ao glob. Confira o exemplo abaixo com :mylib e :gen_java_srcs.

  2. Se uma regra tiver o mesmo nome que um arquivo de origem correspondente, ela "obscurecerá" o arquivo.

    Para entender isso, lembre-se de que glob() retorna uma lista de caminhos. Portanto, usar glob() em outros atributos de regras (por exemplo, srcs = glob(["*.cc"])) tem o mesmo efeito de listar os caminhos correspondentes explicitamente. Se, por exemplo, glob() produzir ["Foo.java", "bar/Baz.java"], mas também houver uma regra no pacote chamada "Foo.java" (o que é permitido, embora o Bazel emita um aviso sobre isso), o consumidor de glob() vai usar a regra "Foo.java" (saídas) em vez do arquivo "Foo.java". Consulte o problema #10395 do GitHub para mais detalhes.

  3. Os globs podem corresponder a arquivos em subdiretórios. E os nomes de subdiretórios podem ter caracteres curinga. No entanto...
  4. Os marcadores não podem cruzar o limite do pacote, e o glob não corresponde a arquivos em subpacotes.

    Por exemplo, a expressão glob **/*.cc no pacote x não inclui x/y/z.cc se x/y existir como um pacote (como x/y/BUILD ou em outro lugar no caminho do pacote). Isso significa que o resultado da expressão glob depende da existência de arquivos BUILD. Ou seja, a mesma expressão glob incluiria x/y/z.cc se não houvesse um pacote chamado x/y ou se ele fosse marcado como excluído usando a bandeira --deleted_packages.

  5. A restrição acima se aplica a todas as expressões glob, independentemente dos curingas usados.
  6. Um arquivo oculto com um nome que começa com . é totalmente correspondido pelos caracteres curinga ** e *. Se você quiser corresponder a um arquivo oculto com um padrão composto, ele precisa começar com .. Por exemplo, * e .*.txt corresponderão a .foo.txt, mas *.txt não. Os diretórios ocultos também são correspondidos da mesma maneira. Diretórios ocultos podem incluir arquivos que não são necessários como entradas e aumentar o número de arquivos globados desnecessariamente e o consumo de memória. Para excluir diretórios ocultos, adicione-os ao argumento de lista "exclude".
  7. O curinga "**" tem um caso extremo: o padrão "**" não corresponde ao caminho do diretório do pacote. Ou seja, glob(["**"], exclude_directories = 0) corresponde a todos os arquivos e diretórios transitivamente, estritamente, no diretório do pacote atual (mas, claro, não entra em diretórios de subpacotes. Consulte a observação anterior).

Em geral, tente fornecer uma extensão adequada (por exemplo, *.html) em vez de usar um '*' vazio para um padrão glob. O nome mais explícito é autodocumentado e garante que você não combine acidentalmente arquivos de backup ou arquivos de salvamento automático emacs/vi/...

Ao escrever regras de build, você pode enumerar os elementos do glob. Isso permite gerar regras individuais para cada entrada, por exemplo. Consulte a seção exemplo de glob expandido abaixo.

Exemplos de glob

Crie uma biblioteca Java criada a partir de todos os arquivos Java neste diretório e de todos os arquivos gerados pela regra :gen_java_srcs.

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

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

Inclua todos os arquivos txt no diretório testdata, exceto experimental.txt. Os arquivos em subdiretórios de testdata não serão incluídos. Se você quiser que esses arquivos sejam incluídos, use um glob recursivo (**).

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

Exemplos de glob recursivo

Faça com que o teste dependa de todos os arquivos txt no diretório de dados de teste e de todos os subdiretórios (e subdiretórios deles e assim por diante). Os subdiretórios que contêm um arquivo BUILD são ignorados. Consulte as limitações e ressalvas acima.

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

Crie uma biblioteca criada com todos os arquivos Java neste diretório e todos os subdiretórios, exceto aqueles cujo caminho inclui um diretório chamado "testing". Evite esse padrão, se possível, porque ele pode reduzir a incrementalidade do build e, portanto, aumentar os tempos de build.

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

Exemplos de globs expandidos

Crie uma genrule individual para *_test.cc no diretório atual que conte o número de linhas no arquivo.

# 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"])]

Se o arquivo BUILD acima estiver no pacote //foo e o pacote contiver três arquivos correspondentes, a_test.cc, b_test.cc e c_test.cc, a execução de bazel query '//foo:all' vai listar todas as regras que foram geradas:

$ 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() é a função auxiliar que torna um atributo de regra configurável. Ele pode substituir o lado direito de quase qualquer atribuição de atributo. Assim, o valor depende das flags do Bazel na linha de comando. É possível usar isso, por exemplo, para definir dependências específicas da plataforma ou incorporar diferentes recursos, dependendo se uma regra foi criada no modo "desenvolvedor" ou "liberação".

O uso básico é o seguinte:

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

Isso torna o atributo srcs de um sh_binary configurável substituindo a atribuição de lista de rótulos normal por uma chamada select que mapeia condições de configuração para valores correspondentes. Cada condição é uma referência de rótulo a um config_setting ou constraint_value, que "corresponde" se a configuração do destino corresponde a um conjunto esperado de valores. O valor de mytarget#srcs se torna a lista de rótulos que corresponde à invocação atual.

Observações:

  • Exatamente uma condição é selecionada em qualquer invocação.
  • Se várias condições corresponderem e uma for uma especialização das outras, a especialização terá precedência. A condição B é considerada uma especialização da condição A se tiver todas as mesmas flags e valores de restrição que A, além de algumas flags ou valores de restrição adicionais. Isso também significa que a resolução de especialização não foi projetada para criar uma ordenação, conforme demonstrado no Exemplo 2 abaixo.
  • Se várias condições corresponderem e uma não for uma especialização de todas as outras, o Bazel vai falhar com um erro, a menos que todas as condições sejam resolvidas com o mesmo valor.
  • O pseudorótulo especial //conditions:default é considerado correspondente se nenhuma outra condição corresponder. Se essa condição for deixada de fora, outra regra precisará corresponder para evitar um erro.
  • select pode ser incorporado dentro de uma atribuição de atributo maior. Portanto, srcs = ["common.sh"] + select({ ":conditionA": ["myrule_a.sh"], ...}) e srcs = select({ ":conditionA": ["a.sh"]}) + select({ ":conditionB": ["b.sh"]}) são expressões válidas.
  • select funciona com a maioria dos atributos, mas não com todos. Atributos incompatíveis são marcados como nonconfigurable na documentação.

    subpacotes

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

    subpackages() é uma função auxiliar semelhante a glob() que lista subpacotes em vez de arquivos e diretórios. Ele usa os mesmos padrões de caminho que glob() e pode corresponder a qualquer subpacote que seja um descendente direto do arquivo BUILD em carregamento. Consulte glob para uma explicação detalhada e exemplos de padrões de inclusão e exclusão.

    A lista resultante de subpacotes retornados é classificada e contém caminhos relativos ao pacote de carregamento atual que correspondem aos padrões fornecidos em include, e não aqueles em exclude.

    Exemplo

    O exemplo a seguir lista todos os subpacotes diretos do pacote foo/BUILD.

    # The following BUILD files exist:
    # foo/BUILD
    # foo/bar/baz/BUILD
    # foo/sub/BUILD
    # foo/sub/deeper/BUILD
    #
    # In foo/BUILD a call to
    subs = subpackages(include = ["**"])
    
    # results in subs == ["sub", "bar/baz"]
    #
    # 'sub/deeper' is not included because it is a subpackage of 'foo/sub' not of
    # 'foo'
    

    Em geral, em vez de chamar essa função diretamente, é preferível que os usuários usem o módulo "subpackages" da skylib.