Linker Error — Como Resolver em Zig

Linker Error — Como Resolver em Zig

O Que Este Erro Significa

Erros de linker em Zig ocorrem na etapa final da compilação, quando o linker tenta combinar o código objeto compilado com bibliotecas externas para gerar o executável ou biblioteca final. O linker precisa resolver todos os símbolos (funções, variáveis) referenciados pelo código — se algum símbolo não é encontrado ou há conflito, o processo falha.

Mensagens típicas:

error: undefined symbol: funcao_externa
error: library not found: -lssl
error: relocation overflow

Estes erros são mais comuns ao usar interoperabilidade com C (@cImport), bibliotecas externas ou cross-compilation.

Causas Comuns

1. Biblioteca C Não Instalada

const c = @cImport({
    @cInclude("openssl/ssl.h");
});
// ERRO DE LINKER: library not found: -lssl

2. Símbolo Externo Não Definido

// Declaração de função externa que não existe
extern fn funcao_que_nao_existe() void;

pub fn main() void {
    funcao_que_nao_existe(); // ERRO: undefined symbol
}

3. Falta Vincular Biblioteca no build.zig

// build.zig — SEM linkagem da biblioteca
const exe = b.addExecutable(.{
    .name = "meu-projeto",
    .root_source_file = b.path("src/main.zig"),
    .target = target,
    .optimize = optimize,
});
// Falta: exe.linkSystemLibrary("ssl");

4. Biblioteca Estática Não Encontrada

$ zig build
# error: unable to find library: -lminha_lib
# library search paths: /usr/lib, /usr/local/lib

5. Conflito de Símbolos Duplicados

// Dois módulos exportam a mesma função
export fn processar() void {} // Módulo A
export fn processar() void {} // Módulo B
// ERRO: duplicate symbol: processar

Como Corrigir

Solucao 1: Instalar Bibliotecas de Desenvolvimento

# Ubuntu/Debian
$ sudo apt install libssl-dev libz-dev

# Fedora/RHEL
$ sudo dnf install openssl-devel zlib-devel

# macOS
$ brew install openssl zlib

# Após instalar, rebuild
$ zig build

Solucao 2: Vincular Biblioteca no build.zig

// build.zig
const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    const exe = b.addExecutable(.{
        .name = "meu-projeto",
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    // Vincular bibliotecas do sistema
    exe.linkSystemLibrary("ssl");
    exe.linkSystemLibrary("crypto");
    exe.linkSystemLibrary("z");

    // Vincular libc (necessário para muitas bibliotecas C)
    exe.linkLibC();

    b.installArtifact(exe);
}

Solucao 3: Adicionar Caminhos de Busca de Bibliotecas

// build.zig
const exe = b.addExecutable(.{
    .name = "meu-projeto",
    .root_source_file = b.path("src/main.zig"),
    .target = target,
    .optimize = optimize,
});

// Adicionar caminhos de busca
exe.addLibraryPath(.{ .cwd_relative = "/usr/local/lib" });
exe.addIncludePath(.{ .cwd_relative = "/usr/local/include" });

exe.linkSystemLibrary("minha_lib");
exe.linkLibC();

Solucao 4: Vincular Biblioteca Estática Diretamente

// build.zig
const exe = b.addExecutable(.{
    .name = "meu-projeto",
    .root_source_file = b.path("src/main.zig"),
    .target = target,
    .optimize = optimize,
});

// Vincular arquivo .a ou .lib diretamente
exe.addObjectFile(.{ .cwd_relative = "libs/libminha_lib.a" });
exe.linkLibC();

Solucao 5: Compilar Código C junto com Zig

// build.zig
const exe = b.addExecutable(.{
    .name = "meu-projeto",
    .root_source_file = b.path("src/main.zig"),
    .target = target,
    .optimize = optimize,
});

// Compilar arquivo C como parte do projeto
exe.addCSourceFile(.{
    .file = b.path("src/utils.c"),
    .flags = &.{ "-Wall", "-O2" },
});

exe.linkLibC();

Solucao 6: Cross-Compilation com Bibliotecas Bundled

// build.zig — para cross-compilation
const exe = b.addExecutable(.{
    .name = "meu-projeto",
    .root_source_file = b.path("src/main.zig"),
    .target = target,
    .optimize = optimize,
});

// Use bibliotecas que Zig traz embutidas
exe.linkLibC(); // libc do target
// Zig inclui implementações de muitas bibliotecas comuns

Diagnóstico

Verificar Bibliotecas Disponíveis

# Linux — listar bibliotecas instaladas
$ ldconfig -p | grep ssl

# macOS
$ brew list openssl --prefix

# Verificar se pkg-config encontra a biblioteca
$ pkg-config --libs openssl

Ver Símbolos em uma Biblioteca

# Listar símbolos de uma biblioteca estática
$ nm /usr/lib/libssl.a | grep SSL_connect

# Listar símbolos de uma biblioteca compartilhada
$ nm -D /usr/lib/libssl.so | grep SSL_connect

Verbose Mode do Linker

# Zig com output verbose do linker
$ zig build -verbose

Cross-Compilation e Linker

Ao compilar para outro sistema, o linker precisa das bibliotecas do alvo:

// build.zig — cross-compilation
const target = b.resolveTargetQuery(.{
    .cpu_arch = .x86_64,
    .os_tag = .linux,
    .abi = .musl, // musl é estático — evita problemas de linking
});

const exe = b.addExecutable(.{
    .name = "meu-projeto",
    .root_source_file = b.path("src/main.zig"),
    .target = target,
    .optimize = optimize,
});

// musl libc é bundled com Zig — funciona em cross-compilation
exe.linkLibC();

Erros Relacionados

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.