Sistema de build Soong

Antes do lançamento do Android 7.0, o Android usava o GNU Make (link em inglês) exclusivamente para descrever e executar regras de criação. O sistema de criação Make tem ampla compatibilidade e é muito utilizado, mas se tornou lento, propenso a erros, não escalonável e difícil de testar no Android. O sistema de build Soong oferece a flexibilidade necessária para os builds do Android.

Por isso, os desenvolvedores de plataforma precisam trocar o Make pelo Soong assim que possível. Se precisar de ajuda, envie perguntas para o Grupo do Google android-building.

O que é o Soong?

O sistema de build Soong foi lançado no Android 7.0 (Nougat) para substituir o Make. Ele usa a ferramenta de clonagem do GNU Make, Kati, e o componente de sistema de build, Ninja (links em inglês), para acelerar os builds do Android.

Acesse a descrição do sistema de build Make do Android no Android Open Source Project (AOSP) para consultar instruções gerais e mudanças no sistema de build para os gravadores do Android.mk e saber mais sobre as modificações necessárias para a adaptação do Make para o Soong.

Consulte as entradas relacionadas ao build no glossário para conferir as definições dos termos-chave, e os arquivos de referência do Soong para todos os detalhes.

Comparação entre o Make e o Soong

Veja uma comparação da configuração do Make com o Soong, fazendo o mesmo em um arquivo de configuração Soong (Blueprint ou .bp).

Exemplo do Make

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := libxmlrpc++
LOCAL_MODULE_HOST_OS := linux

LOCAL_RTTI_FLAG := -frtti
LOCAL_CPPFLAGS := -Wall -Werror -fexceptions
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/src

LOCAL_SRC_FILES := $(call \
     all-cpp-files-under,src)
include $(BUILD_SHARED_LIBRARY)

Exemplo do Soong

cc_library_shared {
     name: "libxmlrpc++",

     rtti: true,
     cppflags: [
           "-Wall",
           "-Werror",
           "-fexceptions",
     ],
     export_include_dirs: ["src"],
     srcs: ["src/**/*.cpp"],

     target: {
           darwin: {
                enabled: false,
           },
     },
}

Para exemplos de configuração Soong específicos de teste, consulte Configuração simples do build.

Para explicações sobre os campos em um arquivo Android.bp, consulte Formato do arquivo Android.bp.

Módulos especiais

Alguns grupos de módulos especiais têm características únicas.

Módulos de padrões

Um módulo de padrões pode ser usado para repetir as mesmas propriedades em vários módulos. Por exemplo:

cc_defaults {
    name: "gzip_defaults",
    shared_libs: ["libz"],
    stl: "none",
}

cc_binary {
    name: "gzip",
    defaults: ["gzip_defaults"],
    srcs: ["src/test/minigzip.c"],
}

Módulos pré-criados

Alguns tipos de módulos pré-criados permitem que um módulo tenha o mesmo nome que as contrapartes dele baseadas em origem. Por exemplo, pode haver um cc_prebuilt_binary chamado foo quando já houver um cc_binary com o mesmo nome. Isso dá aos desenvolvedores a flexibilidade de escolher qual versão incluir no produto final. Se uma configuração de criação contiver as duas versões, o valor da sinalização prefer na definição do módulo pré-criado ditará qual versão tem prioridade. Observe que alguns módulos pré-criados têm nomes que não começam com prebuilt, como android_app_import.

Módulos de namespace

Até que o Android seja totalmente convertido de Make para Soong, a configuração de produto Make precisa especificar um valor PRODUCT_SOONG_NAMESPACES. O valor precisa ser uma lista de namespaces separados por espaços, que o Soong exporta para o Make para ser compilada pelo comando m. Os detalhes de ativação de namespaces poderão mudar depois que a conversão do Android para Soong for concluída.

O Soong permite que módulos em diferentes diretórios especifiquem o mesmo nome, contanto que cada módulo seja declarado dentro de um namespace diferente. Um namespace pode ser declarado desta forma:

soong_namespace {
    imports: ["path/to/otherNamespace1", "path/to/otherNamespace2"],
}

Um namespace não tem a propriedade de nome. O caminho é atribuído automaticamente como o nome dele.

Cada módulo Soong recebe um namespace com base na própria localização na árvore. Considera-se que cada módulo Soong está no namespace definido pelo soong_namespace encontrado em um arquivo Android.bp no diretório atual ou no diretório ancestral mais próximo. Se nenhum módulo soong_namespace for localizado, será considerado que o módulo está no namespace raiz implícito.

Veja um exemplo: o Soong tenta resolver a dependência D declarada pelo módulo M no namespace N que importa namespaces I1, I2, I3...

  1. Então, se D for um nome totalmente qualificado com a forma //namespace:module, somente o namespace especificado será procurado pelo nome do módulo especificado.
  2. Caso contrário, o Soong primeiro procurará por um módulo chamado D declarado no namespace N.
  3. Se esse módulo não existir, o Soong procurará por um módulo chamado D nos namespaces I1, I2, I3…
  4. Por fim, o Soong procurará no namespace raiz.