Trabalhar com dependências externas

Informar um problema Mostrar fonte Por noite · 7,3 · 7,2 · 7,1 · 7,0 · 6,5

Ele pode depender de destinos de outros projetos. Dependências desses outros projetos são chamadas de dependências externas.

O arquivo WORKSPACE (ou WORKSPACE.bazel) na diretório do espaço de trabalho diz ao Bazel como conseguir as credenciais de outros projetos de dados. Esses outros projetos podem conter um ou mais arquivos BUILD com destinos próprios. BUILD arquivos em do projeto principal pode depender desses destinos externos usando o nome de no arquivo WORKSPACE.

Por exemplo, suponha que haja dois projetos em um sistema:

/
  home/
    user/
      project1/
        WORKSPACE
        BUILD
        srcs/
          ...
      project2/
        WORKSPACE
        BUILD
        my-libs/

Se project1 quisesse depender de um destino, :foo, definido em /home/user/project2/BUILD, ele pode especificar que um repositório chamado project2 pode ser encontrado em /home/user/project2. Depois, as segmentações /home/user/project1/BUILD pode depender de @project2//:foo.

O arquivo WORKSPACE permite que os usuários dependam de destinos de outras partes do ou transferidos por download da Internet. Ele usa a mesma sintaxe que BUILD. mas permite um conjunto diferente de regras chamadas regras de repositório (às vezes, também conhecidas como regras do espaço de trabalho). Ele vem com alguns repositórios integrados regras e um conjunto de repositórios Starlark incorporados regras. Os usuários também podem criar repositórios personalizados regras para um comportamento mais complexo.

Tipos compatíveis de dependências externas

Alguns tipos básicos de dependências externas podem ser usados:

Depende de outros projetos do Bazel

Para usar destinos de um segundo projeto do Bazel, você pode usam local_repository, git_repository ou http_archive para vinculá-lo simbolicamente a partir do sistema de arquivos local, referenciar um repositório git ou fazer o download (respectivamente).

Por exemplo, suponha que você esteja trabalhando em um projeto, my-project/, e queira depender dos objetivos do projeto de um colega de trabalho, coworkers-project/. Ambos projetos usam o Bazel, para que você possa adicionar o projeto de um colega de trabalho como um dependência e usar qualquer destino que seu colega de trabalho tenha definido no seu próprio BUILD. Você adicionaria o seguinte a my_project/WORKSPACE:

local_repository(
    name = "coworkers_project",
    path = "/path/to/coworkers-project",
)

Se seu colega de trabalho tiver uma //foo:bar de destino, seu projeto poderá se referir a ela como @coworkers_project//foo:bar. Os nomes de projetos externos devem ser nomes válidos de espaço de trabalho.

Dependendo de projetos que não sejam do Bazel

Regras prefixadas com new_, como new_local_repository, permitem que você crie destinos a partir de projetos que não usam o Bazel.

Por exemplo, suponha que você esteja trabalhando em um projeto, my-project/, e queira depender do projeto de um colega de trabalho, coworkers-project/. Do seu colega de trabalho O projeto usa make para criar, mas você gostaria de depender de um dos arquivos .so gerado por ele. Para fazer isso, adicione o seguinte a my_project/WORKSPACE:

new_local_repository(
    name = "coworkers_project",
    path = "/path/to/coworkers-project",
    build_file = "coworker.BUILD",
)

build_file especifica um arquivo BUILD a ser sobreposto no projeto existente, por exemplo:

cc_library(
    name = "some-lib",
    srcs = glob(["**"]),
    visibility = ["//visibility:public"],
)

Então, você pode depender de @coworkers_project//:some-lib do BUILD arquivos.

Dependendo dos pacotes externos,

Artefatos e repositórios Maven

Usar o conjunto de regras rules_jvm_external para fazer o download de artefatos de repositórios Maven e disponibilizá-los em Java dependências.

Como buscar dependências

Por padrão, as dependências externas são buscadas conforme necessário durante bazel build. Se quiser pré-buscar as dependências necessárias para um conjunto específico de destinos, use bazel fetch Para buscar incondicionalmente todas as dependências externas, use bazel sync À medida que os repositórios buscados são armazenados na base de saída, a busca acontece por espaço de trabalho.

Dependências de acompanhamento

Sempre que possível, recomendamos ter uma única política de versão no em um projeto de IA. Isso é necessário para dependências que você compila e acaba no binário final. Mas, nos casos em que isso não é verdade, é possível dependências de sombra. Pense no seguinte cenário:

projeto/espaço de trabalho

workspace(name = "myproject")

local_repository(
    name = "A",
    path = "../A",
)
local_repository(
    name = "B",
    path = "../B",
)

A/ESPAÇO DE TRABALHO

workspace(name = "A")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "testrunner",
    urls = ["https://github.com/testrunner/v1.zip"],
    sha256 = "...",
)

B/ESPAÇO DE TRABALHO

workspace(name = "B")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "testrunner",
    urls = ["https://github.com/testrunner/v2.zip"],
    sha256 = "..."
)

As dependências A e B dependem de testrunner, mas também dependem de versões diferentes de testrunner. Não há motivo para estes executores de teste não coexistem pacificamente dentro do myproject, mas vão entrar em conflito porque têm o mesmo nome. Para declarar as duas dependências, atualize myproject/WORKSPACE:

workspace(name = "myproject")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "testrunner-v1",
    urls = ["https://github.com/testrunner/v1.zip"],
    sha256 = "..."
)
http_archive(
    name = "testrunner-v2",
    urls = ["https://github.com/testrunner/v2.zip"],
    sha256 = "..."
)
local_repository(
    name = "A",
    path = "../A",
    repo_mapping = {"@testrunner" : "@testrunner-v1"}
)
local_repository(
    name = "B",
    path = "../B",
    repo_mapping = {"@testrunner" : "@testrunner-v2"}
)

Esse mecanismo também pode ser usado para unir diamantes. Por exemplo, se A e B tivesse a mesma dependência, mas chamá-la por nomes diferentes, essas dependências podem serão mesclados em myproject/WORKSPACE.

Como substituir repositórios pela linha de comando

Para substituir um repositório declarado por um repositório local na linha de comando, faça o seguinte: use o método --override_repository . O uso dessa flag altera o conteúdo dos repositórios externos sem alterar o código-fonte.

Por exemplo, para substituir @foo pelo diretório local /path/to/local/foo, transmitir a flag --override_repository=foo=/path/to/local/foo.

Alguns dos casos de uso incluem:

  • Depuração de problemas. Por exemplo, é possível modificar um repositório http_archive para um diretório local no qual é possível fazer alterações com mais facilidade.
  • Fornecedores. Se você estiver em um ambiente em que não é possível fazer chamadas de rede, substitua as regras de repositório baseadas em rede para apontar para diretórios locais como alternativa.

Como usar proxies

O Bazel vai selecionar endereços proxy de HTTPS_PROXY e HTTP_PROXY. variáveis de ambiente e use-as para fazer o download de arquivos HTTP/HTTPS (se especificado).

Suporte para IPv6

Em máquinas somente IPv6, o Bazel pode fazer o download de dependências com nenhuma mudança. Em máquinas IPv4/IPv6 de pilha dupla, o Bazel segue a mesma padrão como Java: se o IPv4 estiver ativado, o IPv4 será preferível. Em algumas situações, por exemplo, quando a rede IPv4 não consegue resolver/alcançar endereços externos, isso pode causar exceções Network unreachable e falhas de build. Nesses casos, é possível substituir o comportamento do Bazel para preferir o IPv6. usando a propriedade do sistema java.net.preferIPv6Addresses=true. Especificamente:

  • Usar o --host_jvm_args=-Djava.net.preferIPv6Addresses=true opção de inicialização, por exemplo, adicionando a seguinte linha em seu Arquivo .bazelrc:

    startup --host_jvm_args=-Djava.net.preferIPv6Addresses=true

  • Se você estiver executando destinos de build Java que precisam se conectar à Internet. (os testes de integração às vezes precisam disso), também use --jvmopt=-Djava.net.preferIPv6Addresses=true sinalização de ferramenta, por exemplo, ao definir linha a seguir no seu arquivo .bazelrc:

    build --jvmopt=-Djava.net.preferIPv6Addresses

  • Se você estiver usando rules_jvm_external, Por exemplo, para resolução da versão da dependência, adicione também -Djava.net.preferIPv6Addresses=true para COURSIER_OPTS variável de ambiente para fornecer opções da JVM para a Coursier

Dependências transitivas

O Bazel só lê as dependências listadas no seu arquivo WORKSPACE. Se o seu projeto (A) depende de outro projeto (B), que lista uma dependência de um terceiro projeto (C) em seu arquivo WORKSPACE, você terá que adicionar tanto B e C ao arquivo WORKSPACE do projeto. Esse requisito pode fazer o balão O tamanho do arquivo é WORKSPACE, mas limita as chances de ter uma biblioteca incluem C na versão 1.0 e outro incluem C na 2.0.

Armazenamento em cache de dependências externas

Por padrão, o Bazel só faz um novo download das dependências externas quando a definição muda. Alterações nos arquivos referenciados na definição (como patches) ou BUILD) também são consideradas pelo Bazel.

Para forçar um novo download, use bazel sync.

Layout

É feito o download das dependências externas em um diretório no subdiretório external na base de saída. No caso de um repositório local, um link simbólico será criado. em vez de criar um novo diretório. Para ver o diretório external, execute:

ls $(bazel info output_base)/external

A execução do bazel clean não exclui o componente externo diretório. Para remover todos os artefatos externos, use bazel clean --expunge.

Compilações off-line

Às vezes, é desejável ou necessário executar um build de modo off-line. Para casos de uso simples, como viajar de avião, prefetching do que com bazel fetch ou bazel sync pode ser suficiente. além do mais, os usando a opção --nofetch, a busca de outros repositórios poderá ser desativada durante o build.

Para builds off-line verdadeiros, em que o fornecimento dos arquivos necessários é feito. por uma entidade diferente do Bazel, o Bazel é compatível com a opção --distdir: Sempre que uma regra de repositório solicitar que o Bazel busque um arquivo pelo ctx.download ou ctx.download_and_extract e fornece uma soma hash do arquivo necessário, o Bazel vai examinar primeiro os diretórios especificados por essa opção um arquivo correspondente ao nome de base do primeiro URL fornecido e usar essa cópia local se o hash corresponder.

O próprio Bazel usa essa técnica para fazer o bootstrap off-line da distribuição artefato. Para isso, ela coleta todas as informações dependências em um ambiente distdir_tar.

No entanto, o Bazel permite a execução de comandos arbitrários em regras de repositório, sem saber se eles pedem para a rede. Portanto, o Bazel não tem opção para fazer com que os builds sejam totalmente off-line. Testar se um build funciona corretamente off-line exige o bloqueio externo da rede, como o Bazel faz na teste de inicialização.

Práticas recomendadas

Regras do repositório

Uma regra de repositório geralmente é responsável por:

  • Detectar as configurações do sistema e gravá-las em arquivos.
  • Encontrar recursos em outro lugar do sistema.
  • Fazendo o download de recursos de URLs.
  • gerar ou fazer a vinculação simbólica de arquivos BUILD no diretório do repositório externo.

Evite usar repository_ctx.execute sempre que possível. Por exemplo, ao usar uma linguagem C++ que não é do Bazel que tenha um build usando o Make, é preferível usar repository_ctx.download() e depois grave um arquivo BUILD em vez de executar ctx.execute(["make"]).

Prefere http_archive a git_repository e new_git_repository. Os motivos são:

  • As regras de repositório Git dependem do sistema git(1), enquanto o downloader HTTP é criado ao Bazel e não tem dependências de sistema.
  • http_archive oferece suporte a uma lista de urls como espelhos, e git_repository oferece suporte apenas um único remote.
  • http_archive funciona com o cache do repositório, mas não git_repository. Consulte #5116 (link em inglês) para mais informações.

Não use bind(). Consulte "Considere remover vinculação" por muito tempo discussão sobre os problemas e as alternativas.