Esta página contém recursos que ajudam você a usar o Bazel com projetos Java. Ela contém um link para um tutorial, regras de build e outras informações específicas para criar 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 seus projetos Java com o Maven, siga as etapas no guia de migração para começar a criar projetos do Maven com o Bazel:
Versões do Java
Há duas versões relevantes do Java definidas com flags de configuração:
- a versão dos arquivos de origem no repositório
- a versão do ambiente de execução do Java usada para executar e testar o código
Como configurar a versão do código-fonte no repositório
Sem uma configuração adicional, o Bazel pressupõe que todos os arquivos de origem Java no repositório sejam gravados em uma única versão do Java. Para especificar a versão das
origens no repositório, adicione build --java_language_version={ver} ao
.bazelrc arquivo, em que {ver} é, por exemplo, 11. Os proprietários do repositório do Bazel precisam definir essa flag para que o Bazel e os usuários possam referenciar o número da versão Java do código-fonte. Para mais detalhes, consulte a
flag de versão da linguagem Java.
Como 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 ele faz o download e executa e testa o código com a JVM instalada na máquina local. O Bazel pesquisa a JVM usando JAVA_HOME ou o caminho.
Os binários resultantes são compatíveis com a JVM instalada localmente nas bibliotecas do sistema, o que significa que os binários resultantes dependem do que está instalado na máquina.
Para configurar a JVM usada para execução e teste, use a flag --java_runtime_version. O valor padrão é local_jdk.
Teste e compilação herméticos
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 transferida por download de um repositório remoto. Para mais detalhes, consulte
a flag de versão do ambiente de execução do Java.
Como configurar a compilação e a execução de ferramentas de build no Java
Há um segundo par de JDK e JVM usado para criar e executar ferramentas, que são usadas no processo de build, mas não nos resultados do build. Esse JDK e a JVM são controlados usando --tool_java_language_version e --tool_java_runtime_version. Os valores padrão são 11 e remotejdk_11,
respectivamente.
Como compilar usando o JDK instalado localmente
O Bazel compila por padrão usando o JDK remoto, porque ele substitui os internos do JDK. Os conjuntos de ferramentas de compilação que usam o JDK instalado localmente são configurados, mas não usados.
Para compilar usando o JDK instalado localmente, ou seja, usar os conjuntos de ferramentas de compilação para o JDK local, use a flag adicional --extra_toolchains=@local_jdk//:all. No entanto, isso pode não funcionar no JDK de fornecedores arbitrários.
Para mais detalhes, consulte Como configurar conjuntos de ferramentas Java.
Práticas recomendadas
Além das práticas recomendadas gerais do Bazel, confira abaixo as 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 arquivos BUILD:
Use um arquivo
BUILDpor diretório que contenha origens Java, porque isso melhora o desempenho do build.Cada arquivo
BUILDprecisa conter uma regrajava_librarysemelhante a esta:java_library( name = "directory-name", srcs = glob(["*.java"]), deps = [...], )O nome da biblioteca precisa ser o nome do diretório que contém o arquivo
BUILD. Isso torna o rótulo da biblioteca mais curto, ou seja, use"//package"em vez de"//package:package".As origens precisam ser um
globde todos os arquivos Java no diretório.Os testes precisam estar em um diretório correspondente em
src/teste depender dessa biblioteca.
Como criar novas regras para builds avançados do Java
Observação: a criação de novas regras é para cenários avançados de build e teste. Não é necessário ao começar a usar o Bazel.
Os módulos, fragmentos de configuração e provedores a seguir ajudam você a estender os recursos do Bazel ao criar projetos Java:
- Módulo principal do Java:
java_common - Provedor principal do Java:
JavaInfo - Fragmento de configuração:
java Outros módulos:
Como configurar os conjuntos de ferramentas Java
O Bazel usa dois tipos de conjuntos de ferramentas 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 conjuntos de ferramentas de execução adicionais
O conjunto 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 regras de repositório local_java_repository ou remote_java_repository em uma extensão de módulo. A adição da regra disponibiliza a JVM usando uma flag. Quando várias definições são fornecidas para o mesmo sistema operacional e arquitetura de CPU, a primeira é usada.
Exemplo de configuração da JVM local em MODULE.bazel:
custom_jdk = use_extension("@rules_java//java:extensions.bzl", "java_repository")
custom_jdk.local(
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
)
use_repo(custom_jdk, "additionaljdk")
register_toolchains("@additionaljdk//:all")
Exemplo de configuração da JVM remota:
custom_jdk = use_extension("@rules_java//java:extensions.bzl", "java_repository")
custom_jdk.remote(
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 = ...
)
use_repo(custom_jdk, "openjdk_canary_linux_arm", "openjdk_canary_linux_arm_toolchain_config_repo")
register_toolchains("@openjdk_canary_linux_arm_toolchain_config_repo//:all")
Como configurar conjuntos de ferramentas de compilação adicionais
O conjunto de ferramentas de compilação é composto pelo JDK e várias ferramentas que o Bazel usa durante a compilação e que fornecem recursos adicionais, como: Error Prone, dependências Java estritas, compilação de cabeçalho, simplificação do Android, instrumentação de cobertura e tratamento de genclass para IDEs.
O JavaBuilder é uma ferramenta agrupada do Bazel que executa a compilação e fornece os recursos mencionados acima. A compilação real é executada usando o compilador interno do JDK. O JDK usado para compilação é especificado pelo atributo java_runtime do conjunto de ferramentas.
O Bazel substitui alguns internos do JDK. No caso da 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 a flag -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 nenhum dos conjuntos de ferramentas integrados.
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 as assinaturas de chamada. Os jars resultantes são chamados de jars de cabeçalho. Eles são usados para melhorar a incrementalidade da compilação, recompilando apenas dependentes downstream 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 que contém apenas os arquivos de classe para origens geradas por processadores de anotação.
A ferramenta JacocoRunner executa o Jacoco em arquivos instrumentados e gera resultados no formato LCOV.
A ferramenta TestRunner executa testes JUnit 4 em um ambiente controlado.
É possível reconfigurar a compilação adicionando default_java_toolchain macro a
um arquivo BUILD e registrando-o adicionando a regra register_toolchains ao
arquivo MODULE.bazel ou usando
--extra_toolchains flag.
O conjunto de ferramentas só é usado quando o atributo source_version corresponde ao valor especificado pela flag --java_language_version.
Exemplo de configuração do conjunto de ferramentas:
load(
"@rules_java//toolchains: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 = "@rules_java//toolchains: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, compatível com versões do JDK >= 9VANILLA_TOOLCHAIN_CONFIGURATION: sem recursos adicionais, compatível com JDKs de fornecedores arbitrários.PREBUILT_TOOLCHAIN_CONFIGURATION: igual ao padrão, mas usa apenas ferramentas pré-criadas (ijar,singlejar)NONPREBUILT_TOOLCHAIN_CONFIGURATION: igual ao padrão, mas todas as ferramentas são criadas a partir de origens (isso pode ser útil em sistemas operacionais com libc diferentes)
Como configurar flags de compilador JVM e Java
É possível configurar flags de JVM e javac com flags ou com
default_java_toolchain atributos.
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 de compilador Java específicas do pacote
É possível configurar diferentes flags de compilador Java para arquivos de origem específicos usando o atributo package_configuration de default_java_toolchain.
Consulte o exemplo abaixo.
load("@rules_java//toolchains: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
O Bazel só oferece suporte à compilação de uma única versão de origens Java em um build. Isso significa que, ao criar um teste ou um aplicativo Java, todas as dependências são criadas na mesma versão do Java.
No entanto, builds separados podem ser executados usando flags diferentes.
Para facilitar a tarefa de usar flags diferentes, conjuntos de flags para uma versão específica podem ser agrupados com 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 --config flag, por exemplo
bazel test --config=java11 //:java11_test.