Nesta página, descrevemos como criar ou testar um projeto do Xcode com o Bazel. Ele descreve as diferenças entre o Xcode e o Bazel e fornece as etapas para converter um projeto do Xcode em um projeto do Bazel. Ele também oferece soluções de problemas para resolver erros comuns.
Diferenças entre Xcode e Bazel
O Bazel exige que você especifique explicitamente cada destino de build e suas dependências, além das configurações de build correspondentes usando regras de build.
O Bazel exige que todos os arquivos de que o projeto depende estejam presentes no diretório do espaço de trabalho ou especificados como dependências no arquivo
MODULE.bazel
.Ao criar projetos do Xcode com o Bazel, os arquivos
BUILD
se tornam a fonte da verdade. Se você trabalhar no projeto no Xcode, gere uma nova versão do projeto do Xcode que corresponda aos arquivosBUILD
usando rules_xcodeproj sempre que atualizar os arquivosBUILD
. Algumas mudanças nos arquivosBUILD
, como a adição de dependências a uma meta, não exigem a regeneração do projeto, o que pode acelerar o desenvolvimento. Se você não estiver usando o Xcode, os comandosbazel build
ebazel test
vão oferecer recursos de build e teste com algumas limitações descritas mais adiante neste guia.
Antes de começar
Antes de começar, faça o seguinte:
Instale o Bazel se ainda não tiver feito isso.
Se você não conhece o Bazel e os conceitos dele, conclua o tutorial de app iOS. Você precisa entender o espaço de trabalho do Bazel, incluindo os arquivos
MODULE.bazel
eBUILD
, bem como os conceitos de destinos, regras de build e pacotes do Bazel.Analise e entenda as dependências do projeto.
Analisar dependências do projeto
Ao contrário do Xcode, o Bazel exige que você declare explicitamente todas as dependências de
cada destino no arquivo BUILD
.
Para mais informações sobre dependências externas, consulte Como trabalhar com dependências externas.
Criar ou testar um projeto do Xcode com o Bazel
Para criar ou testar um projeto do Xcode com o Bazel, faça o seguinte:
Etapa 1: criar o arquivo MODULE.bazel
Crie um arquivo MODULE.bazel
em um novo diretório. Esse diretório se torna a raiz do espaço de trabalho do Bazel. Se o projeto não usar dependências externas, esse arquivo
poderá ficar vazio. Se o projeto depender de arquivos ou pacotes que não estão em um dos diretórios do projeto, especifique essas dependências externas no arquivo MODULE.bazel
.
Etapa 2: (experimental) integrar dependências do SwiftPM
Para integrar dependências do SwiftPM ao espaço de trabalho do Bazel com swift_bazel, é necessário convertê-las em pacotes do Bazel, conforme descrito no tutorial a seguir .
Etapa 3: criar um arquivo BUILD
Depois de definir o espaço de trabalho e as dependências externas, crie um arquivo BUILD
que informe ao Bazel como o projeto está estruturado. Crie o arquivo
BUILD
na raiz do espaço de trabalho do Bazel e configure-o para fazer um
build inicial do projeto da seguinte maneira:
- Etapa 3a: adicionar o destino do aplicativo
- Etapa 3b: (opcional) adicionar os destinos de teste
- Etapa 3c: adicionar os destinos da biblioteca
Dica:para saber mais sobre pacotes e outros conceitos do Bazel, consulte Espaços de trabalho, pacotes e destinos.
Etapa 3a: adicionar o destino do aplicativo
Adicione uma
macos_application
ou uma
ios_application
segmentação por regra. Esse destino cria um pacote de aplicativos macOS ou iOS, respectivamente.
No destino, especifique no mínimo o seguinte:
bundle_id
: o ID do pacote (caminho de DNS reverso seguido pelo nome do app) do binário.provisioning_profile
: perfil de provisionamento da sua conta de desenvolvedor da Apple (se você estiver criando para um dispositivo iOS).families
(somente iOS): se o aplicativo será criado para iPhone, iPad ou ambos.infoplists
: lista de arquivos .plist a serem mesclados no arquivo Info.plist final.minimum_os_version
: a versão mínima do macOS ou iOS compatível com o aplicativo. Isso garante que o Bazel crie o aplicativo com os níveis corretos da API.
Etapa 3b: (opcional) adicione as metas de teste
As regras de build da Apple do Bazel oferecem suporte à execução de testes de unidade e de interface em todas as plataformas da Apple. Adicione os destinos de teste da seguinte forma:
macos_unit_test
para executar testes de unidade baseados em biblioteca e em aplicativo no macOS.ios_unit_test
para criar e executar testes de unidade baseados em biblioteca no iOS.ios_ui_test
para criar e executar testes de interface do usuário no simulador do iOS.Existem regras de teste semelhantes para tvOS, watchOS e visionOS.
No mínimo, especifique um valor para o atributo minimum_os_version
. Embora outros atributos de pacote, como bundle_identifier
e infoplists
, sejam definidos como os valores mais usados, verifique se esses padrões são compatíveis com o projeto e ajuste-os conforme necessário. Para testes que exigem o simulador do iOS, especifique também o nome do destino ios_application
como o valor do atributo test_host
.
Etapa 3c: adicionar as metas de biblioteca
Adicione um destino objc_library
para cada biblioteca Objective-C e um destino swift_library
para cada biblioteca Swift de que o aplicativo e/ou os testes dependem.
Adicione os destinos da biblioteca da seguinte maneira:
Adicione os destinos da biblioteca de aplicativos como dependências aos destinos do aplicativo.
Adicione os destinos da biblioteca de teste como dependências aos destinos de teste.
Liste as fontes de implementação no atributo
srcs
.Liste os cabeçalhos no atributo
hdrs
.
Você pode navegar pelos exemplos atuais de vários tipos de aplicativos diretamente no diretório rules_apple examples. Por exemplo:
Para mais informações sobre regras de build, consulte Regras da Apple para Bazel.
Neste ponto, é recomendável testar o build:
bazel build //:<application_target>
Etapa 4: (opcional) granularizar o build
Se o projeto for grande ou à medida que ele crescer, considere dividi-lo em vários pacotes do Bazel. Essa granularidade maior oferece:
Aumento da incrementalidade dos builds
Aumento da paralelização de tarefas de build.
Melhor capacidade de manutenção para usuários futuros.
Melhor controle sobre a visibilidade do código-fonte em destinos e pacotes. Isso evita problemas como bibliotecas que contêm detalhes de implementação vazando para APIs públicas.
Dicas para granularizar o projeto:
Coloque cada biblioteca em um pacote do Bazel. Comece com aqueles que exigem o menor número de dependências e avance na árvore de dependências.
À medida que você adiciona arquivos
BUILD
e especifica destinos, adicione esses novos destinos aos atributosdeps
dos destinos que dependem deles.A função
glob()
não cruza limites de pacotes. Portanto, à medida que o número de pacotes aumenta, os arquivos correspondentes aglob()
diminuem.Ao adicionar um arquivo
BUILD
a um diretóriomain
, também adicione um arquivoBUILD
ao diretóriotest
correspondente.Impor limites de visibilidade saudáveis em todos os pacotes.
Crie o projeto após cada mudança importante nos arquivos
BUILD
e corrija os erros de build à medida que eles aparecem.
Etapa 5: executar o build
Execute o build totalmente migrado para garantir que ele seja concluído sem erros ou avisos. Execute cada aplicativo e destino de teste individualmente para encontrar mais facilmente as fontes de erros que ocorrerem.
Exemplo:
bazel build //:my-target
Etapa 6: gerar o projeto Xcode com rules_xcodeproj
Ao criar com o Bazel, os arquivos MODULE.bazel
e BUILD
se tornam a fonte
de verdade sobre o build. Para que o Xcode saiba disso, gere um projeto do Xcode compatível com o Bazel usando rules_xcodeproj.
Solução de problemas
Os erros do Bazel podem surgir quando ele fica dessincronizado com a versão selecionada do Xcode, como quando você aplica uma atualização. Confira algumas coisas que você pode tentar se estiver enfrentando erros com o Xcode, por exemplo, "A versão do Xcode precisa ser especificada para usar um CROSSTOOL da Apple".
Execute o Xcode manualmente e aceite os Termos e Condições.
Use o Xcode select para indicar a versão correta, aceite a licença e limpe o estado do Bazel.
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
sudo xcodebuild -license
bazel sync --configure
- Se isso não funcionar, tente executar
bazel clean --expunge
.