Habilitando Compilação Incremental de Kotlin no Buck2 com a Build Tools API KEEP
Sources: https://engineering.fb.com/2025/08/26/open-source/enabling-kotlin-incremental-compilation-on-buck2, https://engineering.fb.com/2025/08/26/open-source/enabling-kotlin-incremental-compilation-on-buck2/, Meta
TL;DR
- A compilação incremental do Kotlin agora está integrada ao Buck2 para acelerar builds ao focar apenas nos arquivos alterados.
- A abordagem usa a Build Tools API KEEP para uma integração estável e com visão de futuro, lidando com questões de shading e conflitos de classpath.
- Ações incrementais do Buck2 preservam saídas entre execuções, usando hashes para detectar mudanças e snapshots de classpath para considerar alterações nas dependências.
- Alguns módulos críticos chegam a ser 3x mais rápidos, evidenciando ganhos de produtividade significativos em escala.
- Plugins e processamento de anotações (KSP2) foram ajustados para trabalhar com rodadas incrementais, garantindo resultados consistentes entre várias avaliações. Fonte: blog de engenharia da Meta sobre habilitar compilação incremental do Kotlin no Buck2. Veja https://engineering.fb.com/2025/08/26/open-source/enabling-kotlin-incremental-compilation-on-buck2/ para o relato detalhado.
Contexto e antecedentes
O compilador incremental do Kotlin tem sido uma vantagem para desenvolvedores que buscam feedback rápido ao recompilar apenas as porções modificadas de um código. O Buck2, sistema de build da Meta, também defende módulos pequenos para alcançar builds rápidos por meio de paralelismo e execução incremental. Conforme os bases de código crescem e as equipes evoluem, alguns módulos inevitavelmente aumentam de tamanho, o que pode impactar o tempo total de compilação. Para explorar se a compilação incremental traria ganhos mensuráveis no Buck2, a Meta avaliou o compilador incremental do Kotlin dentro da toolchain Android. O benefício central da compilação incremental é simples: em vez de reconstruir todo o módulo, o compilador foca nos arquivos alterados e nos que dependem deles. A Meta observou que vários módulos críticos podem se beneficiar significativamente, com algumas compilações acelerando até três vezes. Esse achado motivou um esforço de integração mais profundo, equilibrando estabilidade a longo prazo com a necessidade de velocidade. Do ponto de vista de ferramentas, a equipe enfrentou alguns obstáculos. Em Kotlin 2.2.0, o único contrato público garantido para o compilador é via interface de linha de comando (CLI). A CLI não suporta compilação incremental, o que levou a buscar pontos de integração alternativos. APIs internas do compilador são instáveis e não destinadas ao uso público, então depender delas traria fragilidade diante de atualizações do Kotlin. A Build Tools API (KEEP), introduzida com Kotlin 1.9.20, surgiu como o ponto de integração oficial mais estável e com suporte à compilação incremental. A decisão foi adotar o KEEP, com a ideia de influenciar a direção da API enquanto obtém um caminho estável para o futuro. Outro desafio prático foi o conflito de classpath entre jars do compilador Kotlin sombreado e o toolchain Android historicamente feito com o compiler não sombreado. Para resolver isso, a Meta, em estágio de protótipo, des-sombreou temporariamente a Build Tools API (com jarjar) antes de migrar completamente para o compilador sombreado, assegurando um protótipo funcional antes de uma migração completa. Essa abordagem permitiu validar o caminho incremental sem exigir grandes refatorações de imediato. Para habilitar a compilação incremental, o Buck2 precisa ter acesso aos outputs da construção anterior. O Buck2, por padrão, apaga outputs antes de reconstruir um módulo, o que quebraria a compilação incremental. A equipe introduziu um modo nos ações incrementais que permite preservar os outputs anteriores, com a advertência de que os desenvolvedores devem limpar manualmente o que não for mais necessário. Essa mudança foi essencial para abrir o caminho incremental, mantendo o controle sobre a higiene de cache. Uma visão mais ampla era suportar builds distribuídos—os builds do Buck2 podem acontecer remotamente e os resultados retornam ao desenvolvedor. Um cache de compilação relocável é crucial nesse cenário para evitar conflitos de caminho entre máquinas diferentes. A Meta configurou explicitamente o diretório raiz do projeto e o diretório de build dentro das configurações de compilação incremental para manter a estabilidade do cache entre diferentes workers e ambientes.
O que há de novo
- Adoção da Build Tools API KEEP como ponto de integração oficial da compilação incremental do Kotlin no Buck2, oferecendo um caminho mais estável e com visão de futuro.
- Um workaround prático foi utilizado durante a prototipagem para des-sombrear a Build Tools API (com jarjar) antes de migrar para o compilador sombreado completo, assegurando um protótipo funcional antes da migração total.
- A Buck2 incremental preserva outputs entre execuções e gera digests de hash para cada entrada de ação, permitindo detecção precisa de mudanças e recompilação seletiva.
- A detecção de mudanças pode ocorrer automaticamente ou de forma manual. A detecção automática depende da versão do Kotlin; para versões anteriores a 2.1.20, é necessário fornecer uma lista de arquivos modificados. Mesmo com detecção automática, fornecer a lista pode otimizar o processo.
- Snapshots de classpath capturam o ABI de bibliotecas. Comparando snapshots atuais com os anteriores, o compilador pode determinar quais arquivos no módulo são afetados por mudanças nas dependências. Uma ação dedicada gera esses snapshots, e o artefato resultante pode ser armazenado em cache ou executado remotamente para evitar processamento local pesado.
- Se a ferramenta de análise de dependências já identifica as mudanças relevantes, a etapa de comparação de snapshots pode ser pulada para acelerar a build.
- Integrar compilação incremental com plugins de compilador personalizados demandou ajustes: plugins precisam ser incrementais e capazes de lidar com entradas parciais, já que a compilação incremental pode trabalhar com subconjuntos de arquivos em rodadas múltiplas.
- O compilador incremental do Kotlin pode executar várias rodadas dentro de uma única construção para determinar o conjunto completo de arquivos afetados. Esse comportamento pode acionar o plugin várias vezes com entradas diferentes, então atualizações nos plugins passaram a acumular resultados ao longo das rodadas para evitar sobrescrever saídas anteriores.
- O processamento de anotações (KSP2) foi utilizado como parte do fluxo. O KSP2 é projetado como uma ferramenta independente que usa a Kotlin Analysis API para analisar o código, o que ajuda a manter a compatibilidade com a compilação incremental.
Por que isso importa (impacto para desenvolvedores/empresas)
A integração oferece ganhos de produtividade ao reduzir o trabalho de desenvolvedores quando recompilam grandes bases Android. Ao reutilizar saídas e focar apenas nos arquivos alterados, as builds podem ser concluídas mais rapidamente, resultando em ciclos de feedback mais curtos. Em ambientes de build distribuídos, um cache estável e relocável é essencial para evitar conflitos de caminho entre diferentes máquinas. Esse trabalho também ajuda equipes a escalar suas toolchains conforme módulos crescem e equipes se expandem, mantendo a satisfação com builds e a eficiência de desenvolvimento.
Detalhes técnicos ou implementação
- O compilador incremental do Kotlin requer acesso aos outputs anteriores, o que o Buck2 normalmente apaga por padrão. A equipe configurou as ações incrementais do Buck2 para preservar outputs anteriores, com a ressalva de que desenvolvedores devem limpar manualmente saídas não mais úteis. Isso viabiliza o estado anterior para o processo de compilação incremental.
- A detecção de mudanças pode ocorrer automaticamente ou manualmente. A detecção automática depende da versão do Kotlin; para versões anteriores a 2.1.20, é necessário fornecer a lista de arquivos modificados. Mesmo com detecção automática, fornecer a lista pode melhorar o desempenho.
- A Buck2 action incremental captura digests de hash para cada entrada de ação para determinar o que mudou desde a construção anterior. Isso facilita a identificação precisa dos arquivos afetados e minimiza trabalho desnecessário.
- Snapshots de classpath capturam o estado de ABI de bibliotecas. Ao comparar snapshots atuais com os anteriores, o compilador pode determinar quais arquivos no módulo são afetados por mudanças nas dependências. Uma ação separada gera esses snapshots, que podem ser armazenados em cache ou executados remotamente para evitar processamento local pesado.
- Se a análise de dependências já realizada pela ferramenta de build identifica as mudanças relevantes, a etapa de comparação de snapshots pode ser pulada para simplificar a build.
- Integrar compilação incremental com plugins personalizados exigiu cuidado: plugins devem ser incrementais e capazes de lidar com entradas parciais, pois a compilação incremental pode operar com subconjuntos de arquivos em várias rodadas. O Kotlin Symbol Processing (KSP2) foi utilizado para processamento de anotações, ajudando a manter compatibilidade com o fluxo incremental. O KSP2 funciona como uma ferramenta independente que usa a Kotlin Analysis API para analisar código, o que reduz o acoplamento com o compilador central.
Visão rápida sobre mudanças
| Opção de detecção | O que faz |
| Quando usar |
|---|
| --- |
| --- |
| Detecção automática |
| Melhor com Kotlin 2.1.20+ |
| Lista manual de mudanças |
| Necessário para Kotlin |
References
More news
Nova Estrutura de Classificação com Foco em Diversidade para Melhor Qualidade de Notificações no Instagram
Meta apresenta uma estrutura de classificação de notificações com foco em diversidade, adicionando uma camada de diversidade aos modelos de engajamento para reduzir a repetição, ampliar a variedade de conteúdo e manter a CTR no Instagram.
Criando Soluções de Agentes de IA para Acesso e Segurança de Dados em Armazém
Meta apresenta um fluxo de trabalho de acesso a dados orientado por agentes para o seu data warehouse, usando agentes de usuário de dados e agentes de proprietário de dados para simplificar o acesso, impor salvaguardas e permitir exploração de dados contextualizada em escala.
Diff Risk Score: IA orientada ao risco no desenvolvimento de software da Meta
Diff Risk Score (DRS) usa um modelo Llama ajustado para prever risco de produção de mudanças de código, viabilizando desbloqueio de código com segurança e ampliando ferramentas de gerenciamento de risco.
Construindo uma interface humano-máquina para todos
A Reality Labs da Meta explora dispositivos de pulso com sEMG para ampliar a interação humano-computador. Este texto resume a discussão do Meta Tech Podcast sobre generalização e o caminho rumo a uma interface neuromotora genérica.
Aceleração de ML no dispositivo na família de apps da Meta com ExecuTorch
ExecuTorch é o framework de inferência no dispositivo de código aberto da Meta, elevando latência, privacidade e performance no Instagram, WhatsApp e Messenger, com PyTorch 2.x.
Como a Meta Mantém Seu Hardware de IA Confiável: Detecção e Mitigação de Neutralizações Silenciosas de Dados
Abordagem robusta de confiabilidade de hardware de IA da Meta: taxonomia de falhas, SDCs (neutralizações silenciosas de dados), mecanismos de detecção e mitigação em toda a frota para treinar e gerar inferência com confiabilidade em larga escala.