O Bazel tem suporte sofisticado para a modelagem de plataformas e conjuntos de ferramentas para multiarquitetura e builds de compilação cruzada.
Esta página resume o estado desse suporte.
Consulte também:
Status
C++
As regras do C++ usam plataformas para selecionar conjuntos de ferramentas quando
--incompatible_enable_cc_toolchain_resolution
está definido.
Isso significa que é possível 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 em C++ com plataformas, consulte Como migrar o projeto e Como configurar os 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 os detalhes em Java e Bazel.
Android
As regras do Android usam plataformas para selecionar conjuntos de ferramentas quando
--incompatible_enable_android_toolchain_resolution
é definido.
Isso significa que é possível 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 Android com plataformas, consulte Como migrar seu projeto.
Apple
As regras da Apple não oferecem suporte a plataformas e ainda não foram programadas para receber suporte.
Ainda é possível 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 do Go oferecem suporte total a plataformas
- As regras do Rust têm suporte total a plataformas.
Se você for proprietário de um conjunto de regras de idioma, consulte Como migrar o conjunto de regras para adicionar suporte.
Contexto
Foram introduzidos conjuntos de ferramentas e plataformas para padronizar a forma como os projetos de software visam arquiteturas diferentes e fazer 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++ usaram --cpu
e --crosstool_top
para declarar uma CPU de destino e um conjunto de ferramentas. Nenhuma dessas opções modela corretamente uma "plataforma". Isso produzia 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 em várias linguagens confusos e complicados.
O Bazel é destinado a projetos grandes, com várias linguagens e várias plataformas. Isso exige suporte mais fundamentado para 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 conjuntos de ferramentas específicos da linguagem sejam definidos, que a lógica da linguagem leia os conjuntos de ferramentas usando a nova API em vez de sinalizações antigas, como --crosstool_top
, e config_setting
s selecionem na 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 de projetos testem as próximas mudanças.
Por isso, essa migração está em andamento.
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 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
. //:myplatform
é definido em um local claro e acessível: no repositório do seu projeto, se a plataforma for exclusiva do projeto, ou em algum lugar comum para que todos os projetos de consumo 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ê usar linguagens que oferecem suporte a plataformas, seu build já vai funcionar com uma invocação como esta:
bazel build //:myproject --platforms=//:myplatform
Consulte o Status e a documentação da sua linguagem para conferir detalhes precisos.
Se um idioma exigir uma sinalização para ativar o suporte à plataforma, você também precisará defini-la. Consulte o Status para saber mais.
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.Os conjuntos de ferramentas que você quer usar precisam existir. Se você estiver usando conjuntos de ferramentas de banco de ferramentas, os proprietários da linguagem precisarão incluir instruções sobre como registrá-los. 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 resolvidas corretamente. Consulte select() e Transitions.Se o build combinar 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 para as quais querem criar. Em seguida, 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 @platforms//host
(alias de
@bazel_tools//tools:host_platform
),
portanto, 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
destinos constraint_value
, mas não podem concluir
plataformas. Isso é intencional para que select()
seja compatível com a maior variedade 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 um motivo para ser mais específico.
Para selecionar em um ou mais constraint_value
s, use:
config_setting(
name = "is_arm",
constraint_values = [
"@platforms//cpu:arm",
],
)
Isso equivale a selecionar tradicionalmente --cpu
:
config_setting(
name = "is_arm",
values = {
"cpu": "arm",
},
)
Confira mais detalhes neste link.
select
s no --cpu
, --crosstool_top
etc. não entendem --platforms
.
Ao migrar seu projeto para as plataformas, você precisa convertê-las em
constraint_values
ou usar mapeamentos de plataforma para oferecer suporte
aos dois estilos durante a migração.
Transições
As transições Starlark mudam
as sinalizações para partes do seu 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 terão essas mudanças.
Ao migrar seu projeto para plataformas, é necessário 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 a ambos os estilos durante a migração.
.
Migrando seu conjunto de regras
Se você tem um grupo de regras e quer oferecer suporte a plataformas, precisa:
Fazer com que a lógica de regras resolva os conjuntos de ferramentas com a API correspondente. Consulte 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.
Definir os conjuntos de ferramentas padrão e torná-los acessíveis aos usuários por meio das instruções de registro da regra (detalhes)
Verifique se as
select()
s e as transições de configuração oferecem suporte a plataformas. Esse é o maior desafio. Isso é particularmente desafiador para projetos com várias linguagens, que pode falhar se todos os idiomas não puderem ler--platforms
.
Se você precisar misturar regras sem suporte a plataformas, talvez seja necessário usar mapeamentos de plataforma para preencher a lacuna.
Propriedades comuns da plataforma
As 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 linguagens.
As propriedades exclusivas das suas regras precisam ser declaradas no repositório delas. Isso permite que você mantenha uma propriedade clara sobre os 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 combinar lógicas com reconhecimento de plataforma com a lógica legada no mesmo build. Essa é uma ferramenta sem fio destinada apenas a suavizar 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 vice-versa. 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, sejam baseadas na plataforma ou legadas, sejam aplicadas de maneira consistente em toda a compilação, inclusive por meio de transições.
Por padrão, o Bazel lê os 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
destinos constraint_value
:
platform(
name = "myplatform",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:arm",
],
)
Uma constraint_value
é uma propriedade de 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",
)
Uma toolchain
é uma regra 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.
Os conjuntos de ferramentas declaram os constraint_value
s de máquinas em 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 um conjunto de ferramentas que pode ser executado na máquina de build 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 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 ver discussões sobre o design e a evolução das APIs de plataforma/conjunto de ferramentas, entre em contato com bazel-dev (link em inglês).