O Bazel tem suporte sofisticado à modelagem de plataformas e conjuntos de ferramentas para várias arquiteturas e builds de compilação cruzada.
Esta página resume o estado desse suporte.
Consulte também:
Status
C++
As regras C++ usam plataformas para selecionar conjuntos de ferramentas quando --incompatible_enable_cc_toolchain_resolution
está definido.
Isso significa que você pode configurar um projeto em C++ com:
bazel build //:my_cpp_project --platforms=//:myplatform
em vez do legado:
bazel build //:my_cpp_project` --cpu=... --crosstool_top=... --compiler=...
Isso será ativado por padrão no Bazel 7.0 (#7260).
Para testar o projeto em C++ com plataformas, consulte Como migrar seu projeto e Como configurar conjuntos de ferramentas do C++.
Java
As regras Java usam plataformas para selecionar conjuntos de ferramentas.
Isso substitui as sinalizações legadas --java_toolchain
, --host_java_toolchain
, --javabase
e --host_javabase
.
Consulte Java e Bazel para mais detalhes.
Android
As regras do Android usam plataformas para selecionar conjuntos de ferramentas quando
--incompatible_enable_android_toolchain_resolution
é definido.
Isso significa que você pode configurar um projeto Android com:
bazel build //:my_android_project --android_platforms=//:my_android_platform
em vez de com sinalizações legadas, como --android_crosstool_top
, --android_cpu
e --fat_apk_cpu
.
Isso será ativado por padrão no Bazel 7.0 (#16285).
Para testar o projeto Android com plataformas, consulte Como migrar seu projeto.
Apple
As regras da Apple não são compatíveis com plataformas e ainda não estão programadas para suporte.
Você ainda pode usar APIs de plataforma com builds da Apple (por exemplo, ao criar com uma combinação de regras da Apple e C++ puro) com mapeamentos de plataforma.
Outros idiomas
- As regras Go são totalmente compatíveis com plataformas
- As regras do Rust oferecem suporte total a plataformas.
Se você tiver um conjunto de regras de idioma, consulte Como migrar seu conjunto de regras para adicionar suporte.
Contexto
Plataformas e conjuntos de ferramentas foram introduzidos para padronizar a forma como os projetos de software são direcionados a diferentes arquiteturas e fazem compilação cruzada.
Isso foi inspirado pela observação de que os mantenedores de idioma já estavam fazendo isso de maneiras ad hoc e incompatíveis. Por exemplo, as regras C++ usaram --cpu
e --crosstool_top
para declarar uma CPU e um conjunto de ferramentas de destino. Nenhuma dessas opções modela corretamente uma "plataforma". Isso produziu builds estranhos e incorretos.
Java, Android e outras linguagens desenvolveram as próprias flags para fins semelhantes, nenhuma interoperada entre si. Isso tornava os builds entre linguagens confusos e complicados.
Ele é destinado a projetos grandes, em vários idiomas e em várias plataformas. Isso exige um suporte mais baseado em princípios para esses conceitos, incluindo uma API padrão clara.
Necessidade de migração
O upgrade para a nova API requer dois esforços: liberar a API e atualizar a lógica da regra para usá-la.
A primeira já foi concluída, mas a segunda está em andamento. Isso consiste em garantir que plataformas e conjuntos de ferramentas específicos da linguagem sejam definidos, a lógica da linguagem lê os conjuntos de ferramentas usando a nova API em vez de sinalizações antigas, como --crosstool_top
, e config_setting
s selecionem a nova API em vez de sinalizações antigas.
Esse trabalho é simples, mas requer um esforço distinto para cada idioma, além de um aviso justo para que os proprietários do projeto testem as próximas mudanças.
É por isso que essa é uma migração em andamento.
Meta
Essa migração será concluída quando todos os projetos forem criados com o formulário:
bazel build //:myproject --platforms=//:myplatform
Isso implica:
- As regras do projeto escolhem os conjuntos de ferramentas certos para
//:myplatform
. - As dependências do projeto escolhem os conjuntos de ferramentas certos para
//:myplatform
. //:myplatform
faz referência a declarações comuns deCPU
,OS
e outras propriedades genéricas e independentes de linguagem.- Todos os
select()
s relevantes correspondem corretamente a//:myplatform
. - O
//:myplatform
é definido em um local claro e acessível: no repositório do seu projeto se a plataforma for exclusiva dele, ou em algum lugar comum em que todos os projetos consumidores possam encontrá-la.
Sinalizações antigas, como --cpu
, --crosstool_top
e --fat_apk_cpu
, serão
descontinuadas e removidas assim que for seguro.
Essa será a única maneira de configurar arquiteturas.
Como migrar seu projeto
Se você criar com linguagens compatíveis com plataformas, seu build já funcionará com uma invocação como:
bazel build //:myproject --platforms=//:myplatform
Consulte o Status e a documentação do seu idioma para ver detalhes precisos.
Se uma linguagem exigir uma flag para ativar o suporte à plataforma, também vai ser necessário configurá-la. Consulte Status para mais detalhes.
Para que seu projeto seja criado, verifique o seguinte:
//:myplatform
precisa existir. Geralmente, é responsabilidade do proprietário do projeto definir as plataformas, porque projetos diferentes visam máquinas distintas. Consulte Plataformas padrão.Os conjuntos de ferramentas que você quer usar precisam existir. Se você estiver usando conjuntos de ferramentas de banco de imagens, os proprietários da linguagem precisarão incluir instruções sobre como registrá-los. Se você estiver criando seus próprios conjuntos de ferramentas personalizados, será necessário register no
WORKSPACE
ou com--extra_toolchains
.select()
s e transições de configuração precisam ser resolvidas corretamente. Consulte select() e Transições.Se o build combina linguagens com ou sem suporte a plataformas, talvez os mapeamentos de plataforma sejam necessários para que as linguagens legadas funcionem com a nova API. Consulte Mapeamentos de plataforma para mais detalhes.
Se você ainda tiver problemas, entre em contato para receber suporte.
Plataformas padrão
Os proprietários de projetos precisam definir plataformas explícitas que descrevam as arquiteturas para as quais eles querem criar. Eles são então acionados com --platforms
.
Quando --platforms
não está definido, o Bazel assume como padrão uma platform
que representa a
máquina de build local. Ele é gerado automaticamente em @local_config_platform//:host
,
portanto, não é necessário defini-lo explicitamente. Ele mapeia os OS
e os CPU
da máquina local com constraint_value
s declarados em
@platforms
.
select()
Os projetos podem select()
em
constraint_value
destinos, mas não em plataformas
completas. Isso é intencional para que select()
ofereça suporte ao maior número possível de
máquinas. Uma biblioteca com fontes específicas de ARM
precisa oferecer suporte a todas
as máquinas com tecnologia ARM
, a menos que haja motivo para ser mais específica.
Para selecionar um ou mais constraint_value
s, use:
config_setting(
name = "is_arm",
constraint_values = [
"@platforms//cpu:arm",
],
)
Isso é equivalente a selecionar tradicionalmente no --cpu
:
config_setting(
name = "is_arm",
values = {
"cpu": "arm",
},
)
Confira mais detalhes neste link.
select
s em --cpu
, --crosstool_top
etc. não entendem --platforms
.
Ao migrar seu projeto para plataformas, você precisa convertê-las em
constraint_values
ou usar mapeamentos de plataforma para oferecer suporte
a ambos os estilos durante a migração.
Transições
As transições do Starlark mudam
as sinalizações para partes do gráfico de build. Se o projeto usar uma transição que
defina --cpu
, --crossstool_top
ou outras sinalizações legadas, as regras que leem
--platforms
não verão essas mudanças.
Ao migrar o projeto para plataformas, você precisa converter mudanças como
return { "//command_line_option:cpu": "arm" }
em return {
"//command_line_option:platforms": "//:my_arm_platform" }
ou usar mapeamentos de
plataforma para oferecer suporte aos dois estilos durante a
migração.
Como migrar seu conjunto de regras
Se você possui um conjunto de regras e deseja oferecer suporte a plataformas, você precisa:
Faça com que a lógica de regra resolva os conjuntos de ferramentas com a API de conjunto de ferramentas. Consulte a API do conjunto de ferramentas (
ctx.toolchains
).Opcional: defina uma sinalização
--incompatible_enable_platforms_for_my_language
para que a lógica de regra resolva os conjuntos de ferramentas por meio da nova API ou de sinalizações antigas, como--crosstool_top
, durante o teste de migração.Defina as propriedades relevantes que compõem os componentes da plataforma. Consulte Propriedades comuns da plataforma
Defina conjuntos de ferramentas padrão e torne-os acessíveis aos usuários com as instruções de registro da regra (detalhes).
Verifique se
select()
s e transições de configuração oferecem suporte a plataformas. Esse é o maior desafio. Isso é particularmente desafiador para projetos com vários idiomas, o que pode falhar se todos os idiomas não puderem ler--platforms
.
Se você precisar misturar regras que não são compatíveis com plataformas, talvez seja necessário usar mapeamentos de plataforma para preencher a lacuna.
Propriedades comuns da plataforma
Propriedades comuns da plataforma em vários idiomas, como OS
e CPU
, precisam ser
declaradas em @platforms
.
Isso incentiva o compartilhamento, a padronização e a compatibilidade entre idiomas.
As propriedades exclusivas das suas regras precisam ser declaradas no repositório da regra. Isso permite que você mantenha uma propriedade clara sobre os conceitos específicos pelos quais as regras são responsáveis.
Se as regras usam CPUs ou SOs de finalidade personalizada, eles precisam ser declarados no
repositório da regra em comparação a
@platforms
.
Mapeamentos de plataforma
Os mapeamentos de plataforma são uma API temporária que permite misturar a lógica baseada na plataforma com a legada no mesmo build. Essa é uma ferramenta de corte que se destina apenas a suavizar as incompatibilidades com diferentes períodos de migração.
Um mapeamento de plataforma é um mapa de uma platform()
para um
conjunto correspondente de sinalizações legadas ou o inverso. Exemplo:
platforms:
# Maps "--platforms=//platforms:ios" to "--cpu=ios_x86_64 --apple_platform_type=ios".
//platforms:ios
--cpu=ios_x86_64
--apple_platform_type=ios
flags:
# Maps "--cpu=ios_x86_64 --apple_platform_type=ios" to "--platforms=//platforms:ios".
--cpu=ios_x86_64
--apple_platform_type=ios
//platforms:ios
# Maps "--cpu=darwin_x86_64 --apple_platform_type=macos" to "//platform:macos".
--cpu=darwin_x86_64
--apple_platform_type=macos
//platforms:macos
Ele usa isso para garantir que todas as configurações, tanto baseadas em plataforma quanto legadas, sejam aplicadas de forma consistente em todo o build, inclusive em transições.
Por padrão, o Bazel lê mapeamentos do arquivo platform_mappings
na raiz do seu espaço de trabalho. Você também pode definir
--platform_mappings=//:my_custom_mapping
.
Consulte o design de mapeamentos de plataforma para saber mais detalhes.
Revisão da API
Um platform
é uma coleção de
constraint_value
destinos:
platform(
name = "myplatform",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:arm",
],
)
Um constraint_value
é uma propriedade de
máquina. Os valores do mesmo "tipo" são agrupados em um constraint_setting
comum:
constraint_setting(name = "os")
constraint_value(
name = "linux",
constraint_setting = ":os",
)
constraint_value(
name = "mac",
constraint_setting = ":os",
)
Uma toolchain
é uma regra do Starlark. Os
atributos dela declaram as ferramentas de uma linguagem (como compiler =
"//mytoolchain:custom_gcc"
). Os provedores transmitem
essas informações para regras que precisam ser criadas com essas ferramentas.
Os conjuntos de ferramentas declaram os constraint_value
s das máquinas que podem
direcionar
(target_compatible_with = ["@platforms//os:linux"]
) e as máquinas em que as ferramentas podem
ser executadas
(exec_compatible_with = ["@platforms//os:mac"]
).
Ao compilar $ bazel build //:myproject --platforms=//:myplatform
, o Bazel
seleciona automaticamente um conjunto de ferramentas que pode ser executado na máquina e
binários de build para //:myplatform
. Isso é conhecido como resolução do conjunto de ferramentas.
O conjunto de conjuntos de ferramentas disponíveis pode ser registrado em WORKSPACE
com
register_toolchains
ou na
linha de comando com --extra_toolchains
.
Confira mais informações aqui.
Dúvidas
Para suporte geral e dúvidas sobre o cronograma de migração, entre em contato com bazel-discuss ou com os proprietários das regras apropriadas.
Para discussões sobre o design e a evolução das APIs de plataforma/conjunto de ferramentas, entre em contato com bazel-dev.