O Bazel tem suporte sofisticado para modelagem de plataformas e toolchains para builds de várias arquiteturas e com compilação cruzada.
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 você pode configurar um projeto C++ com:
bazel build //:my_cpp_project --platforms=//:myplatform
em vez da legada:
bazel build //:my_cpp_project` --cpu=... --crosstool_top=... --compiler=...
Isso será ativado por padrão no Bazel 7.0 (#7260).
Para testar seu projeto C++ com plataformas, consulte Como migrar seu projeto e Como configurar toolchains C++.
Java
As regras do Java usam plataformas para selecionar as cadeias de ferramentas.
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 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 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 seu projeto do 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.
Ainda é possível usar APIs de plataforma com builds da Apple (por exemplo, ao criar com uma mistura de regras da Apple e C++) com mapeamentos de plataforma.
Outros idiomas
- As regras do Go oferecem suporte total às plataformas
- As regras do Rust oferecem suporte total às plataformas.
Se você tiver um conjunto de regras de idioma, consulte Como migrar seu conjunto de regras para adicionar suporte.
Contexto
Plataformas e toolchains foram introduzidos para padronizar como os projetos de software visam diferentes arquiteturas e fazem a compilação cruzada.
Isso foi inspirado pela observação de que os mantenedores de linguagem já estavam fazendo 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. Nenhuma dessas opções modela corretamente uma "plataforma". Isso produziu builds estranhos e incorretos.
Java, Android e outras linguagens evoluíram as próprias sinalizações para fins semelhantes, nenhuma das quais interoperou entre si. Isso tornou os builds entre idiomas confusos e complicados.
O Bazel é destinado a projetos grandes, multilíngues e multiplataforma. Isso exige mais suporte a esses conceitos, incluindo uma API padrão clara.
Necessidade de migração
O upgrade para a nova API requer dois esforços: lançar a API e fazer upgrade da lógica de regras para usá-la.
A primeira foi concluída, mas a segunda ainda está em andamento. Isso consiste em garantir
que plataformas e toolchains específicos da linguagem sejam definidos, que a lógica da linguagem leia
toolchains pela nova API em vez de flags antigas, como --crosstool_top
, e
que config_setting
s sejam selecionados na nova API em vez de flags antigas.
Esse trabalho é simples, mas requer 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 que essa é uma migração contínua.
Meta
Essa migração é concluída quando todos os projetos são 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 seu projeto escolhem as cadeias de ferramentas certas para
//:myplatform
. //:myplatform
faz referência a declarações comuns deCPU
,OS
e outras propriedades genéricas independentes do idioma- Todos os
select()
s relevantes correspondem corretamente a//:myplatform
. //:myplatform
é definido em um local claro e acessível: no repositório do projeto, se a plataforma for exclusiva para o projeto, ou em algum lugar comum que todos os projetos que consomem possam encontrar.
As flags antigas, como --cpu
, --crosstool_top
e --fat_apk_cpu
, serão
descontinuadas e removidas assim que for seguro fazer isso.
Essa será a única forma de configurar arquiteturas.
Como migrar seu projeto
Se você usar linguagens que oferecem suporte a plataformas, seu build já vai funcionar com uma invocação como esta:
bazel build //:myproject --platforms=//:myplatform
Consulte Status e a documentação do idioma para saber mais detalhes.
Se um idioma exigir uma flag para ativar o suporte à plataforma, você também precisará definir essa flag. 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 têm como alvo máquinas diferentes. Consulte Plataformas padrão.As cadeias de ferramentas que você quer usar precisam existir. Se você estiver usando toolchains padrão, os proprietários da linguagem precisam incluir instruções sobre como fazer o registro. Se estiver criando seus próprios conjuntos de ferramentas personalizados, você precisará register no
WORKSPACE
ou com--extra_toolchains
.select()
s e transições de configuração precisam ser resolvidos corretamente. Consulte select() e Transições.Se seu build mistura linguagens que têm e não suporte a plataformas, talvez seja necessário mapeamentos de plataforma para ajudar as linguagens legadas a funcionarem 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 eles querem criar. Elas são acionadas com --platforms
.
Quando --platforms
não está definido, o padrão do Bazel é definido como um platform
que representa a
máquina de build local. Isso é gerado automaticamente em @local_config_platform//:host
,
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
de destino, mas não em plataformas
completas. Isso é intencional para que select()
ofereça suporte a
máquinas o mais variado possível. Uma biblioteca com fontes específicas de ARM
precisa oferecer suporte a todas
máquinas ARM
, a menos que haja um motivo para ser mais específico.
Para selecionar um ou mais constraint_value
s, use:
config_setting(
name = "is_arm",
constraint_values = [
"@platforms//cpu:arm",
],
)
Isso é equivalente à seleção tradicional em --cpu
:
config_setting(
name = "is_arm",
values = {
"cpu": "arm",
},
)
Mais detalhes aqui.
select
s em --cpu
, --crosstool_top
etc. não entendem --platforms
.
Ao migrar seu projeto para plataformas, é necessário convertê-lo 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 flags para partes do gráfico de build. Se o projeto usar uma transição que
define --cpu
, --crossstool_top
ou outras flags legadas, as regras que leem
--platforms
não vão notar 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.
janela.
Migrar o conjunto de regras
Se você tiver um conjunto de regras e quiser oferecer suporte a plataformas, faça o seguinte:
Use a lógica de regra para resolver cadeias de ferramentas com a API toolchain. 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 alternativamente os conjuntos de ferramentas usando a nova API ou 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 toolchains padrão e torne-as acessíveis aos usuários pelas instruções de registro da regra (detalhes).
Verifique se as
select()
s e as transições de configuração são compatíveis com as plataformas. Esse é o maior desafio. Isso é particularmente desafiador para projetos multilíngues, que podem falhar se todos os idiomas não conseguirem ler--platforms
.
Se você precisar misturar com regras que não oferecem suporte a plataformas, talvez seja necessário usar mapeamentos de plataforma para preencher a lacuna.
Propriedades comuns da plataforma
Propriedades comuns de plataformas 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 delas. Isso permite que você mantenha a propriedade clara dos conceitos específicos pelos quais suas regras são responsáveis.
Se as regras usam CPUs ou SOs personalizados, elas precisam ser declaradas no
repositório da regra, em vez de
@platforms
.
Mapeamentos de plataforma
Os mapeamentos de plataforma são uma API temporária que permite que a lógica compatível com a plataforma seja combinada com a lógica legada no mesmo build. Essa é uma ferramenta simples que tem como objetivo suavizar incompatibilidades com diferentes períodos de migração.
Um mapeamento de plataforma é um mapeamento de um platform()
para um
conjunto correspondente de flags legados 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
O Bazel usa isso para garantir que todas as configurações, baseadas na plataforma e legado, sejam aplicadas de forma 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
é uma coleção de
alvo constraint_value
:
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",
)
Um toolchain
é uma regra do Starlark. Os
atributos 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 cadeias de ferramentas declaram as constraint_value
s de máquinas que podem
ser direcionadas
(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 um conjunto de ferramentas que pode ser executado na máquina de build e
criar binários para //:myplatform
. Isso é conhecido como resolução de toolchain.
O conjunto de toolchains disponíveis pode ser registrado no WORKSPACE
com
register_toolchains
ou na
linha de comando com --extra_toolchains
.
Clique aqui para mais informações.
Perguntas
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 da plataforma/ferramenta, entre em contato com o bazel-dev.