Linkar Biblioteca C em Zig — Resolver Problemas de Linkagem
A interoperabilidade com C é uma das grandes forças do Zig. Quando a linkagem com bibliotecas C falha, este guia ajuda a diagnosticar e resolver.
Erro: “undefined symbol”
Causa: O linker não encontra a implementação de uma função C.
error: undefined symbol: 'sqlite3_open'
Soluções:
// No build.zig — adicionar a biblioteca
exe.linkSystemLibrary("sqlite3");
exe.linkLibC(); // Necessário para qualquer código C
// Se a biblioteca está em local não padrão:
exe.addLibraryPath(.{ .cwd_relative = "/usr/local/lib" });
exe.addIncludePath(.{ .cwd_relative = "/usr/local/include" });
# Verificar se a biblioteca está instalada
# Linux
ldconfig -p | grep sqlite3
pkg-config --libs sqlite3
# macOS
brew list sqlite3
Erro: “library not found”
Causa: A biblioteca não está instalada ou o caminho está errado.
# Instalar a biblioteca faltante
# Ubuntu/Debian
sudo apt install libsqlite3-dev
# Fedora
sudo dnf install sqlite-devel
# macOS
brew install sqlite3
# Verificar o caminho
pkg-config --cflags --libs sqlite3
// Se usando pkg-config:
exe.linkSystemLibrary("sqlite3");
// Zig usa pkg-config automaticamente quando disponível
Erro: “@cImport falha”
Causa: Headers C não encontrados ou com erros de parsing.
// PROBLEMA: header não encontrado
const c = @cImport(@cInclude("minha_lib.h")); // Falha
// SOLUÇÃO 1: Adicionar caminho do include no build.zig
exe.addIncludePath(b.path("include"));
exe.addIncludePath(.{ .cwd_relative = "/usr/local/include" });
// SOLUÇÃO 2: Usar caminho completo
const c = @cImport(@cInclude("/usr/include/sqlite3.h"));
// No build.zig — configuração completa
const exe = b.addExecutable(.{
.name = "app",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
// Headers
exe.addIncludePath(b.path("vendor/include"));
// Bibliotecas
exe.addLibraryPath(b.path("vendor/lib"));
exe.linkSystemLibrary("minha_lib");
exe.linkLibC();
Erro: “incompatible types from @cImport”
Causa: Tipos C não mapeiam diretamente para tipos Zig.
const c = @cImport(@cInclude("lib.h"));
// PROBLEMA: tipos C são traduzidos diferentemente
// char* em C vira [*c]u8 em Zig
// SOLUÇÃO: Cast explícito
const resultado = c.funcao_c();
const zig_string: [*:0]const u8 = resultado; // Se terminado em null
const slice = std.mem.span(zig_string); // Converter para slice
Compilando Código C junto com Zig
// No build.zig — compilar arquivos .c como parte do projeto
exe.addCSourceFiles(.{
.files = &.{
"src/lib.c",
"src/utils.c",
},
.flags = &.{
"-Wall",
"-Wextra",
"-std=c11",
},
});
// Incluir diretórios de headers
exe.addIncludePath(b.path("src"));
exe.linkLibC();
Linkando Biblioteca Estática (.a / .lib)
// No build.zig
exe.addObjectFile(b.path("vendor/libminha.a"));
// Ou adicionar o diretório e nome
exe.addLibraryPath(b.path("vendor/lib"));
exe.linkSystemLibrary("minha"); // procura libminha.a
Linkando Biblioteca Dinâmica (.so / .dylib / .dll)
// No build.zig
exe.linkSystemLibrary("curl"); // procura libcurl.so
// Especificar que é dinâmica
exe.linkSystemLibrary2("curl", .{ .preferred_link_mode = .dynamic });
// Para rpath (Linux)
exe.addRPath(.{ .cwd_relative = "/opt/lib" });
Problemas com Ponteiros C
const c = @cImport(@cInclude("lib.h"));
// Ponteiros C ([*c]T) são "opcionais" em Zig
// Precisam ser verificados antes de usar
const ptr: ?*c.struct_data = c.get_data();
if (ptr) |p| {
// Usar p com segurança
std.debug.print("valor: {d}\n", .{p.*.campo});
} else {
std.debug.print("Ponteiro null retornado\n", .{});
}
Problemas com Callbacks C
const c = @cImport(@cInclude("lib.h"));
// Callback de Zig para C precisa de callconv(.C)
fn meuCallback(dados: ?*anyopaque) callconv(.C) void {
if (dados) |d| {
const valor: *i32 = @ptrCast(@alignCast(d));
std.debug.print("Callback: {d}\n", .{valor.*});
}
}
pub fn main() void {
var x: i32 = 42;
c.registrar_callback(meuCallback, &x);
}
Diagnóstico de Linkagem
# Ver símbolos de uma biblioteca
nm -D /usr/lib/libsqlite3.so | grep sqlite3_open
# Ver dependências de um binário
ldd ./zig-out/bin/meu-app
# Compilação verbose para ver comandos do linker
zig build --verbose
# Verificar pkg-config
pkg-config --cflags --libs openssl
Checklist de Linkagem
- Verifique se a biblioteca está instalada (
-devou-develpackage) - Adicione
exe.linkLibC()no build.zig - Adicione
exe.linkSystemLibrary("nome") - Adicione caminhos de include se necessário
- Para cross-compilation, inclua os fontes C ou use bibliotecas estáticas
- Teste com
--verbosepara ver os comandos do linker
Veja Também
- FAQ Build System — Configuração de build
- Cross-Compile Falha — Problemas de cross-compilation
- Erros no build.zig — Erros gerais do build system
- FAQ Zig vs Outras Linguagens — Interop com C/C++
- Receitas — Exemplos de uso de bibliotecas C