源码阅读-嵌套宏
在源码阅读的时候,有个非常讨厌的家伙---多层嵌套宏,简单的宏还 OK,有些多则嵌套个四五层,看代码时直接血压飙升。
后来一想,编译器的预处理器不就是在预处理阶段把宏展开嘛?命令示例:
bash
$ cc -E main.c > main.i
但实际上多层嵌套的宏一般会出现在大型项目里面,而不是像上面一个的单个文件当中。那问题就转变成了:怎么在编译时保留这个预处理阶段的产生的中间临时文件?或是怎么生成这样的目标文件?这里选后者-去生成目标文件,拿 CMake 的项目来举例:
bash
# 配置、编译
$ cmake -S . -B build
$ cmake --build build -j
...
# 重点:查找对应的target 目标
$ cmake --build build/lvgl --target help | grep lv_gc.i
... src/misc/lv_gc.i
# 生成对应的目标文件
$ cmake --build build/lvgl --target src/misc/lv_gc.i
cd /Users/shibin/repo/lv_sim_vscode_sdl_8/build && /Library/Developer/CommandLineTools/usr/bin/make -f lvgl/CMakeFiles/lvgl.dir/build.make lvgl/CMakeFiles/lvgl.dir/src/misc/lv_gc.c.i
Preprocessing C source to CMakeFiles/lvgl.dir/src/misc/lv_gc.c.i
cd /Users/shibin/repo/lv_sim_vscode_sdl_8/build/lvgl && /Library/Developer/CommandLineTools/usr/bin/cc -DLV_CONF_INCLUDE_SIMPLE -DLV_LVGL_H_INCLUDE_SIMPLE -I/Users/shibin/repo/lv_sim_vscode_sdl_8 -I/opt/homebrew/Cellar/sdl2/2.26.1/include -isystem /Users/shibin/repo/lv_sim_vscode_sdl_8/lvgl -fno-omit-frame-pointer -fsanitize=undefined -fsanitize=float-cast-overflow -fsanitize-address-use-after-scope -fno-sanitize-recover -g -arch arm64 -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX13.1.sdk -E /Users/shibin/repo/lv_sim_vscode_sdl_8/lvgl/src/misc/lv_gc.c > CMakeFiles/lvgl.dir/src/misc/lv_gc.c.i
$ find . -name lv_gc.c.i
./build/lvgl/CMakeFiles/lvgl.dir/src/misc/lv_gc.c.i
$ code ./build/lvgl/CMakeFiles/lvgl.dir/src/misc/lv_gc.c.i
CMake项目默认会生成 Makefile
的构建脚本,然后调用 make 去编译项目,多层嵌套的 CMakeLists.txt
项目就会生成多层嵌套的 Makefile
脚本文件。上述前面两个命令不用多解释,是 CMake 的配置和编译,编译缓存会生成在 build 目录下,build 目录下有对应的 Makefile
文件;重点是第三四条命令 :
cmake --build build/lvgl --target help
:显示build/lvgl
下面的Makefile
里面有哪些目标;这里由于我的是多层CMake 项目,所以我去build/lvgl/Makefile
里面去查找grep lv_gc.i
:过滤查找 我要展开宏的源代码文件;如果文件名是xxx.c
,对应搜索xxx.i
cmake --build build/lvgl --target src/misc/lv_gc.i
:来去生成对应的 target 目标,就是对应源代码进行预处理的目标
最后可能需要find
搜索查找下,多层嵌套的 CMakeLists.txt
项目目录相对复杂点,使用搜索稳妥些。最后打开文件,代码格式化一下,立马清晰了,截图如下:生成的文件还会有源文件的行号注释(指示什么文件的多少行代码如下)
![](/assets/image-20230110102350586%20PM.CiTbWbY9.webp)
那如果要展开的宏在头文件中,而不是在c
文件中呢?把这个头文件包含include
到另一个c
源文件中,然后去生成这个 c
文件的目标文件。