O Bazel tem suporte sofisticado à modelagem de plataformas e de ferramentas. Integrar isso a projetos reais exige uma cooperação cuidadosa entre proprietários de código, mantenedores de regras e desenvolvedores principais do Bazel.
Esta página resume o propósito das plataformas e mostra como criar com elas.
tl;dr: as APIs de plataforma e de conjunto de ferramentas do Bazel estão disponíveis, mas não funcionam.
em todos os lugares até que todas as regras de idioma, select()
s e outras referências legadas
sejam atualizados. Esse trabalho é constante. Todos os builds serão baseados em plataforma.
Leia abaixo para ver onde seus builds se encaixam.
Para documentação mais formal, consulte:
Contexto
Plataformas e conjuntos de ferramentas foram introduzidos para padronizar a forma como o software projetos são direcionados a diferentes máquinas e são criados com as ferramentas de linguagem certas.
Essa é uma adição relativamente recente ao Bazel. Ele foi
inspirado
ao observar que os mantenedores de linguagem já estavam fazendo isso em campanhas
de formas incompatíveis e hoc. Por exemplo, as regras de C++ usam --cpu
e --crosstool_top
para definir a CPU de destino e o conjunto de ferramentas do C++ de um build. Nenhum desses modelos corretamente
uma "plataforma". As tentativas históricas de fazer isso causaram builds estranhos e imprecisos.
Esses sinalizadores também não controlam a compilação Java, que evoluiu a própria
interface independente com --java_toolchain
.
O Bazel é destinado a projetos grandes, com várias linguagens e várias plataformas. Isso exige um suporte mais fundamentado para esses conceitos, incluindo APIs claras que incentivar a interoperabilidade da linguagem e do projeto. É isso que essas novas APIs pelas quais
Migração
As APIs de plataforma e de conjunto de ferramentas só funcionam quando os projetos as utilizam. Isso
não é trivial porque a lógica da regra, os conjuntos de ferramentas, as dependências e
select()
s precisam oferecer suporte a elas. Isso exige uma sequência de migração cuidadosa
para manter todos os projetos e dependências funcionando corretamente.
Por exemplo, As regras do C++ são compatíveis com plataformas. Mas as Regras da Apple, não. Seu projeto em C++ pode não se importar com a Apple. Mas outros talvez. Então, Ainda não é seguro ativar plataformas globalmente para todos os builds C++.
O restante desta página descreve essa sequência de migração, além de como e quando em que seus projetos se encaixam.
Meta
A migração da plataforma do Bazel é concluída quando todos os projetos são compilados com o formulário:
bazel build //:myproject --platforms=//:myplatform
Isso implica:
- As regras usadas pelo projeto podem inferir os conjuntos de ferramentas corretos
//:myplatform
: - As regras que as dependências do projeto usam podem inferir os conjuntos de ferramentas corretos.
a partir de
//:myplatform
. - Ou os projetos que dependem do seu oferecem suporte a
//:myplatform
ou sua projeto oferece suporte às APIs legadas (como--crosstool_top
). //:myplatform
referências [declarações comuns][Declaração de plataforma comum]{: .external} deCPU
,OS
e outros conceitos genéricos que oferecem suporte a processos automáticos entre projetos compatibilidade.- Todos os projetos relevantes
select()
entender as propriedades de máquina implícitas por//:myplatform
. - O
//:myplatform
é definido em um local claro e reutilizável: no arquivo se a plataforma for exclusiva do seu projeto. Caso contrário, em algum lugar, todos os projetos que a plataforma pode encontrar.
As APIs antigas serão removidas assim que a meta for alcançada. Isso vai que os projetos usam como padrão para selecionar plataformas e conjuntos de ferramentas.
Devo usar plataformas?
Se você quiser apenas criar ou fazer a compilação cruzada de um projeto, siga as da documentação oficial do projeto.
Se você mantiver um projeto, uma linguagem ou um conjunto de ferramentas, para dar suporte às novas APIs. Se você espera até que a migração global seja concluída ou ativar antecipadamente depende das suas necessidades específicas de valor / custo:
Valor
- Você pode usar
select()
ou escolher conjuntos de ferramentas nas propriedades exatas que quiser em vez de sinalizações codificadas, como--cpu
. Por exemplo, várias CPUs podem oferecer suporte ao mesmo conjunto de instruções. - Builds mais corretos. Se você
select()
com--cpu
no exemplo acima, então: adicione uma nova CPU que ofereça suporte ao mesmo conjunto de instruções, aselect()
. não reconhecerá a nova CPU. No entanto, umselect()
nas plataformas permanece preciso. - Experiência do usuário mais simples. Todos os projetos entendem:
--platforms=//:myplatform
: Não é necessário usar várias versões na linha de comando. - Design de linguagem mais simples. Todas as linguagens compartilham uma API comum para definir conjuntos de ferramentas, usando conjuntos de ferramentas e selecionando o conjunto correto para uma plataforma.
- Os destinos podem ser ignorados na fase de build e teste se forem incompatíveis com a plataforma de destino.
Custos
- Projetos dependentes que ainda não têm suporte a plataformas podem não funcionar automaticamente com o seu.
- Para fazê-los funcionar, você pode precisar de manutenção temporária adicional.
- A coexistência de APIs novas e legadas exige uma orientação do usuário mais cuidadosa para evitar confusão.
- Definições canônicas de propriedades comuns, como
O
OS
e oCPU
ainda estão em evolução e podem exigir mais contribuições iniciais. - As definições canônicas de conjuntos de ferramentas específicos da linguagem ainda estão em evolução pode exigir contribuições iniciais extras.
Revisão da API
Uma platform
é uma coleção de
constraint_value
destinos:
platform(
name = "myplatform",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:arm",
],
)
Um constraint_value
é uma máquina
. Valores do mesmo "tipo" são agrupadas em um mesmo
constraint_setting
constraint_setting(name = "os")
constraint_value(
name = "linux",
constraint_setting = ":os",
)
constraint_value(
name = "mac",
constraint_setting = ":os",
)
Uma toolchain
é uma regra Starlark. Seu
Os atributos declaram as ferramentas de uma linguagem (como compiler =
"//mytoolchain:custom_gcc"
). Os provedores transmitem
essas informações às regras que precisam ser criadas com essas ferramentas.
Os conjuntos de ferramentas declaram os constraint_value
s de máquinas que podem
target
(target_compatible_with = ["@platforms//os:linux"]
) e as máquinas que as ferramentas
executar em
(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 do conjunto de ferramentas.
O conjunto de conjuntos de ferramentas disponíveis pode ser registrado no WORKSPACE
com
register_toolchains
ou no
linha de comando com --extra_toolchains
.
Veja mais detalhes aqui.
Status
A compatibilidade atual com a plataforma varia de acordo com o idioma. Todas as regras principais do Bazel são estão migrando para plataformas. Mas esse processo levará algum tempo. Isso se deve a três motivos principais:
A lógica da regra precisa ser atualizada para receber informações da ferramenta do novo conjunto de ferramentas. API (
ctx.toolchains
) e parar de ler as configurações legadas como--cpu
e--crosstool_top
. Isso é relativamente simples.Os mantenedores das cadeias de ferramentas devem defini-los e torná-los acessíveis aos usuários (em repositórios do GitHub e entradas
WORKSPACE
). É tecnicamente simples, mas precisa ser organizado de maneira inteligente para manter uma experiência do usuário fácil.As definições de plataforma também são necessárias (a menos que você crie para a mesma máquina o Bazel é executado. Geralmente, os projetos precisam definir as próprias plataformas.
É preciso migrar os projetos atuais.
select()
s e as transições também precisam ser migrados. Esse é o maior desafio. Isso é particularmente desafiador para projetos em vários idiomas (que pode falhar se todos os idiomas não puderem ler--platforms
).
Se estiver criando um novo conjunto de regras, você deve oferecer suporte a plataformas do desde o início. Isso torna automaticamente suas regras compatíveis com outros regras e projetos, aumentando o valor à medida que a API da plataforma se torna onipresente.
Propriedades comuns da plataforma
As propriedades de plataforma, como OS
e CPU
, comuns em todos os projetos, precisam
sejam declarados em um local padrão e centralizado. Isso incentiva a colaboração entre projetos
e a compatibilidade com várias linguagens.
Por exemplo, se MyApp tiver um select()
em constraint_value
@myapp//cpus:arm
e SomeCommonLib tem um select()
em
@commonlib//constraints:arm
, estes acionam o "braço" com modelos incompatíveis
critérios.
Propriedades globalmente comuns são declaradas na
Repositório do @platforms
Portanto, o rótulo canônico do exemplo acima é @platforms//cpu:arm
.
As propriedades comuns de linguagem precisam ser declaradas nos repositórios das respectivas
idiomas.
Plataformas padrão
Geralmente, os proprietários do projeto devem definir
platforms para descrever a
tipos de máquina para a qual querem criar. Eles são então acionados com
--platforms
:
Quando --platforms
não está definido, o padrão do Bazel é usar um platform
representando o
máquina de build local. Gerado automaticamente às @local_config_platform//:host
portanto, não é necessário defini-lo explicitamente. Ela mapeia o OS
da máquina local
e CPU
com constraint_value
s declarados em
@platforms
C++
As regras em C++ do Bazel usam plataformas para selecionar conjuntos de ferramentas quando você define
--incompatible_enable_cc_toolchain_resolution
(#7260).
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=...
Se seu projeto é C++ puro e não depende de projetos que não sejam C++, você pode usar
plataformas seguras, contanto que seus select
s e
transições são compatíveis. Consulte
#7260 e
Como configurar conjuntos de ferramentas C++ para ver mais orientações.
Esse modo não está ativado por padrão. Isso ocorre porque os projetos da Apple
ainda configurar dependências C++ com --cpu
e --crosstool_top
(exemplo). Isso depende das regras da Apple migrando para plataformas.
Java
As regras Java do Bazel usam plataformas.
Isso substitui as sinalizações legadas --java_toolchain
, --host_java_toolchain
,
--javabase
e --host_javabase
.
Para saber como usar os sinalizadores de configuração, consulte o manual do Bazel e do Java (em inglês). Para mais informações, consulte o documento de design.
Se você ainda estiver usando sinalizações legadas, siga o processo de migração no Problema 7849.
Android
As regras do Bazel para Android usam plataformas para selecionar conjuntos de ferramentas quando você define
--incompatible_enable_android_toolchain_resolution
:
Essa opção não é ativada por padrão. Mas a migração está a caminho.
Apple
As regras da Apple do Bazel ainda não têm suporte a plataformas para selecionar conjuntos de ferramentas da Apple.
Eles também não oferecem suporte a dependências C++ ativadas para a plataforma porque usam a
--crosstool_top
legado para definir o conjunto de ferramentas do C++. Até que isso seja migrado, você
é possível misturar projetos da Apple com C++ compatível com platorm e platform
mapeamentos
(exemplo).
Outros idiomas
- As regras do Rust do Bazel têm suporte total plataformas.
- As regras Go do Bazel têm suporte total plataformas (detalhes).
Se você estiver criando regras para um novo idioma, use as plataformas para selecionar os conjuntos de ferramentas da linguagem. Consulte a documentação sobre conjuntos de ferramentas para um bom tutorial.
select()
Os projetos podem select()
em
constraint_value
destinos, mas não concluídos
plataformas. Isso é intencional para que select()
s ofereçam suporte a uma grande variedade
o máximo possível de máquinas. Uma biblioteca com fontes específicas de ARM
precisa oferecer suporte
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
. Quando
migrando seu projeto para as plataformas, é necessário convertê-las em
constraint_values
ou use mapeamentos de plataforma para dar suporte
os dois estilos na janela de migração.
Transições
As transições Starlark mudam
sinaliza partes do seu gráfico de build. Se o seu projeto usa uma transição que
define --cpu
, --crossstool_top
ou outras sinalizações legadas, regras que leem
--platforms
não terá acesso a essas mudanças.
Ao migrar seu projeto para as plataformas, você precisa converter mudanças como
return { "//command_line_option:cpu": "arm" }
para return {
"//command_line_option:platforms": "//:my_arm_platform" }
ou use platform
mapeamentos para dar suporte aos dois estilos na migração.
janela.
Como usar as plataformas atualmente
Se você quiser apenas criar ou fazer a compilação cruzada de um projeto, siga as da documentação oficial do projeto. Cabe aos mantenedores da linguagem e do projeto determinar como e quando integrar com plataformas e que valor isso oferece.
Se você é um administrador de projetos, linguagens ou conjuntos de ferramentas e seu build não usar plataformas por padrão, você tem três opções (além de aguardar o lançamento migração):
Ative a opção "Usar plataformas". para os idiomas do seu projeto (se eles tiverem um) e faça os testes necessários para ver se os projetos de que você se importa sobre o trabalho.
Se os projetos importantes para você ainda dependerem de sinalizações legadas como
--cpu
e--crosstool_top
, use-os com--platforms
:bazel build //:my_mixed_project --platforms==//:myplatform --cpu=... --crosstool_top=...
Tem algum custo de manutenção (você precisa verificar manualmente se as configurações correspondentes). Mas isso deve funcionar na ausência de políticas transições.
Escreva mapeamentos de plataforma para oferecer suporte aos dois estilos ao mapear as configurações do estilo
--cpu
para as plataformas correspondentes e vice-versa.
Mapeamentos de plataforma
Os mapeamentos de plataforma são uma API temporária que permite que os recursos da plataforma lógica com tecnologia legada coexistem no mesmo build após a descontinuação do segundo janela.
Um mapeamento de plataforma é um mapa de um platform()
para um
o 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 --apple_platform_type=macos" to "//platform:macos".
--cpu=darwin
--apple_platform_type=macos
//platforms:macos
O Bazel usa isso para garantir todas as configurações, tanto as baseadas na plataforma quanto legados, são aplicadas de modo consistente em todo o build, inclusive por meio da transições.
Por padrão, o Bazel lê os mapeamentos do arquivo platform_mappings
na sua
raiz do espaço de trabalho. Você também pode definir
--platform_mappings=//:my_custom_mapping
:
Consulte aqui para conferir todos os detalhes.
Perguntas
Para suporte geral e dúvidas sobre o cronograma de migração, entre em contato com bazel-discuss@googlegroups.com ou os proprietários das regras apropriadas.
Para discussões sobre o design e a evolução das APIs da plataforma/conjunto de ferramentas, contato bazel-dev@googlegroups.com.