- Início
- Documentation
- Nativos
- Runbook de Build, Release e Depuração de Nativos
Runbook de Build, Release e Depuração de Nativos
Este runbook descreve como o pipeline de build do @f5-sales-demo/pi-natives produz addons .node, como as distribuições compiladas os carregam e como depurar falhas de carregador/build.
Segue os termos de arquitetura de docs/natives-architecture.md:
- produção de artefatos em tempo de build (
scripts/build-native.ts) - geração de manifesto de addon embutido (
scripts/embed-native.ts) - carregamento de addon em runtime + porta de validação (
src/native.ts)
Arquivos de implementação
Seção intitulada “Arquivos de implementação”packages/natives/scripts/build-native.tspackages/natives/scripts/embed-native.tspackages/natives/package.jsonpackages/natives/src/native.tscrates/pi-natives/Cargo.toml
Visão geral do pipeline de build
Seção intitulada “Visão geral do pipeline de build”1) Entrypoints de build
Seção intitulada “1) Entrypoints de build”Scripts em packages/natives/package.json:
bun scripts/build-native.ts(build) → build de releasebun scripts/build-native.ts --dev(dev:native) → build de perfil debug/dev (mesma nomenclatura de saída)bun scripts/embed-native.ts(embed:native) → gerarsrc/embedded-addon.tsa partir dos arquivos compilados
2) Build do artefato Rust
Seção intitulada “2) Build do artefato Rust”build-native.ts executa o Cargo em crates/pi-natives:
- comando base:
cargo build - modo release adiciona
--release, a menos que--devseja passado - alvo de cross-compilação adiciona
--target <CROSS_TARGET>
crates/pi-natives/Cargo.toml declara crate-type = ["cdylib"], portanto o Cargo emite uma biblioteca compartilhada (.so/.dylib/.dll) que é então copiada/renomeada para um nome de arquivo de addon .node.
3) Descoberta e instalação do artefato
Seção intitulada “3) Descoberta e instalação do artefato”Após a conclusão do Cargo, build-native.ts verifica os diretórios de saída candidatos na seguinte ordem:
${CARGO_TARGET_DIR}(se definido)<repo>/targetcrates/pi-natives/target
Para cada raiz, verifica os diretórios de perfil:
- cross build:
<root>/<crossTarget>/<profile>depois<root>/<profile> - build nativo:
<root>/<profile>
Em seguida, procura por um dos seguintes:
libpi_natives.solibpi_natives.dylibpi_natives.dlllibpi_natives.dll
Quando encontrado, instala atomicamente em packages/natives/native/ com semântica de arquivo temporário + renomeação (o fallback do Windows trata explicitamente falhas de substituição de DLL bloqueada).
Modelo de alvo/variante e convenções de nomenclatura
Seção intitulada “Modelo de alvo/variante e convenções de nomenclatura”Tag de plataforma
Seção intitulada “Tag de plataforma”Tanto o build quanto o runtime utilizam a tag de plataforma:
<platform>-<arch> (exemplo: darwin-arm64, linux-x64)
Modelo de variante (somente x64)
Seção intitulada “Modelo de variante (somente x64)”x64 suporta variantes de CPU:
modern(caminho com suporte a AVX2)baseline(fallback)
Arquiteturas diferentes de x64 utilizam um único artefato padrão (sem sufixo de variante).
Nomes de arquivo de saída
Seção intitulada “Nomes de arquivo de saída”Builds de release:
- x64:
pi_natives.<platform>-<arch>-modern.nodeou...-baseline.node - não-x64:
pi_natives.<platform>-<arch>.node
Build de dev (--dev):
- Utiliza flags de perfil debug, mas mantém a nomenclatura de saída padrão com tag de plataforma
Ordem dos candidatos do carregador em native.ts:
- candidatos de release
- o modo compilado antepõe candidatos extraídos/em cache antes dos arquivos locais do pacote
Flags de ambiente e opções de build
Seção intitulada “Flags de ambiente e opções de build”Flags de runtime
Seção intitulada “Flags de runtime”PI_DEV(comportamento do carregador): ativa diagnósticos do carregadorPI_NATIVE_VARIANT(comportamento do carregador, somente x64): força a seleção demodernoubaselineem runtimePI_COMPILED(comportamento do carregador): ativa o comportamento de candidato/extração para binário compilado
Flags/opções em tempo de build
Seção intitulada “Flags/opções em tempo de build”--dev(argumento do script): compila perfil debugCROSS_TARGET: passado ao--targetdo CargoTARGET_PLATFORM: sobrescreve a nomenclatura da tag de plataforma na saídaTARGET_ARCH: sobrescreve a nomenclatura de arquitetura na saídaTARGET_VARIANT(somente x64): forçamodernoubaselinepara o nome do arquivo de saída e política de RUSTFLAGSCARGO_TARGET_DIR: raiz adicional ao buscar saídas do CargoRUSTFLAGS:- se não definido e sem cross-compilação, o script define:
- modern:
-C target-cpu=x86-64-v3 - baseline:
-C target-cpu=x86-64-v2 - não-x64 / sem variante:
-C target-cpu=native
- modern:
- se já definido, o script não sobrescreve
- se não definido e sem cross-compilação, o script define:
Transições de estado/ciclo de vida do build
Seção intitulada “Transições de estado/ciclo de vida do build”Ciclo de vida do build (build-native.ts)
Seção intitulada “Ciclo de vida do build (build-native.ts)”- Init: analisa args/env (
--dev, sobrescritas de alvo, flags de cross) - Resolução de variante:
- não-x64 → sem variante
- x64 +
TARGET_VARIANT→ variante explícita - cross-build x64 sem
TARGET_VARIANT→ erro fatal - build local x64 sem sobrescrita → detecta AVX2 do host
- Compilação: executa o Cargo com perfil/alvo resolvidos
- Localização do artefato: varre raízes de alvo/diretórios de perfil/nomes de biblioteca
- Instalação: copia + renomeação atômica em
packages/natives/native - Conclusão: addon de saída pronto para candidatos do carregador
As saídas por falha ocorrem em qualquer etapa com texto de erro explícito (variante inválida, falha no build do cargo, biblioteca de saída ausente, falha de instalação/renomeação).
Ciclo de vida do embed (embed-native.ts)
Seção intitulada “Ciclo de vida do embed (embed-native.ts)”- Init: computa a tag de plataforma a partir de
TARGET_PLATFORM/TARGET_ARCHou dos valores do host - Conjunto de candidatos:
- x64 espera ambos
modernebaseline - não-x64 espera um arquivo padrão
- x64 espera ambos
- Valida disponibilidade em
packages/natives/native - Gera manifesto (
src/embedded-addon.ts) com importsfiledo Bun e versão do pacote - Extração em runtime pronta para o modo compilado
--reset ignora a validação e escreve um stub de manifesto nulo (embeddedAddon = null).
Fluxo de desenvolvimento local vs. comportamento compilado/distribuído
Seção intitulada “Fluxo de desenvolvimento local vs. comportamento compilado/distribuído”Fluxo de trabalho de desenvolvimento local
Seção intitulada “Fluxo de trabalho de desenvolvimento local”Loop local típico:
- Compilar o addon:
- release:
bun --cwd=packages/natives run build - perfil debug:
bun --cwd=packages/natives run dev:native
- release:
- Definir
PI_DEV=1ao testar diagnósticos do carregador - O carregador em
native.tsresolve candidatos emnative/local ao pacote (e fallback de diretório do executável) validateNativeimpõe a compatibilidade de exports antes que os wrappers utilizem o binding
Fluxo de trabalho de binário compilado/distribuído
Seção intitulada “Fluxo de trabalho de binário compilado/distribuído”No modo compilado (PI_COMPILED ou marcadores embutidos do Bun):
- O carregador computa o diretório de cache versionado:
<getNativesDir()>/<packageVersion>(operacionalmente~/.xcsh/natives/<version>) - Se o manifesto embutido corresponder à plataforma+versão atual, o carregador pode extrair o arquivo embutido selecionado para esse diretório versionado
- A ordem dos candidatos em runtime inclui:
- diretório de cache versionado
- diretório legado de binário compilado (
%LOCALAPPDATA%/xcshno Windows,~/.local/binem outros sistemas) - diretórios do pacote/executável
- O primeiro addon carregado com sucesso ainda deve passar por
validateNative
É por isso que as expectativas de empacotamento e do carregador em runtime devem estar alinhadas: nomes de arquivo, tags de plataforma e símbolos exportados devem corresponder ao que native.ts sonda e valida.
Mapeamento de API JS ↔ export Rust (subconjunto da porta de validação)
Seção intitulada “Mapeamento de API JS ↔ export Rust (subconjunto da porta de validação)”native.ts exige que esses exports visíveis em JS existam no addon carregado. Eles mapeiam para exports N-API em Rust em crates/pi-natives/src:
Nome JS exigido por validateNative | Declaração de export Rust | Arquivo-fonte Rust |
|---|---|---|
glob | #[napi] pub fn glob(...) | crates/pi-natives/src/glob.rs |
grep | #[napi] pub fn grep(...) | crates/pi-natives/src/grep.rs |
search | #[napi] pub fn search(...) | crates/pi-natives/src/grep.rs |
highlightCode | #[napi] pub fn highlight_code(...) | crates/pi-natives/src/highlight.rs |
getSystemInfo | #[napi] pub fn get_system_info(...) | crates/pi-natives/src/system_info.rs |
getWorkProfile | #[napi] pub fn get_work_profile(...) (export em camelCase) | crates/pi-natives/src/prof.rs |
invalidateFsScanCache | #[napi] pub fn invalidate_fs_scan_cache(...) | crates/pi-natives/src/fs_cache.rs |
Se algum símbolo obrigatório estiver ausente, o carregador falha imediatamente com uma dica de rebuild.
Comportamento em caso de falha e diagnósticos
Seção intitulada “Comportamento em caso de falha e diagnósticos”Falhas em tempo de build
Seção intitulada “Falhas em tempo de build”- Configuração de variante inválida:
TARGET_VARIANTdefinido em não-x64 → erro imediato- cross-build x64 sem
TARGET_VARIANTexplícito → erro imediato
- Falha no build do Cargo:
- o script exibe saída não-zero e stderr
- Artefato não encontrado:
- o script imprime cada diretório de perfil verificado
- Falha na instalação:
- mensagem explícita; no Windows inclui dica sobre arquivo bloqueado
Falhas do carregador em runtime (native.ts)
Seção intitulada “Falhas do carregador em runtime (native.ts)”- Tag de plataforma não suportada:
- lança exceção com a lista de plataformas suportadas
- Nenhum candidato pôde ser carregado:
- lança exceção com a lista completa de erros dos candidatos e dicas de correção específicas ao modo
- Exports ausentes:
- lança exceção com os nomes exatos dos símbolos ausentes e o comando de rebuild
- Problemas de extração embutida:
- erros de mkdir/escrita na extração são registrados e incluídos no diagnóstico final
Matriz de solução de problemas
Seção intitulada “Matriz de solução de problemas”| Sintoma | Causa provável | Como verificar | Correção |
|---|---|---|---|
Native addon missing exports ... Missing: <name> | Binário .node desatualizado, nome do export Rust incompatível ou binário errado carregado | Execute com PI_DEV=1 para ver o caminho carregado; inspecione a lista de exports desse arquivo | Recompile com build; certifique-se de que o nome do export #[napi] em Rust (ou alias explícito quando necessário) corresponda à chave JS; remova arquivos versionados/em cache desatualizados |
| Máquina x64 carrega baseline quando modern é esperado | PI_NATIVE_VARIANT=baseline, AVX2 não detectado ou apenas arquivo baseline presente | Verifique PI_NATIVE_VARIANT; inspecione native/ em busca do arquivo -modern | Compile a variante modern (TARGET_VARIANT=modern ... build) e certifique-se de que o arquivo seja distribuído |
| Cross-build produz binário inutilizável/rotulado incorretamente | Incompatibilidade entre CROSS_TARGET e TARGET_PLATFORM/TARGET_ARCH, ou TARGET_VARIANT ausente para x64 | Confirme a tupla de env e o nome do arquivo de saída | Reexecute com valores de env consistentes e TARGET_VARIANT x64 explícito |
| Binário compilado falha após atualização | Cache extraído desatualizado (~/.xcsh/natives/<versão-antiga-ou-incompatível>) ou incompatibilidade no manifesto embutido | Inspecione o diretório de nativos versionado e a lista de erros do carregador | Exclua o cache de nativos versionado para a versão do pacote e reexecute; regenere o manifesto embutido durante o empacotamento |
| O carregador verifica muitos caminhos e nenhum funciona | Incompatibilidade de plataforma ou artefato de release ausente em native/ do pacote | Verifique platformTag versus o(s) nome(s) real(is) do(s) arquivo(s) | Certifique-se de que o nome do arquivo compilado corresponda exatamente à convenção pi_natives.<platform>-<arch>(-variant).node e que o pacote inclua native/ |
embed:native falha com “Incomplete native addons” | Arquivos de variante necessários não compilados antes do embedding | Verifique a lista de esperados vs. encontrados no texto de erro | Compile os arquivos necessários primeiro (x64: ambos modern+baseline; não-x64: padrão) e então reexecute embed:native |
Comandos operacionais
Seção intitulada “Comandos operacionais”# Artefato de release para o host atualbun --cwd=packages/natives run build
# Build de artefato com perfil debugbun --cwd=packages/natives run dev:native
# Compilar variantes x64 explícitasTARGET_VARIANT=modern bun --cwd=packages/natives run buildTARGET_VARIANT=baseline bun --cwd=packages/natives run build
# Gerar manifesto de addon embutido a partir dos arquivos nativos compiladosbun --cwd=packages/natives run embed:native
# Redefinir manifesto embutido para stub nulobun --cwd=packages/natives run embed:native -- --reset