Tutorial do Bazel: criar um app Android

7.3 · 7.2 · 7.1 · 7.0 · 6.5

Observação:há limitações conhecidas no uso do Bazel para criar apps Android. Acesse a lista de problemas conhecidos do team-Android no GitHub para conferir a lista de problemas conhecidos. Embora a equipe do Bazel e os colaboradores de software de código aberto (OSS, na sigla em inglês) trabalhem ativamente para resolver problemas conhecidos, os usuários precisam estar cientes de que o Android Studio não oferece suporte oficial a projetos do Bazel.

Neste tutorial, mostramos como criar um app Android simples usando o Bazel.

O Bazel permite a criação de apps Android usando as regras do Android.

Este tutorial é destinado a usuários do Windows, macOS e Linux e não exige experiência com o Bazel ou o desenvolvimento de apps Android. Não é necessário programar nenhum código do Android neste tutorial.

O que você vai aprender

Neste tutorial, você vai aprender a:

  • Configure seu ambiente instalando o Bazel e o Android Studio e fazendo o download do projeto de exemplo.
  • Configure um espaço de trabalho do Bazel que contenha o código-fonte do app e um arquivo WORKSPACE que identifique o nível superior do diretório do espaço de trabalho.
  • Atualize o arquivo WORKSPACE para conter referências às dependências externas necessárias, como o SDK do Android.
  • Crie um arquivo BUILD.
  • Crie o app com o Bazel.
  • Implante e execute o app em um emulador Android ou dispositivo físico.

Antes de começar

Instalar o Bazel

Antes de começar o tutorial, instale o seguinte software:

  • Bazel. Para instalar, siga as instruções de instalação.
  • Android Studio. Para instalar, siga as etapas para fazer o download do Android Studio. Execute o assistente de configuração para fazer o download do SDK e configurar o ambiente.
  • (Opcional) Git. Use git para fazer o download do projeto do app Android.

Fazer o download do projeto de exemplo

Para o projeto de exemplo, use um projeto de app Android básico no repositório de exemplos do Bazel.

Este app tem um único botão que mostra uma saudação quando clicado:

Saudação do botão

Figura 1. Saudação do botão do app Android.

Clone o repositório com git (ou faça o download do arquivo ZIP diretamente):

git clone https://github.com/bazelbuild/examples

O projeto de exemplo deste tutorial está em examples/android/tutorial. No restante do tutorial, você executará comandos nesse diretório.

Analisar os arquivos de origem

Confira os arquivos de origem do app.

.
├── README.md
└── src
    └── main
        ├── AndroidManifest.xml
        └── java
            └── com
                └── example
                    └── bazel
                        ├── AndroidManifest.xml
                        ├── Greeter.java
                        ├── MainActivity.java
                        └── res
                            ├── layout
                            │   └── activity_main.xml
                            └── values
                                ├── colors.xml
                                └── strings.xml

Os arquivos e diretórios principais são:

Nome Local
Arquivos de manifesto do Android src/main/AndroidManifest.xml e src/main/java/com/example/bazel/AndroidManifest.xml
Arquivos de origem do Android src/main/java/com/example/bazel/MainActivity.java e Greeter.java
Diretório de arquivos de recursos src/main/java/com/example/bazel/res/

Criação com o Bazel

Configurar o espaço de trabalho

Um espaço de trabalho é um diretório que contém os arquivos de origem de um ou mais projetos de software e tem um arquivo WORKSPACE na raiz.

O arquivo WORKSPACE pode estar vazio ou conter referências a dependências externas necessárias para criar o projeto.

Primeiro, execute o comando a seguir para criar um arquivo WORKSPACE vazio:

SO Comando
Linux, macOS touch WORKSPACE
Windows (prompt de comando) type nul > WORKSPACE
Windows (PowerShell) New-Item WORKSPACE -ItemType file

Como executar o Bazel

Agora você pode verificar se o Bazel está sendo executado corretamente com o comando:

bazel info workspace

Se o Bazel imprimir o caminho do diretório atual, está tudo pronto. Se o arquivo WORKSPACE não existir, uma mensagem de erro como esta será exibida:

ERROR: The 'info' command is only supported from within a workspace.

Integrar com o SDK do Android

O Bazel precisa executar as ferramentas de build do SDK do Android para criar o app. Isso significa que você precisa adicionar algumas informações ao arquivo WORKSPACE para que o Bazel saiba onde encontrá-las.

Adicione a linha a seguir ao arquivo WORKSPACE:

android_sdk_repository(name = "androidsdk")

Isso vai usar o SDK do Android no caminho referenciado pela variável de ambiente ANDROID_HOME e detectar automaticamente o nível mais alto da API e a versão mais recente das ferramentas de build instaladas nesse local.

Você pode definir a variável ANDROID_HOME como o local do SDK do Android. Encontre o caminho para o SDK instalado usando o SDK Manager do Android Studio. Supondo que o SDK esteja instalado nos locais padrão, use os seguintes comandos para definir a variável ANDROID_HOME:

SO Comando
Linux export ANDROID_HOME=$HOME/Android/Sdk/
macOS export ANDROID_HOME=$HOME/Library/Android/sdk
Windows (prompt de comando) set ANDROID_HOME=%LOCALAPPDATA%\Android\Sdk
Windows (PowerShell) $env:ANDROID_HOME="$env:LOCALAPPDATA\Android\Sdk"

Os comandos acima definem a variável apenas para a sessão de shell atual. Para torná-los permanentes, execute os seguintes comandos:

SO Comando
Linux echo "export ANDROID_HOME=$HOME/Android/Sdk/" >> ~/.bashrc
macOS echo "export ANDROID_HOME=$HOME/Library/Android/Sdk/" >> ~/.bashrc
Windows (prompt de comando) setx ANDROID_HOME "%LOCALAPPDATA%\Android\Sdk"
Windows (PowerShell) [System.Environment]::SetEnvironmentVariable('ANDROID_HOME', "$env:LOCALAPPDATA\Android\Sdk", [System.EnvironmentVariableTarget]::User)

Também é possível especificar explicitamente o caminho absoluto do SDK do Android, o nível da API e a versão das ferramentas de build a serem usadas, incluindo os atributos path, api_level e build_tools_version. Se api_level e build_tools_version não forem especificados, a regra android_sdk_repository vai usar a respectiva versão mais recente disponível no SDK. É possível especificar qualquer combinação desses atributos, desde que eles estejam presentes no SDK, por exemplo:

android_sdk_repository(
    name = "androidsdk",
    path = "/path/to/Android/sdk",
    api_level = 25,
    build_tools_version = "30.0.3"
)

No Windows, o atributo path precisa usar o caminho de estilo misto, ou seja, um caminho do Windows com barras oblíquas:

android_sdk_repository(
    name = "androidsdk",
    path = "c:/path/to/Android/sdk",
)

Opcional:se você quiser compilar código nativo no seu app Android, também será necessário fazer o download do Android NDK e informar ao Bazel onde encontrá-lo, adicionando a seguinte linha ao arquivo WORKSPACE:

android_ndk_repository(name = "androidndk")

Semelhante ao android_sdk_repository, o caminho para o Android NDK é inferido da variável de ambiente ANDROID_NDK_HOME por padrão. O caminho também pode ser especificado explicitamente com um atributo path em android_ndk_repository.

Para mais informações, leia Como usar o Kit de desenvolvimento nativo do Android com o Bazel.

api_level é a versão da API do Android que o SDK e o NDK destinam, por exemplo, 23 para o Android 6.0 e 25 para o Android 7.1. Se não for definido explicitamente, o padrão de api_level será o nível de API mais alto disponível para android_sdk_repository e android_ndk_repository.

Não é necessário definir os níveis de API com o mesmo valor para o SDK e o NDK. Esta página contém um mapa das versões do Android para os níveis da API suportados pelo NDK.

Criar um arquivo BUILD

Um arquivo BUILD descreve a relação entre um conjunto de saídas de build, como recursos Android compilados de aapt ou arquivos de classe de javac, e as dependências deles. Essas dependências podem ser arquivos de origem (Java, C++) no seu espaço de trabalho ou em outras saídas de build. Os arquivos BUILD são escritos em uma linguagem chamada Starlark.

Os arquivos BUILD fazem parte de um conceito no Bazel conhecido como hierarquia de pacotes. A hierarquia de pacotes é uma estrutura lógica que sobrepõe a estrutura de diretórios no seu espaço de trabalho. Cada pacote é um diretório (e seus subdiretórios) que contém um conjunto relacionado de arquivos de origem e um arquivo BUILD. O pacote também inclui todos os subdiretórios, exceto os que contêm o próprio arquivo BUILD. O nome do pacote é o caminho para o arquivo BUILD relativo ao WORKSPACE.

A hierarquia de pacotes do Bazel é conceitualmente diferente da hierarquia de pacotes Java do diretório do app Android em que o arquivo BUILD está localizado, embora os diretórios possam ser organizados de maneira idêntica.

Para o app Android simples neste tutorial, os arquivos de origem em src/main/ formam um único pacote do Bazel. Um projeto mais complexo pode ter muitos pacotes aninhados.

Adicionar uma regra android_library

Um arquivo BUILD contém vários tipos diferentes de declarações para o Bazel. O tipo mais importante é a regra de build, que informa ao Bazel como criar uma saída de software intermediária ou final a partir de um conjunto de arquivos de origem ou outras dependências. O Bazel fornece duas regras de build, android_library e android_binary, que podem ser usadas para criar um app Android.

Neste tutorial, você vai usar a regra android_library para informar ao Bazel que ele precisa criar um módulo de biblioteca do Android a partir do código-fonte e dos arquivos de recursos do app. Em seguida, você vai usar a regra android_binary para dizer ao Bazel como criar o pacote do app Android.

Crie um novo arquivo BUILD no diretório src/main/java/com/example/bazel e declare um novo destino android_library:

src/main/java/com/example/bazel/BUILD:

package(
    default_visibility = ["//src:__subpackages__"],
)

android_library(
    name = "greeter_activity",
    srcs = [
        "Greeter.java",
        "MainActivity.java",
    ],
    manifest = "AndroidManifest.xml",
    resource_files = glob(["res/**"]),
)

A regra de build android_library contém um conjunto de atributos que especificam as informações necessárias para o Bazel criar um módulo de biblioteca com base nos arquivos de origem. O nome da regra é greeter_activity. Você vai fazer referência à regra usando esse nome como uma dependência na regra android_binary.

Adicionar uma regra android_binary

A regra android_binary cria o pacote de aplicativo Android (arquivo .apk) para seu app.

Crie um novo arquivo BUILD no diretório src/main/ e declare um novo destino android_binary:

src/main/BUILD:

android_binary(
    name = "app",
    manifest = "AndroidManifest.xml",
    deps = ["//src/main/java/com/example/bazel:greeter_activity"],
)

Aqui, o atributo deps faz referência à saída da regra greeter_activity que você adicionou ao arquivo BUILD acima. Isso significa que, quando o Bazel gera a saída dessa regra, ele verifica primeiro se a saída da regra da biblioteca greeter_activity foi criada e está atualizada. Caso contrário, o Bazel compila e usa essa saída para criar o arquivo de pacote do aplicativo.

Agora, salve e feche o arquivo.

Criar o app

Tente criar o app. Execute o comando a seguir para criar o destino android_binary:

bazel build //src/main:app

O subcomando build instrui o Bazel a criar o destino que segue. O destino é especificado como o nome de uma regra de build em um arquivo BUILD, com o caminho do pacote relativo ao diretório do espaço de trabalho. Neste exemplo, o destino é app e o caminho do pacote é //src/main/.

Às vezes, é possível omitir o caminho do pacote ou o nome de destino, dependendo do diretório de trabalho atual na linha de comando e do nome do destino. Para mais detalhes sobre rótulos e caminhos de destino, consulte Rótulos.

O Bazel vai começar a criar o app de exemplo. Durante esse processo, a saída vai ser semelhante a esta:

INFO: Analysed target //src/main:app (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //src/main:app up-to-date:
  bazel-bin/src/main/app_deploy.jar
  bazel-bin/src/main/app_unsigned.apk
  bazel-bin/src/main/app.apk

Localizar as saídas de build

Ele coloca as saídas das operações de compilação intermediárias e finais em um conjunto de diretórios de saída por usuário e por espaço de trabalho. Esses diretórios são vinculados pelos seguintes locais no nível superior do diretório do projeto, em que WORKSPACE é:

  • bazel-bin armazena executáveis binários e outras saídas de build executáveis
  • bazel-genfiles armazena arquivos de origem intermediários gerados pelas regras do Bazel.
  • bazel-out armazena outros tipos de saídas de build

O Bazel armazena o arquivo .apk do Android gerado usando a regra android_binary no diretório bazel-bin/src/main, em que o nome do subdiretório src/main é derivado do nome do pacote do Bazel.

Em um prompt de comando, liste o conteúdo desse diretório e encontre o arquivo app.apk:

SO Comando
Linux, macOS ls bazel-bin/src/main
Windows (prompt de comando) dir bazel-bin\src\main
Windows (PowerShell) ls bazel-bin\src\main

Executar o app

Agora é possível implantar o app em um dispositivo Android ou emulador conectado na linha de comando usando o comando bazel mobile-install. Esse comando usa o Android Debug Bridge (adb) para se comunicar com o dispositivo. É necessário configurar o dispositivo para usar adb seguindo as instruções na Android Debug Bridge antes da implantação. Você também pode instalar o app no Android Emulator incluído no Android Studio. Verifique se o emulador está em execução antes de executar o comando abaixo.

Digite o seguinte:

bazel mobile-install //src/main:app

Em seguida, localize e inicie o "Bazel Tutorial App":

App de tutorial do Bazel

Figura 2. App de tutorial do Bazel.

Parabéns! Você acabou de instalar seu primeiro app Android criado com o Bazel.

O subcomando mobile-install também oferece suporte à flag --incremental, que pode ser usada para implantar apenas as partes do app que mudaram desde a última implantação.

Ele também é compatível com a sinalização --start_app para iniciar o app imediatamente após a instalação.

Leitura adicional

Para mais detalhes, consulte estas páginas:

Boa construção!