skills/binaries/linkers-lto/SKILL.md
Linker and Link-Time Optimisation (LTO) skill. Use when configuring GNU ld, gold, or lld linker flags, diagnosing link-order issues or undefined symbols at link time, enabling LTO safely in real projects, or understanding inter-module optimisation trade-offs. Activates on queries about linker flags, -flto, thin LTO, LTCG, --gc-sections, link order errors, weak symbols, or linker scripts.
npx skillsauth add mohitmishra786/low-level-dev-skills linkers-ltoInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Guide agents through linker selection, common linker flags, link-order issues, LTO setup, and symbol-visibility management.
undefined reference at link time"--gc-sections?"| Linker | Invocation | Strengths |
|--------|-----------|-----------|
| GNU ld (BFD) | default on Linux | Universal, stable |
| gold | -fuse-ld=gold | Faster than ld for C++; supports LTO plugins |
| lld (LLVM) | -fuse-ld=lld | Fastest, parallel, required for Clang LTO |
# Use lld with GCC or Clang
gcc -fuse-ld=lld -o prog ...
clang -fuse-ld=lld -o prog ...
# Check which linker is used
gcc -v -o prog main.c 2>&1 | grep 'Invoking'
# Pass linker flags via compiler driver:
# -Wl,flag1,flag2 (comma-separated, no spaces)
# -Wl,flag1 -Wl,flag2 (separate -Wl options)
gcc main.c -o prog \
-Wl,-rpath,/opt/mylibs/lib \ # runtime library search path
-Wl,--as-needed \ # only link libraries that are actually used
-Wl,--gc-sections \ # remove unused sections (requires -ffunction-sections -fdata-sections)
-Wl,-z,relro \ # mark relocations read-only after startup
-Wl,-z,now \ # resolve all symbols at startup (full RELRO)
-L/opt/mylibs/lib -lfoo
GNU ld processes archives left-to-right. A library must come after the objects that need it.
# Wrong: libfoo provides symbols needed by main.o
gcc main.o -lfoo libdep.a -o prog # can fail if libdep.a needs libfoo
# Correct: dependencies after dependents
gcc main.o -lfoo -ldep -o prog
# If there are circular deps between archives:
gcc main.o -Wl,--start-group -lfoo -lbar -Wl,--end-group -o prog
# --start-group/--end-group: repeat search until no new symbols resolved
# Compile
gcc -O2 -flto -ffunction-sections -fdata-sections -c foo.c -o foo.o
gcc -O2 -flto -ffunction-sections -fdata-sections -c bar.c -o bar.o
# Link (must pass -flto again)
gcc -O2 -flto -Wl,--gc-sections foo.o bar.o -o prog
# Archives: must use gcc-ar / gcc-ranlib, not plain ar
gcc-ar rcs libfoo.a foo.o
gcc-ranlib libfoo.a
Parallel LTO:
gcc -O2 -flto=auto foo.o bar.o -o prog # uses jobserver
gcc -O2 -flto=4 foo.o bar.o -o prog # 4 parallel jobs
# Full LTO
clang -O2 -flto -fuse-ld=lld foo.c bar.c -o prog
# ThinLTO (faster, nearly same quality)
clang -O2 -flto=thin -fuse-ld=lld foo.c bar.c -o prog
# LTO with cmake: set globally
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) # enables -flto
ThinLTO caches work: subsequent builds that reuse unchanged modules are faster.
Cache location: specify with -Wl,--thinlto-cache-dir=/tmp/thinlto-cache.
# Compile with per-function/per-data sections
gcc -O2 -ffunction-sections -fdata-sections -c foo.c -o foo.o
# Link with garbage collection
gcc -Wl,--gc-sections foo.o -o prog
# Verify what was removed
gcc -Wl,--gc-sections -Wl,--print-gc-sections foo.o -o prog 2>&1 | head -20
On macOS, the linker strips dead code by default (-dead_strip).
Controlling visibility reduces DSO size and enables better LTO:
# Hide all symbols by default, export explicitly
gcc -fvisibility=hidden -O2 -shared -fPIC foo.c -o libfoo.so
# In source, mark exports:
__attribute__((visibility("default"))) int my_public_function(void);
Or use a version script:
# foo.ver
{
global: my_public_function; my_other_public;
local: *;
};
gcc -Wl,--version-script=foo.ver -shared -fPIC -o libfoo.so foo.o
| Error | Cause | Fix |
|-------|-------|-----|
| undefined reference to 'foo' | Missing library or wrong order | Add -lfoo; move after the object that needs it |
| multiple definition of 'foo' | Symbol defined in two TUs | Remove duplicate; use static or extern |
| cannot find -lfoo | Library not in search path | Add -L/path/to/lib; install dev package |
| relocation truncated | Address overflow in relocation | Use -mcmodel=large; restructure image |
| version 'GLIBC_2.33' not found | Binary needs newer glibc | Link statically or rebuild on older host |
| circular reference | Archives mutually depend | Use --start-group/--end-group |
# Generate a map file (shows symbol → section → file)
gcc -Wl,-Map=prog.map -o prog foo.o bar.o
less prog.map
Useful for debugging binary size and symbol placement.
For a comprehensive linker and LTO flags reference, see references/flags.md.
skills/binaries/elf-inspection for examining the resulting binaryskills/compilers/gcc or skills/compilers/clang for compile-phase LTO flagsskills/binaries/binutils for ar, strip, objcopydevelopment
Zig testing skill for writing and running tests. Use when using zig build test, writing comptime tests, using test filters, working with test allocators to detect leaks, or using Zig's built-in fuzz testing (0.14+). Activates on queries about Zig tests, zig test, zig build test, comptime testing, test allocators, Zig fuzz testing, or detecting memory leaks in Zig tests.
development
Zig debugging skill. Use when debugging Zig programs with GDB or LLDB, interpreting Zig runtime panics, using std.debug.print for tracing, configuring debug builds, or debugging Zig programs in VS Code. Activates on queries about debugging Zig, Zig panics, zig gdb, zig lldb, std.debug.print, Zig stack traces, or Zig error return traces.
tools
Zig cross-compilation skill. Use when cross-compiling Zig programs to different targets, using Zig's built-in cross-compilation for embedded, WASM, Windows, ARM, or using zig cc to cross-compile C code without a system cross-toolchain. Activates on queries about Zig cross-compilation, zig target triples, zig cc cross-compile, Zig embedded targets, or Zig WASM.
development
Zig comptime skill for compile-time evaluation and metaprogramming. Use when using comptime parameters, comptime types, generics via anytype, comptime reflection with @typeInfo, or metaprogramming patterns that replace C++ templates. Activates on queries about Zig comptime, compile-time evaluation, Zig generics, anytype, @typeInfo, comptime types, or Zig metaprogramming.