本文へ移動
cccskills
無料GitHub で公開

linkers-lto

Use when choosing a linker, fixing link order or undefined symbol errors, enabling LTO or ThinLTO, or cutting dead code with --gc-sections. Not for inspecting the linked binary: use elf-inspection.

インストール方法を見る

含まれるファイル(3)

  • SKILL.md6.2 KB
  • agents/openai.yaml204 B
  • references/flags.md5.3 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Linkers and LTO

The linker turns object files into one binary and decides what survives from each translation unit. Most link failures are order problems; most size wins are LTO plus dead-code removal.

Contract

FieldBound contract
TriggerThe task fixes undefined reference or multiple definition errors, selects a linker, enables LTO or ThinLTO, removes dead code, controls symbol visibility, or reads a linker map.
AuthorityReversible local: writes only build flags, linker scripts, and build outputs; rollback is version control and a rebuild. No remote mutation.
Side effectLocal writes to the outputs the build produces and to build configuration the user names.
DoneThe link succeeds with the intended flags, or the size and visibility changes are proven by the map, --print-gc-sections, or nm -D output.

Inputs

  • The failing link command or build configuration: required.
  • Toolchain in use: required. GCC and Clang differ in LTO setup and archive tools.
  • Whether LTO must be incremental: required before choosing ThinLTO over full LTO.

Procedure

  1. Select the linker through the compiler driver. ld is the universal default, gold is the retired-in-name C++ linker kept for legacy builds, lld is the fast choice and the practical requirement for Clang LTO on large projects. Verify which linker actually ran from the driver's verbose output. Done when: the build uses the intended linker.
gcc  -fuse-ld=lld -o prog main.c
clang -fuse-ld=lld -o prog main.c
gcc -v main.c -o prog 2>&1 | grep 'collect2\|ld\.new\|lld'
  1. Pass flags correctly. The driver forwards linker flags after -Wl, with commas instead of spaces. Done when: readelf -d or the map shows the flag took effect.
gcc main.o -o prog \
  -Wl,-rpath,/opt/mylibs/lib \
  -Wl,--as-needed \
  -Wl,--gc-sections \
  -Wl,-z,relro -Wl,-z,now \
  -L/opt/mylibs/lib -lfoo
  1. Fix link order. GNU ld resolves archives left to right; a library must follow the objects that use it. Circular archive dependencies need a group. Done when: the link succeeds without suppression flags.
gcc main.o -lfoo -ldep -o prog                    # dependents first
gcc main.o -Wl,--start-group -lfoo -lbar -Wl,--end-group -o prog
  1. Enable LTO with GCC. Every compile and the final link carry -flto with the same optimization level. LTO archives must be built with gcc-ar and gcc-ranlib, because plain ar cannot build the LTO symbol index. Done when: the link succeeds and size or performance improves against the non-LTO build.
gcc -O2 -flto -ffunction-sections -fdata-sections -c foo.c -o foo.o
gcc -O2 -flto -Wl,--gc-sections foo.o bar.o -o prog
gcc-ar rcs libfoo.a foo.o
gcc-ranlib libfoo.a
gcc -O2 -flto=auto foo.o bar.o -o prog   # parallel, uses the make jobserver
  1. Enable ThinLTO with Clang. ThinLTO parallelizes across machines and caches results, so incremental links stay fast. Done when: the link succeeds and the ThinLTO cache directory fills.
clang -O2 -flto=thin -fuse-ld=lld foo.c bar.c -o prog

In CMake, set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) selects the right LTO mode per compiler.

  1. Remove dead code. --gc-sections discards unreferenced sections, which only exist if compilation used -ffunction-sections -fdata-sections. Done when: --print-gc-sections reports the removals and the binary still runs.
gcc -O2 -ffunction-sections -fdata-sections -c foo.c -o foo.o
gcc -Wl,--gc-sections -Wl,--print-gc-sections foo.o -o prog
  1. Control visibility for LTO quality and DSO size. Hide everything, export the API. Done when: nm -D --defined-only libfoo.so lists only the public API.
gcc -fvisibility=hidden -O2 -shared -fPIC foo.c -o libfoo.so
# foo.ver
{
  global: my_public_function; my_other_public;
  local: *;
};
gcc -Wl,--version-script=foo.ver -shared -fPIC -o libfoo.so foo.o
  1. Read the map file when size or placement puzzles. Every symbol's origin and address is in the map. Done when: the surprising symbol is traced to its object and input section.
gcc -Wl,-Map=prog.map -o prog foo.o bar.o
  1. Diagnose by error class. Done when: each error maps to its row and the fix is applied.
ErrorCauseFix
undefined reference to 'foo'Missing or misordered libraryAdd -lfoo after the objects that need it
multiple definition of 'foo'Symbol defined in two objectsKeep one definition, or declare the other extern
cannot find -lfooLibrary outside -L pathsAdd -L or install the development package
relocation truncated to fitAddress outside the relocation's reachUse -mcmodel=large, or restructure the image layout
version 'GLIBC_2.xx' not foundBuilt on a newer glibcBuild on the older host or link statically
LTO bytecode mismatchMixed LTO and non-LTO objectsRecompile every object with the same -flto
file format not recognizedForeign architecture objectUse the matching cross toolchain for all objects

Failure and recovery

Failure classBehavior
LTO build fails on one objectThat object was compiled without -flto. Recompile it with the same flags as the rest.
--gc-sections removed a needed sectionSomething referenced it only from assembly or a linker script. Add KEEP(*(...)) in the script, or the reference.
ThinLTO cache grows without boundPoint -Wl,--thinlto-cache-dir at a managed path and clear it on a schedule.
A group link got slow--start-group rescans archives until fixed point. Resolve the cycle explicitly instead of leaving the group in place.
LTO changed behaviorInlining across units can expose latent UB. Reproduce without LTO, then fix the source.

Output

The linked binary plus the evidence for each decision: linker chosen, map excerpts, --print-gc-sections output, or nm -D export lists. The full flag tables, lld extras, MSVC /GL /LTCG, and a linker script skeleton are in references/flags.md.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Use when explaining System V AMD64, ARM AAPCS, RISC-V psABI, stack frames, variadic calls, or FFI register rules. Not for the Rust FFI binding layer: use rust-ffi.

日本語の概要は準備中です。原文の説明を表示しています。

OutlineDriven/odin-claude-plugin372026年9月29日 更新

Use when configuring ADC sampling time, DMA-driven ADC, calibration, or DAC channel setup on bare-metal MCUs. Not for the DMA stream itself: use dma-baremetal.

日本語の概要は準備中です。原文の説明を表示しています。

OutlineDriven/odin-claude-plugin372026年9月29日 更新

af-xdp

無料

Use when creating AF_XDP sockets, configuring UMEM and XSK rings, writing an XDP redirect program, or choosing copy versus zero-copy mode. Not for full kernel bypass: use dpdk.

日本語の概要は準備中です。原文の説明を表示しています。

OutlineDriven/odin-claude-plugin372026年9月29日 更新

Use when a completed session needs an agent-environment retrospective. Not for an engineering retrospective from telemetry: use engineering-retrospective.

日本語の概要は準備中です。原文の説明を表示しています。

OutlineDriven/odin-claude-plugin372026年9月29日 更新

Use when a redacted, trimmed agent transcript must be appended to a GitHub PR or issue body, with human approval and preview. Not for automated or model-initiated insertion.

日本語の概要は準備中です。原文の説明を表示しています。

OutlineDriven/odin-claude-plugin372026年9月29日 更新

agents-md

無料

Use when a repo needs agent setup, AGENTS.md added or made lean, CLAUDE.md audited, or agent instructions scored or pruned. Not for remote, credential, publish, deploy, or irreversible changes.

日本語の概要は準備中です。原文の説明を表示しています。

OutlineDriven/odin-claude-plugin372026年9月29日 更新

OutlineDriven のスキルをすべて見る

このスキルの問題を報告する