Java e Bazel

Relatar um problema Conferir código-fonte Por noite · 7,3 · 7,2 · 7,1 · 7,0 · 6,5

Esta página contém recursos que ajudam você a usar o Bazel com projetos Java. Ela links para um tutorial, regras de build e outras informações específicas da criação Projetos Java com o Bazel.

Como trabalhar com o Bazel

Os recursos a seguir ajudam você a trabalhar com o Bazel em projetos Java:

Como migrar para o Bazel

Se você cria projetos Java com o Maven, siga as etapas na guia de migração para começar a criar projetos Maven com o Bazel:

Versões do Java

Há duas versões relevantes do Java definidas com sinalizações de configuração:

  • a versão dos arquivos de origem no repositório
  • a versão do ambiente de execução Java usado para executar o código e testar

Como configurar a versão do código-fonte no seu repositório

Sem uma configuração extra, o Bazel assume todos os arquivos de origem Java na repositório são escritos em uma única versão do Java. Para especificar a versão das fontes no repositório, adicione build --java_language_version={ver} ao arquivo .bazelrc, em que {ver} é, por exemplo, 11. Proprietários do repositório do Bazel deve definir essa flag para que o Bazel e os usuários dele possam consultar Número da versão do Java. Para mais detalhes, consulte Sinalização da versão da linguagem Java.

Configurar a JVM usada para executar e testar o código

O Bazel usa um JDK para compilação e outra JVM para executar e testar o código.

Por padrão, o Bazel compila o código usando um JDK que é baixado e executado. testa o código com a JVM instalada na máquina local. O Bazel procura a JVM usando JAVA_HOME ou caminho.

Os binários resultantes são compatíveis com a JVM instalada localmente no sistema bibliotecas, o que significa que os binários resultantes dependem do que está instalado no máquina virtual.

Para configurar a JVM usada para execução e teste, use --java_runtime_version . O valor padrão é local_jdk.

Teste e compilação hermética

Para criar uma compilação hermética, use a flag de linha de comando --java_runtime_version=remotejdk_11. O código é compilado, executado e testado na JVM baixada de um repositório remoto. Para mais detalhes, consulte Sinalização da versão do ambiente de execução do Java.

Como configurar a compilação e a execução de ferramentas de build em Java

Há um segundo par de JDK e JVM usado para criar e executar ferramentas, que são usados no processo de build, mas não nos resultados do build. Esse JDK e JVM são controladas usando --tool_java_language_version e --tool_java_runtime_version. Os valores padrão são 11 e remotejdk_11, respectivamente.

Compilar usando o JDK instalado localmente

Por padrão, o Bazel compila usando o JDK remoto, porque ele modifica o os componentes internos. Os conjuntos de ferramentas de compilação que usam o JDK instalado localmente estão configurados, mas não são usados.

Para compilar usando o JDK instalado localmente, use os conjuntos de ferramentas de compilação. para JDK local, use a sinalização extra --extra_toolchains=@local_jdk//:all. No entanto, isso pode não funcionar no JDK de fornecedores arbitrários.

Para mais detalhes, consulte Como configurar toolchains Java.

Práticas recomendadas

Além das práticas recomendadas gerais do Bazel, abaixo estão práticas recomendadas específicas para projetos Java.

Estrutura do diretório

Prefira o layout de diretório padrão do Maven (origens em src/main/java, testes) em src/test/java).

Arquivos BUILD

Siga estas diretrizes ao criar seus arquivos BUILD:

  • Use um arquivo BUILD por diretório contendo origens Java, porque essa melhora o desempenho do build.

  • Cada arquivo BUILD precisa conter uma regra java_library semelhante a isso:

    java_library(
        name = "directory-name",
        srcs = glob(["*.java"]),
        deps = [...],
    )
    
  • O nome da biblioteca deve ser o nome do diretório que contém o BUILD. Isso torna o rótulo da biblioteca mais curto, que é usado "//package" em vez de "//package:package".

  • As origens precisam ser um glob não recursivo de todos os arquivos Java no diretório.

  • Os testes precisam estar em um diretório correspondente em src/test e depender dessa biblioteca.

Como criar novas regras para builds avançados em Java

Observação: a criação de novas regras é destinada a cenários avançados de build e teste. Você não precisa dele para começar a usar o Bazel.

Os módulos, fragmentos de configuração e provedores a seguir vão ajudar você estender os recursos do Bazel ao criar seu app projetos:

Como configurar os conjuntos de ferramentas do Java

O Bazel usa dois tipos de toolchains Java: - execução, usada para executar e testar binários Java, controlada com a flag --java_runtime_version - compilação, usada para compilar origens Java, controlada com a flag --java_language_version

Como configurar outras cadeias de ferramentas de execução

A cadeia de ferramentas de execução é a JVM, local ou de um repositório, com algumas informações adicionais sobre a versão, o sistema operacional e a arquitetura da CPU.

Os conjuntos de ferramentas de execução Java podem ser adicionados usando as APIs local_java_repository ou remote_java_repository regras de repositório em uma extensão de módulo. A adição da regra disponibiliza a JVM usando uma flag. Quando várias definições para o mesmo sistema operacional e arquitetura de CPU são fornecidas, a primeira é usada.

Exemplo de configuração de JVM local:

load("@bazel_tools//tools/jdk:local_java_repository.bzl", "local_java_repository")

local_java_repository(
  name = "additionaljdk",          # Can be used with --java_runtime_version=additionaljdk, --java_runtime_version=11 or --java_runtime_version=additionaljdk_11
  version = 11,                    # Optional, if not set it is autodetected
  java_home = "/usr/lib/jdk-15/",  # Path to directory containing bin/java
)

Exemplo de configuração da JVM remota:

load("@bazel_tools//tools/jdk:remote_java_repository.bzl", "remote_java_repository")

remote_java_repository(
  name = "openjdk_canary_linux_arm",
  prefix = "openjdk_canary", # Can be used with --java_runtime_version=openjdk_canary_11
  version = "11",            # or --java_runtime_version=11
  target_compatible_with = [ # Specifies constraints this JVM is compatible with
    "@platforms//cpu:arm",
    "@platforms//os:linux",
  ],
  urls = ...,               # Other parameters are from http_repository rule.
  sha256 = ...,
  strip_prefix = ...
)

Como configurar outros conjuntos de ferramentas de compilação

O conjunto de ferramentas de compilação é composto pelo JDK e várias ferramentas que o Bazel usa durante a compilação e que oferece recursos adicionais, como: Suscetibilidade a erros, dependências Java rígidas, compilação de cabeçalhos, simplificação de Android, instrumentação de cobertura e tratamento de genclass para ambientes de desenvolvimento integrados.

O JavaBuilder é uma ferramenta do Bazel que executa compilação e fornece as e recursos mencionados acima. A compilação real é executada usando o pelo JDK. O JDK usado para compilação é especificado por java_runtime. do conjunto de ferramentas.

O Bazel substitui alguns elementos internos do JDK. No caso de uma versão do JDK > 9, os módulos java.compiler e jdk.compiler são corrigidos usando a flag --patch_module do JDK. No caso da versão 8 do JDK, o compilador Java é corrigido usando sinalização -Xbootclasspath.

VanillaJavaBuilder é uma segunda implementação do JavaBuilder, que não modifica o compilador interno do JDK e não tem nenhum dos recursos adicionais. O VanillaJavaBuilder não é usado por nenhuma das cadeias de ferramentas integradas.

Além do JavaBuilder, o Bazel usa várias outras ferramentas durante a compilação.

A ferramenta ijar processa arquivos jar para remover tudo, exceto chamadas assinaturas. Os jars resultantes são chamados de jars de cabeçalho. Elas são usadas para melhorar a compilação incremental, recompilando apenas as dependentes dependentes quando o corpo de uma função muda.

A ferramenta singlejar empacota vários arquivos jar em um único.

A ferramenta genclass pós-processa a saída de uma compilação Java e produz um jar contendo apenas os arquivos de classe das fontes que foram geradas por processadores de anotações.

A ferramenta JacocoRunner executa o Jacoco em arquivos instrumentados e gera resultados em no formato LCOV.

A ferramenta TestRunner executa testes JUnit 4 em um ambiente controlado.

É possível reconfigurar a compilação adicionando a macro default_java_toolchain ao um arquivo BUILD e registrá-lo adicionando a regra register_toolchains ao o arquivo MODULE.bazel ou usando --extra_toolchains.

A cadeia de ferramentas só é usada quando o atributo source_version corresponde ao valor especificado pela flag --java_language_version.

Exemplo de configuração do conjunto de ferramentas:

load(
  "@bazel_tools//tools/jdk:default_java_toolchain.bzl",
  "default_java_toolchain", "DEFAULT_TOOLCHAIN_CONFIGURATION", "BASE_JDK9_JVM_OPTS", "DEFAULT_JAVACOPTS"
)

default_java_toolchain(
  name = "repository_default_toolchain",
  configuration = DEFAULT_TOOLCHAIN_CONFIGURATION,        # One of predefined configurations
                                                          # Other parameters are from java_toolchain rule:
  java_runtime = "@bazel_tools//tools/jdk:remote_jdk11", # JDK to use for compilation and toolchain's tools execution
  jvm_opts = BASE_JDK9_JVM_OPTS + ["--enable_preview"],   # Additional JDK options
  javacopts = DEFAULT_JAVACOPTS + ["--enable_preview"],   # Additional javac options
  source_version = "9",
)

que pode ser usado com --extra_toolchains=//:repository_default_toolchain_definition ou adicionando register_toolchains("//:repository_default_toolchain_definition") ao espaço de trabalho.

Configurações predefinidas:

  • DEFAULT_TOOLCHAIN_CONFIGURATION: todos os recursos, com suporte a versões 9 ou mais recentes do JDK.
  • VANILLA_TOOLCHAIN_CONFIGURATION: sem recursos adicionais, oferece suporte a JDKs de fornecedores arbitrários.
  • PREBUILT_TOOLCHAIN_CONFIGURATION: igual ao padrão, mas usa apenas ferramentas predefinidas (ijar, singlejar).
  • NONPREBUILT_TOOLCHAIN_CONFIGURATION: o mesmo que o padrão, mas todas as ferramentas são criados a partir de origens. Isso pode ser útil em sistemas operacionais libc)

Como configurar sinalizações do compilador Java e JVM

Você pode configurar as sinalizações JVM e javac com ou com flags default_java_toolchain.

As flags relevantes são --jvmopt, --host_jvmopt, --javacopt e --host_javacopt.

Os atributos default_java_toolchain relevantes são javacopts, jvm_opts, javabuilder_jvm_opts e turbine_jvm_opts.

Configuração de flags do compilador Java específicas do pacote

É possível configurar diferentes flags do compilador Java para arquivos de origem específicos usando o atributo package_configuration de default_java_toolchain. Confira o exemplo abaixo.

load("@bazel_tools//tools/jdk:default_java_toolchain.bzl", "default_java_toolchain")

# This is a convenience macro that inherits values from Bazel's default java_toolchain
default_java_toolchain(
    name = "toolchain",
    package_configuration = [
        ":error_prone",
    ],
    visibility = ["//visibility:public"],
)

# This associates a set of javac flags with a set of packages
java_package_configuration(
    name = "error_prone",
    javacopts = [
        "-Xep:MissingOverride:ERROR",
    ],
    packages = ["error_prone_packages"],
)

# This is a regular package_group, which is used to specify a set of packages to apply flags to
package_group(
    name = "error_prone_packages",
    packages = [
        "//foo/...",
        "-//foo/bar/...", # this is an exclusion
    ],
)

Várias versões do código-fonte Java em um único repositório

Ele só aceita a compilação de uma única versão de fontes Java em um build. ser construído. Isso significa que, ao criar um teste ou um aplicativo Java, todas as dependências são criadas com base na mesma versão do Java.

No entanto, builds separados podem ser executados usando flags diferentes.

Para facilitar o uso de flags diferentes, os conjuntos de flags de uma versão específica podem ser agrupados com as configurações .bazelrc:

build:java8 --java_language_version=8
build:java8 --java_runtime_version=local_jdk_8
build:java11 --java_language_version=11
build:java11 --java_runtime_version=remotejdk_11

Essas configurações podem ser usadas com a flag --config, por exemplo bazel test --config=java11 //:java11_test.