关于 linkers-lto
面向 Agent 的链接器与 LTO 技能,涵盖链接器选择、链接参数、链接顺序、符号可见性及常见错误排查。
主要功能
- 01选择 GNU ld、gold 或 lld
- 02配置常用链接参数和链接顺序
- 03设置 GCC 或 Clang 的 LTO
- 04通过节回收剔除未用代码
- 05控制符号可见性并生成映射文件
适用场景
- 01排查 undefined 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
目的
引导 Agent 选择链接器、使用常见链接器标志、处理链接顺序问题、设置 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' | 符号在两个 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检查生成的二进制文件 - 使用
skills/compilers/gcc或skills/compilers/clang查看编译阶段的 LTO 标志 - 使用
skills/binaries/binutils了解ar、strip、objcopy
评论
支持 Markdown