linkers-lto
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseLinkers and LTO
链接器与LTO
Purpose
用途
Guide agents through linker selection, common linker flags, link-order issues, LTO setup, and symbol-visibility management.
指导开发者完成链接器选择、常用链接器参数配置、链接顺序问题排查、LTO设置以及符号可见性管理。
Triggers
触发场景
- "I'm getting at link time"
undefined reference - "How do I enable LTO for a real project?"
- "Which linker should I use: ld, gold, or lld?"
- "How do I reduce binary size with ?"
--gc-sections - "How do I write or understand a linker script?"
- "I have duplicate symbol or weak symbol issues"
- "我在链接时遇到了错误"
undefined reference - "如何在实际项目中启用LTO?"
- "应该使用哪个链接器:ld、gold还是lld?"
- "如何通过减小二进制文件大小?"
--gc-sections - "如何编写或理解链接器脚本?"
- "我遇到了重复符号或弱符号问题"
Workflow
操作流程
1. Linker selection
1. 链接器选择
| Linker | Invocation | Strengths |
|---|---|---|
| GNU ld (BFD) | default on Linux | Universal, stable |
| gold | | Faster than ld for C++; supports LTO plugins |
| lld (LLVM) | | Fastest, parallel, required for Clang LTO |
bash
undefined| 链接器 | 调用方式 | 优势 |
|---|---|---|
| GNU ld (BFD) | Linux默认链接器 | 通用、稳定 |
| gold | | 比ld处理C++时更快;支持LTO插件 |
| lld (LLVM) | | 速度最快、支持并行处理;Clang LTO必需 |
bash
undefinedUse lld with GCC or Clang
Use lld with GCC or Clang
gcc -fuse-ld=lld -o prog ...
clang -fuse-ld=lld -o prog ...
gcc -fuse-ld=lld -o prog ...
clang -fuse-ld=lld -o prog ...
Check which linker is used
Check which linker is used
gcc -v -o prog main.c 2>&1 | grep 'Invoking'
undefinedgcc -v -o prog main.c 2>&1 | grep 'Invoking'
undefined2. Essential linker flags
2. 核心链接器参数
bash
undefinedbash
undefinedPass linker flags via compiler driver:
通过编译器驱动传递链接器参数:
-Wl,flag1,flag2 (comma-separated, no spaces)
-Wl,flag1,flag2 (逗号分隔,无空格)
-Wl,flag1 -Wl,flag2 (separate -Wl options)
-Wl,flag1 -Wl,flag2 (分开的-Wl选项)
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
-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
undefinedgcc main.c -o prog
-Wl,-rpath,/opt/mylibs/lib \ # 运行时库搜索路径 -Wl,--as-needed \ # 仅链接实际用到的库 -Wl,--gc-sections \ # 移除未使用的段(需配合-ffunction-sections -fdata-sections) -Wl,-z,relro \ # 启动后将重定位标记为只读 -Wl,-z,now \ # 启动时解析所有符号(完全RELRO) -L/opt/mylibs/lib -lfoo
-Wl,-rpath,/opt/mylibs/lib \ # 运行时库搜索路径 -Wl,--as-needed \ # 仅链接实际用到的库 -Wl,--gc-sections \ # 移除未使用的段(需配合-ffunction-sections -fdata-sections) -Wl,-z,relro \ # 启动后将重定位标记为只读 -Wl,-z,now \ # 启动时解析所有符号(完全RELRO) -L/opt/mylibs/lib -lfoo
undefined3. Link order matters (GNU ld)
3. 链接顺序很重要(GNU ld)
GNU ld processes archives left-to-right. A library must come after the objects that need it.
bash
undefinedGNU ld按从左到右的顺序处理归档文件。库必须放在需要它的目标文件之后。
bash
undefinedWrong: libfoo provides symbols needed by main.o
错误:libfoo提供了main.o需要的符号
gcc main.o -lfoo libdep.a -o prog # can fail if libdep.a needs libfoo
gcc main.o -lfoo libdep.a -o prog # 如果libdep.a依赖libfoo,可能会失败
Correct: dependencies after dependents
正确:依赖项放在被依赖项之后
gcc main.o -lfoo -ldep -o prog
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
gcc main.o -Wl,--start-group -lfoo -lbar -Wl,--end-group -o prog
--start-group/--end-group: repeat search until no new symbols resolved
--start-group/--end-group:重复搜索直到没有新符号被解析
undefinedundefined4. LTO with GCC
4. GCC下的LTO
bash
undefinedbash
undefinedCompile
编译
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
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)
链接(必须再次传递-flto)
gcc -O2 -flto -Wl,--gc-sections foo.o bar.o -o prog
gcc -O2 -flto -Wl,--gc-sections foo.o bar.o -o prog
Archives: must use gcc-ar / gcc-ranlib, not plain ar
归档文件:必须使用gcc-ar / gcc-ranlib,而非普通的ar
gcc-ar rcs libfoo.a foo.o
gcc-ranlib libfoo.a
Parallel LTO:
```bash
gcc -O2 -flto=auto foo.o bar.o -o prog # uses jobserver
gcc -O2 -flto=4 foo.o bar.o -o prog # 4 parallel jobsgcc-ar rcs libfoo.a foo.o
gcc-ranlib libfoo.a
并行LTO:
```bash
gcc -O2 -flto=auto foo.o bar.o -o prog # 使用jobserver
gcc -O2 -flto=4 foo.o bar.o -o prog # 4个并行任务5. LTO with Clang / lld
5. Clang / lld下的LTO
bash
undefinedbash
undefinedFull LTO
完整LTO
clang -O2 -flto -fuse-ld=lld foo.c bar.c -o prog
clang -O2 -flto -fuse-ld=lld foo.c bar.c -o prog
ThinLTO (faster, nearly same quality)
ThinLTO(更快,质量几乎相同)
clang -O2 -flto=thin -fuse-ld=lld foo.c bar.c -o prog
clang -O2 -flto=thin -fuse-ld=lld foo.c bar.c -o prog
LTO with cmake: set globally
CMake中启用LTO:全局设置
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`.set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) # 启用-flto
ThinLTO会缓存工作成果:后续构建中复用未修改的模块时速度更快。
缓存位置:通过`-Wl,--thinlto-cache-dir=/tmp/thinlto-cache`指定。6. Dead-code stripping
6. 死代码剥离
bash
undefinedbash
undefinedCompile with per-function/per-data sections
按函数/数据段编译
gcc -O2 -ffunction-sections -fdata-sections -c foo.c -o foo.o
gcc -O2 -ffunction-sections -fdata-sections -c foo.c -o foo.o
Link with garbage collection
链接时启用垃圾回收
gcc -Wl,--gc-sections foo.o -o prog
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`).gcc -Wl,--gc-sections -Wl,--print-gc-sections foo.o -o prog 2>&1 | head -20
在macOS上,链接器默认会剥离死代码(`-dead_strip`)。7. Symbol visibility
7. 符号可见性
Controlling visibility reduces DSO size and enables better LTO:
bash
undefined控制符号可见性可以减小DSO大小并提升LTO效果:
bash
undefinedHide all symbols by default, export explicitly
默认隐藏所有符号,显式导出指定符号
gcc -fvisibility=hidden -O2 -shared -fPIC foo.c -o libfoo.so
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:
```textattribute((visibility("default"))) int my_public_function(void);
也可以使用版本脚本:
```textfoo.ver
foo.ver
{
global: my_public_function; my_other_public;
local: *;
};
```bash
gcc -Wl,--version-script=foo.ver -shared -fPIC -o libfoo.so foo.o{
global: my_public_function; my_other_public;
local: *;
};
```bash
gcc -Wl,--version-script=foo.ver -shared -fPIC -o libfoo.so foo.o8. Common linker errors
8. 常见链接器错误
| Error | Cause | Fix |
|---|---|---|
| Missing library or wrong order | Add |
| Symbol defined in two TUs | Remove duplicate; use |
| Library not in search path | Add |
| Address overflow in relocation | Use |
| Binary needs newer glibc | Link statically or rebuild on older host |
| Archives mutually depend | Use |
| 错误 | 原因 | 解决方法 |
|---|---|---|
| 缺少库或链接顺序错误 | 添加 |
| 符号在两个翻译单元中定义 | 移除重复定义;使用 |
| 库不在搜索路径中 | 添加 |
| 重定位时地址溢出 | 使用 |
| 二进制文件需要更新版本的glibc | 静态链接或在旧版本主机上重新构建 |
| 归档文件之间相互依赖 | 使用 |
9. Linker map file
9. 链接器映射文件
bash
undefinedbash
undefinedGenerate 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](references/flags.md).gcc -Wl,-Map=prog.map -o prog foo.o bar.o
less prog.map
映射文件可用于调试二进制文件大小和符号位置。
关于链接器和LTO参数的完整参考,请查看[references/flags.md](references/flags.md)。Related skills
相关技能
- Use for examining the resulting binary
skills/binaries/elf-inspection - Use or
skills/compilers/gccfor compile-phase LTO flagsskills/compilers/clang - Use for
skills/binaries/binutils,ar,stripobjcopy
- 使用检查生成的二进制文件
skills/binaries/elf-inspection - 使用或
skills/compilers/gcc获取编译阶段的LTO参数skills/compilers/clang - 使用操作
skills/binaries/binutils、ar、stripobjcopy