这是一个经典问题,在嵌入式开发中尤为重要。主要原因可以归结为以下几点:
✅ 1. 链接方式不同
build.sh
使用的是:
bash
arm-none-eabi-gcc -c ...
arm-none-eabi-ld ... -T blue_pill.ld
而 CMake
默认使用的是:
bash
arm-none-eabi-gcc ... -T blue_pill.ld
虽然都能生成 .elf
,gcc
调用 ld
时自动添加了一堆默认库和启动文件,如:
crt0.o
libc.a
libgcc.a
_start
入口__libc_init_array()
调用
这会导致:
- 生成文件大小变大
- 运行逻辑不同(比如多了
libc
初始化)
✅ 2. 启动文件和链接脚本行为不同
你的 build.sh
明确用 -Ttext=$FLASH_BASE
和自定义 .ld
,手动控制内存布局、入口地址。
而 CMake 如果没有强制指定:
cmake
add_link_options(-Ttext=0x08000000 -T your_linker.ld)
或者:
cmake
add_link_options(-nostartfiles -nostdlib)
它很可能链接的是:
- 错误的启动地址(默认
_start
) - 自动插入的
crt0.o
- 新lib初始化代码
- 更改了
stack
,heap
默认符号(比如_stack
、_end
)
✅ 3. 编译选项不同
你的 build.sh
用的是:
bash
-O2 -fno-hosted -fno-inline -fno-align-functions -ffunction-sections -fdata-sections
但在 CMake
里你用了:
cmake
add_compile_options(-Og -g) # Debug
即便链接脚本一样,优化等级不同也会极大影响 .elf
和 .bin
的大小,甚至行为(比如函数没被内联或链接器无法优化函数段合并)。
✅ 4. 汇编预处理路径不同
你用了 .s
文件且其中有 #include
其他 .s
,这要求你确保:
cmake
add_compile_options(-Wa,-I${CMAKE_SOURCE_DIR}/src)
缺失这个会导致 descriptors_audio.s
没被编进 .elf
,最终 .bin
更小,功能缺失。
✅ 5. 是否 strip/debug 信息
你的 build.sh
调用了 --strip-debug
(虽然用错位置了,但有可能有效),而 CMake 没有。
.elf
大小区别 ≠.bin
实际写入闪存的区别
但 strip
会影响 .elf
体积(调试符号被去除),在一些上传/烧录工具中甚至影响校验行为。
✅ 6. 默认链接库行为
如果你没有加 -nostdlib
,GCC 会默认链接这些:
text
libc.a
libm.a
libgcc.a
它们会加入如下代码:
- 浮点支持(可能不需要)
- 除法函数(比如
__aeabi_uidiv
) _exit()
等(如果你没实现可能链接失败)
🧪 ✅ 如何验证差异:
- 对比
.elf
的节区:
bash
arm-none-eabi-size -A your.elf
你会看到:
.text
,.data
,.bss
,.init
,.fini
等差异- 看是否有
libgcc
,crt0.o
的残留代码段
- 用
nm
工具查看符号:
bash
arm-none-eabi-nm -n your.elf | less
特别检查:
- 是否有
_start
,__libc_init_array
,__aeabi_*
,__libc_fini_array
- 用
readelf -a
或objdump
看指令节/布局。
🛠 推荐你在 CMake 中添加以下保证一致性:
cmake
# 防止插入 crt0.o / libc / libgcc
add_link_options(-nostdlib -nostartfiles)
# 禁止 C++ RTTI 和异常支持(如有)
add_compile_options(-fno-exceptions -fno-rtti)
# 加入链接脚本 + 明确入口地址
add_link_options(-T ${LINKER_SCRIPT} -Ttext=0x08000000)
# 汇编 include 支持
add_compile_options(-Wa,-I${CMAKE_SOURCE_DIR}/src)
✅ 总结一句话:
build.sh
是你完全掌控编译流程,CMake 如果不特别配置,会加进很多 GCC 默认行为 ------ 包括启动代码、链接库、调试符号、浮点支持等。这就导致生成文件大小、内容、行为都可能不同 。Cmake 需要加 add_link_options(-nostartfiles -nostdlib)