极致优化可执行文件大小
指令
shell
gcc file.c -Os -flto -ffunction-sections -fdata-sections \
-fomit-frame-pointer -fno-inline -ffast-math \
-fmerge-all-strings -s -DNDEBUG \
-fno-asynchronous-unwind-tables -fno-unwind-tables \
-Wl,--build-id=none -Wl,--nmagic -fno-stack-check \
-fno-stack-protector -fno-rtti -fno-exceptions \
-Wl,-z,norelro -fuse-ld=gold -m32 -fno-plt \
-Wl,--gc-sections -Wl,--as-needed
含义
这些参数组合通过移除调试信息、禁用安全检查、优化代码生成和链接过程,能够显著减小最终二进制文件的大小,但可能会牺牲执行速度、调试能力和安全性,因此主要用于对体积有严格限制的特殊场景。
编译阶段参数(影响代码生成)
-Os
:告诉编译器优先优化代码大小(而非执行速度),这是最核心的大小优化选项-flto
:启用链接时优化(Link-Time Optimization),允许编译器在链接阶段跨文件进行优化-ffunction-sections
:将每个函数放入单独的代码段,便于链接器后续移除未使用的函数-fdata-sections
:将每个全局变量放入单独的数据段,便于链接器移除未使用的数据-fomit-frame-pointer
:省略栈帧指针,减少生成的指令数量(可能影响调试)-fno-inline
:禁用函数内联(与-Os
可能冲突,通常-Os
会适度内联)-ffast-math
:启用快速数学运算,牺牲部分精度换取更小更快的代码-fmerge-all-strings
:合并所有相同的字符串常量,减少重复存储-s
:移除可执行文件中的符号表和调试信息-DNDEBUG
:定义NDEBUG宏,禁用assert()等调试相关代码-fno-asynchronous-unwind-tables
:禁用异步 unwind 表(用于异常处理)-fno-unwind-tables
:禁用 unwind 表(用于栈展开)-fno-stack-check
:禁用栈检查(安全性降低,代码更小)-fno-stack-protector
:禁用栈保护机制(安全性降低,代码更小)-fno-rtti
:禁用C++运行时类型信息(仅C++有效)-fno-exceptions
:禁用C++异常处理(仅C++有效)-fno-plt
:禁用过程链接表(PLT),减少间接调用开销和代码大小-m32
:生成32位架构的代码(通常比64位代码更小)
链接阶段参数(通过-Wl,
传递给链接器)
--build-id=none
:不生成构建ID,减少额外信息--nmagic
:生成"纯"可执行文件,不使用分页对齐,减小文件大小-z,norelro
:禁用RELRO(重定位只读)保护,牺牲安全性换取更小体积--gc-sections
:启用垃圾回收,移除未使用的代码段和数据段--as-needed
:仅链接真正需要的库,减少不必要的依赖
其他参数
-fuse-ld=gold
:使用gold链接器(比传统ld链接器更快,且有时能生成更小的代码)