Cross-Compilation em Zig — O que é e Como Usar
Definição
Cross-compilation (compilação cruzada) é a capacidade de compilar código em uma máquina (host) para ser executado em uma plataforma diferente (target). Zig foi projetado desde o início para suportar cross-compilation de forma nativa, sem necessidade de instalar toolchains adicionais. Basta passar o flag -target para compilar para mais de 30 arquiteturas e sistemas operacionais.
Isso contrasta com C/C++, onde cross-compilation tipicamente exige instalar cross-toolchains específicas, configurar sysroots e lidar com incompatibilidades entre versões.
Por que Cross-Compilation Importa
- Desenvolvimento embarcado: Compilar para ARM, RISC-V ou MIPS diretamente do seu PC x86.
- Distribuição multiplataforma: Gerar binários para Linux, macOS e Windows a partir de uma única máquina.
- CI/CD simplificado: Build pipelines podem gerar todos os artefatos em uma única plataforma.
- Sem toolchains extras: O Zig já inclui tudo necessário para cross-compilation.
Exemplo Prático
Cross-Compilation Básica
# Compilar para Linux x86_64 (a partir de qualquer plataforma)
zig build-exe src/main.zig -target x86_64-linux-gnu
# Compilar para macOS ARM (Apple Silicon)
zig build-exe src/main.zig -target aarch64-macos
# Compilar para Windows x86_64
zig build-exe src/main.zig -target x86_64-windows-gnu
# Compilar para ARM embarcado (bare metal)
zig build-exe src/main.zig -target arm-freestanding-none
# Compilar para WebAssembly
zig build-exe src/main.zig -target wasm32-freestanding
Via build.zig
const std = @import("std");
pub fn build(b: *std.Build) void {
// standardTargetOptions permite -Dtarget= na linha de comando
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "app",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
b.installArtifact(exe);
}
// Uso:
// zig build -Dtarget=aarch64-linux-gnu
// zig build -Dtarget=x86_64-windows-gnu -Doptimize=ReleaseFast
Código Condicional por Plataforma
const std = @import("std");
const builtin = @import("builtin");
pub fn main() void {
const os_nome = switch (builtin.os.tag) {
.linux => "Linux",
.macos => "macOS",
.windows => "Windows",
.freestanding => "Bare Metal",
else => "Outro",
};
const arch_nome = switch (builtin.cpu.arch) {
.x86_64 => "x86_64",
.aarch64 => "AArch64",
.arm => "ARM",
.riscv64 => "RISC-V 64",
.wasm32 => "WebAssembly",
else => "Outra",
};
std.debug.print("Plataforma: {s} / {s}\n", .{ os_nome, arch_nome });
}
Targets Suportados (Principais)
| Arquitetura | Sistemas |
|---|---|
x86_64 | Linux, macOS, Windows, FreeBSD |
aarch64 | Linux, macOS (Apple Silicon) |
arm | Linux, freestanding (embarcado) |
riscv64 | Linux, freestanding |
wasm32 | freestanding, wasi |
mips | Linux |
powerpc64 | Linux |
Armadilhas Comuns
- ABI do sistema:
-gnue-muslproduzem binários diferentes. Use-muslpara binários estáticos portáveis no Linux. - Bibliotecas do sistema: Cross-compilation com
linkSystemLibrarypode falhar se a biblioteca não estiver disponível para o target. - Paths do host: Cuidado ao usar caminhos absolutos em comptime — eles são do host, não do target.
- Endianness: Algumas arquiteturas são big-endian. Código que assume little-endian pode ter bugs.
- Testar no target: Compilar é metade do trabalho — teste o binário na plataforma-alvo.
Termos Relacionados
- Target Triple — Formato de especificação de plataforma
- build.zig — Configuração de cross-compilation no build
- Release Modes — Otimizações por modo de build
- LLVM — Backend que gera código para múltiplas arquiteturas