linkers-lto について
リンカーと LTO を扱うエージェント向けのスキルです。リンカーの選択、フラグ、リンク順序、シンボル可視性、リンク時のエラー対処を説明します。
主な機能
- 01GNU ld、gold、lld の選択
- 02リンカーフラグとライブラリ順序の設定
- 03GCC または Clang での LTO 設定
- 04未使用セクションの削除
- 05シンボル可視性とマップファイルの管理
活用シーン
- 01undefined reference エラーの診断
- 02プロジェクトでの LTO 有効化
- 03バイナリサイズの削減
- 04重複シンボルや循環依存の調査
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ mohitmishra786/ low-level-dev-skills --skill linkers-ltoインストール後、Claude Code で/linkers-ltoを入力して読み込まれたか確認します。
同梱ファイルreferences/flags.md
詳細
リンカーと LTO
目的
リンカーの選択、よく使われるリンカーフラグ、リンク順序の問題、LTO の設定、シンボル可視性の管理について、エージェントを案内します。
トリガー
- 「リンク時に
undefined referenceが発生します」 - 「実際のプロジェクトで LTO を有効にする方法を教えてください」
- 「
ld、gold、lldのどのリンカーを使うべきですか?」 - 「
--gc-sectionsでバイナリサイズを小さくする方法を教えてください」 - 「リンカースクリプトの書き方や読み方を教えてください」
- 「重複シンボルまたは弱シンボルの問題が発生しています」
ワークフロー
1. リンカーの選択
| リンカー | 呼び出し方 | 長所 |
|---|---|---|
| GNU ld (BFD) | Linux でのデフォルト | 汎用的で安定しています |
| gold | -fuse-ld=gold | C++ では ld より高速です。LTO プラグインをサポートします |
| lld (LLVM) | -fuse-ld=lld | 最速で並列処理に対応し、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'
2. 基本的なリンカーフラグ
# 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
3. リンク順序が重要です(GNU ld)
GNU ld はアーカイブを左から右へ処理します。ライブラリは、それを必要とするオブジェクトの後に指定する必要があります。
# 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
4. GCC での LTO
# 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
並列 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
5. Clang / lld での LTO
# 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 は作業内容をキャッシュします。変更されていないモジュールを再利用する以降のビルドは高速になります。
キャッシュの場所:-Wl,--thinlto-cache-dir=/tmp/thinlto-cache で指定します。
6. デッドコードの除去
# 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
macOS では、リンカーがデフォルトでデッドコードを除去します(-dead_strip)。
7. シンボル可視性
可視性を制御すると、DSO サイズを削減でき、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);
または、バージョンスクリプトを使用します。
# foo.ver
{
global: my_public_function; my_other_public;
local: *;
};
gcc -Wl,--version-script=foo.ver -shared -fPIC -o libfoo.so foo.o
8. よくあるリンカーエラー
| エラー | 原因 | 対処方法 |
|---|---|---|
undefined reference to 'foo' | ライブラリが指定されていないか、順序が間違っています | -lfoo を追加し、それを必要とするオブジェクトの後に移動します |
multiple definition of 'foo' | シンボルが 2 つの TU で定義されています | 重複を削除するか、static または extern を使用します |
cannot find -lfoo | ライブラリが検索パスにありません | -L/path/to/lib を追加するか、開発用パッケージをインストールします |
relocation truncated | 再配置でアドレスがオーバーフローしています | -mcmodel=large を使用するか、イメージの構成を変更します |
version 'GLIBC_2.33' not found | バイナリがより新しい glibc を必要としています | 静的リンクするか、より古いホスト上で再ビルドします |
circular reference | アーカイブが相互に依存しています | --start-group/--end-group を使用します |
9. リンカーマップファイル
# Generate a map file (shows symbol → section → file)
gcc -Wl,-Map=prog.map -o prog foo.o bar.o
less prog.map
バイナリサイズとシンボルの配置をデバッグする際に役立ちます。
リンカーと LTO のフラグについて詳しくは、references/flags.md を参照してください。
関連スキル
- 生成されたバイナリの検査には
skills/binaries/elf-inspectionを使用します - コンパイルフェーズの LTO フラグには
skills/compilers/gccまたはskills/compilers/clangを使用します ar、strip、objcopyにはskills/binaries/binutilsを使用します
コメント
Markdown 対応