O Bazel tem suporte sofisticado para modelar plataformas e toolchains para builds de várias arquiteturas e cross-compilados.
Esta página resume o estado desse suporte.
Consulte também:
Status
C++
As regras do C++ usam plataformas para selecionar toolchains quando
--incompatible_enable_cc_toolchain_resolution
está definido.
Isso significa que é possível 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 seu projeto em C++ com plataformas, consulte Migrar seu projeto e Configurar toolchains em C++.
Java
As regras do Java usam plataformas para selecionar toolchains.
Isso substitui as flags 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 toolchains quando
--incompatible_enable_android_toolchain_resolution
está definido.
Isso significa que você pode configurar um projeto do Android com:
bazel build //:my_android_project --android_platforms=//:my_android_platform
em vez de usar flags legadas como --android_crosstool_top
, --android_cpu
e --fat_apk_cpu
.
Isso será ativado por padrão no Bazel 7.0 (#16285).
Para testar seu projeto do Android com plataformas, consulte Migrar seu projeto.
Apple
As regras da Apple não são compatíveis com plataformas e ainda não têm suporte programado.
Você ainda pode usar APIs de plataforma com builds da Apple (por exemplo, ao criar com uma mistura de regras da Apple e C++ puro) com mapeamentos de plataforma.
Outros idiomas
- As regras de Go oferecem suporte total a plataformas
- As regras do Rust oferecem suporte total a plataformas.
Se você tem um conjunto de regras de idioma, consulte Migrar seu conjunto de regras para adicionar suporte.
Contexto
As plataformas e os toolchains foram introduzidos para padronizar como os projetos de software visam diferentes arquiteturas e fazem a compilação cruzada.
Isso foi inspirado na observação de que os mantenedores de idiomas já faziam isso de maneiras ad hoc e incompatíveis. Por exemplo, as regras do C++ usavam --cpu
e --crosstool_top
para declarar uma CPU e uma cadeia de ferramentas de destino. Nenhum deles modela corretamente uma "plataforma". Isso produzia builds estranhos e incorretos.
Java, Android e outras linguagens desenvolveram suas próprias flags para fins semelhantes, mas nenhuma delas interoperava entre si. Isso tornava as criações entre linguagens confusas e complicadas.
O Bazel é destinado a projetos grandes, multilíngues e multiplataforma. Isso exige um suporte mais fundamentado para esses conceitos, incluindo uma API padrão clara.
Necessidade de migração
Para fazer upgrade para a nova API, é necessário fazer duas coisas: lançar a API e atualizar a lógica de regra para usá-la.
A primeira foi concluída, mas a segunda ainda está em andamento. Isso consiste em garantir que
plataformas e cadeias de ferramentas específicas do idioma sejam definidas, que a lógica de linguagem leia
cadeias de ferramentas pela nova API em vez de flags antigas, como --crosstool_top
, e que
config_setting
s selecionem a nova API em vez de flags antigas.
Esse trabalho é simples, mas exige um esforço distinto para cada idioma, além de um aviso justo para que os proprietários de projetos testem as próximas mudanças.
Por isso, essa é uma migração contínua.
Meta
A 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 seu projeto escolhem as cadeias de ferramentas certas para
//:myplatform
. - As dependências do projeto escolhem as toolchains certas 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
. //:myplatform
é definido em um lugar claro e acessível: no repositório do seu projeto, se a plataforma for exclusiva dele, ou em um lugar comum em que todos os projetos consumidores possam encontrá-lo.
As flags antigas, como --cpu
, --crosstool_top
e --fat_apk_cpu
, serão
descontinuadas e removidas assim que for seguro fazer isso.
Em última análise, essa será a única maneira de configurar arquiteturas.
Migrar seu projeto
Se você criar com linguagens que oferecem suporte a plataformas, a build já vai funcionar com uma invocação como:
bazel build //:myproject --platforms=//:myplatform
Consulte Status e a documentação da sua linguagem para mais detalhes.
Se um idioma exigir uma flag para ativar o suporte da plataforma, você também precisará definir essa flag. Consulte Status para mais detalhes.
Para que o projeto seja criado, verifique o seguinte:
//:myplatform
precisa existir. Em geral, é responsabilidade do proprietário do projeto definir as plataformas, já que projetos diferentes têm como destino máquinas diferentes. Consulte Plataformas padrão.As toolchains que você quer usar precisam existir. Se você estiver usando toolchains padrão, os proprietários de idiomas precisarão incluir instruções sobre como registrá-las. Se você estiver criando suas próprias toolchains personalizadas, registre-as no arquivo
MODULE.bazel
ou com--extra_toolchains
.select()
s e transições de configuração precisam ser resolvidas corretamente. Consulte select() e Transições.Se o build misturar linguagens que oferecem e não oferecem suporte a plataformas, talvez seja necessário usar mapeamentos de plataforma para ajudar as linguagens legadas a funcionar 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 para descrever as arquiteturas que querem criar. Elas são acionadas com --platforms
.
Quando --platforms
não está definido, o Bazel usa um platform
padrão que representa a máquina de build local. Ele é gerado automaticamente em @platforms//host
(com alias @bazel_tools//tools:host_platform
), então não é necessário defini-lo explicitamente. Ele mapeia o OS
e o 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 o select()
seja compatível com a maior variedade possível de máquinas. Uma biblioteca com fontes específicas de ARM
precisa ser compatível com todas as máquinas com tecnologia ARM
, a menos que haja um motivo para ser mais específica.
Para selecionar em um ou mais constraint_value
s, use:
config_setting(
name = "is_arm",
constraint_values = [
"@platforms//cpu:arm",
],
)
Isso é equivalente a selecionar tradicionalmente em --cpu
:
config_setting(
name = "is_arm",
values = {
"cpu": "arm",
},
)
Confira mais detalhes aqui.
Os select
s em --cpu
, --crosstool_top
etc. não entendem --platforms
.
Ao migrar seu projeto para plataformas, é necessário convertê-los para
constraint_values
ou usar mapeamentos de plataforma para oferecer suporte
aos dois estilos durante a migração.
Transições
As transições do Starlark mudam
flags em partes do seu gráfico de build. Se o projeto usar uma transição que
defina --cpu
, --crossstool_top
ou outras flags legadas, as regras que leem
--platforms
não vão detectar essas mudanças.
Ao migrar seu projeto para plataformas, é necessário converter mudanças como
return { "//command_line_option:cpu": "arm" }
para return {
"//command_line_option:platforms": "//:my_arm_platform" }
ou usar mapeamentos de
plataforma para oferecer suporte aos dois estilos durante a migração.
window.
Migrar seu conjunto de regras
Se você tem um conjunto de regras e quer oferecer suporte a plataformas, faça o seguinte:
Faça com que a lógica de regra resolva toolchains com a API toolchain. Consulte a API de cadeia de ferramentas (
ctx.toolchains
).Opcional: defina uma flag
--incompatible_enable_platforms_for_my_language
para que a lógica da regra resolva alternadamente as toolchains pela nova API ou flags 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 toolchains padrão e deixe-as acessíveis aos usuários seguindo as instruções de registro da sua regra (detalhes).
Verifique se
select()
s e transições de configuração são compatíveis com plataformas. Esse é o maior desafio. Isso é particularmente difícil para projetos multilíngues, que podem falhar se todos os idiomas não puderem ler--platforms
.
Se você precisar combinar com regras que não oferecem suporte a plataformas, talvez precise de mapeamentos de plataforma para preencher a lacuna.
Propriedades comuns da plataforma
Propriedades comuns e multiplataforma, como OS
e CPU
, precisam ser
declaradas em @platforms
.
Isso incentiva o compartilhamento, a padronização e a compatibilidade entre linguagens.
As propriedades exclusivas das suas regras precisam ser declaradas no repositório delas. Isso permite manter uma propriedade clara sobre os conceitos específicos de que suas regras são responsáveis.
Se as regras usarem SOs ou CPUs de uso personalizado, elas precisarão ser declaradas no repositório da regra em vez de @platforms
.
Mapeamentos de plataforma
Mapeamentos de plataforma é uma API temporária que permite que a lógica compatível com a plataforma seja combinada com a lógica legada na mesma build. Essa é uma ferramenta simples destinada apenas a suavizar incompatibilidades com diferentes períodos de migração.
Um mapeamento de plataforma é um mapa de um platform()
para um
conjunto correspondente de flags legadas ou o contrário. 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
O Bazel usa isso para garantir que todas as configurações, baseadas em plataforma e legadas, sejam aplicadas de maneira consistente em todo o build, incluindo transições.
Por padrão, o Bazel lê mapeamentos do arquivo platform_mappings
na raiz do espaço de trabalho. Também é possível definir
--platform_mappings=//:my_custom_mapping
.
Consulte o design de mapeamentos de plataforma para mais detalhes.
Revisão da API
Um platform
é um conjunto de constraint_value
segmentações:
platform(
name = "myplatform",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:arm",
],
)
Um constraint_value
é uma propriedade da máquina. 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",
)
Um toolchain
é uma regra do Starlark. Os atributos dele 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.
As toolchains declaram os constraint_value
s das máquinas que podem segmentar (target_compatible_with = ["@platforms//os:linux"]
) e as máquinas em que as ferramentas podem ser executadas (exec_compatible_with = ["@platforms//os:mac"]
).
Ao criar $ bazel build //:myproject --platforms=//:myplatform
, o Bazel
seleciona automaticamente uma cadeia de ferramentas que pode ser executada na máquina de build e
criar binários para //:myplatform
. Isso é conhecido como resolução da cadeia de ferramentas.
O conjunto de toolchains disponíveis pode ser registrado no arquivo MODULE.bazel
com register_toolchains
ou na
linha de comando com --extra_toolchains
.
Perguntas
Para suporte geral e dúvidas sobre o cronograma de migração, entre em contato com bazel-discuss ou os proprietários das regras adequadas.
Para discussões sobre o design e a evolução das APIs da plataforma/cadeia de ferramentas, entre em contato com bazel-dev.