66、【OS】【Nuttx】【构建】System.map文件生成(上)
背景
之前的 blog
63、【OS】【Nuttx】任务休眠与唤醒:sleep
64、【OS】【Nuttx】任务休眠与唤醒:clock_nanosleep
分析了任务休眠唤醒,下面先不分析优先级,来看看构建相关的内容
map文件
.map 文件是编译和链接过程中由链接器(linker)生成的一个文本文件,它记录了最终可执行程序(或固件)在内存中的布局信息,map 文件对嵌入式开发、调试和优化非常重要,使用 gcc 或 clang 工具链时,都可以生成 map 文件,map 文件提供了如下关键信息:
- 内存布局:显示各个段(section)的起始地址和大小,比如 .text, .data, .bss
- 符号地址:列出所有全局函数、变量的地址,便于调试反汇编代码
- 节区映射:展示每个源文件,函数,变量占用了多少空间,帮助分析代码膨胀,帮助内存优化
- 链接依赖:查看哪些库或目标文件被实际链接进去了,这个功能也很实用,没有被引用的库文件将会被链接优化,排除在最终目标文件之外,减少目标文件体积
- 地址冲突检查:如果多个节区重叠或超出内存范围,可以通过 map 文件发现(这个也可以通过链接选项拦截)
另外,说了 map 文件这么多功能,但仍要记住,map 文件反映的是静态链接视图下的内存布局,不包含任何动态分配的内容,静态内存分配是指那些在编译时就确定其地址和大小的变量或数据结构,主要包括:
- 全局变量:比如 int global_var; 在整个程序运行期间都存在
- 静态局部变量:比如 static int local_static; 只在定义它的函数内可见,但生命周期贯穿整个程序
- 常量:比如 const char *str = “hello”; 存放在 .rodata 段中,可映射到 flash 空间
- 函数代码:比如 void my_func() { … } 存放在 .text 段中,可映射到 flash 空间
System.map
下面来看下 nuttx 构建时,自动生成的 System.map 文件
System.map 文件的生成,可追溯到 nuttx 根目录下的 CMakeLists.txt 文件
在非 windows 系统下,使用编译工具链生成 System.map 文件,该文件包含 nuttx 中所有符号(函数、全局变量等)的地址信息,这里为什么强调非 windows 系统呢?因为如果不是在 windows 主机上构建(即是在 linux 或 macos 上),才能执行一些命令行工具(如 nm, grep, sort),这些在 windows 下不原生支持
现在来逐个看下这里面的生成代码:
add_custom_command
cmake 中的命令,用于向构建过程添加自定义的构建规则或命令,允许用户在构建过程中插入特定的任务,这对需要在编译前后进行文件生成、转换等情况非常有用,add_custom_command 在这里使用的原型如下:
add_custom_command(OUTPUT output1 [output2 ...]COMMAND command1 [ARGS] [args1...][DEPENDS depend1 depend2 ...][WORKING_DIRECTORY dir][COMMENT "comment-string"]
)
- OUTPUT 指定了命令应该生成的文件,比如 System.map
- COMMAND 是要执行的实际生成命令
- DEPENDS 列出了该命令依赖的文件,如果这些文件发生变化,则命令会被重新执行来更新 System.map 文件,这里的依赖项就是 nuttx 这个最终构建目标
先分析到这里,下篇文章继续