使用clion阅读任意交叉编译软件的代码

clion是linux下比较强大的C/C++ IDE,通过扩展也可以支持很多其他语言,例如shell,lua, perl, python,rust。唯一缺点是收费,但是相对它给我带来的便利,这点费用不算什么。我一般用来开发C/C++/项目,它支持3种方式解析工程源码,分别是

  • Makefile
  • CMake
  • 编译数据库

像代码的高亮,跳转,补全,都依赖对源码的解析,其实CMake和Makefile应该是一回事,CMake最终也会生成Makefile。首先通过make分析出工程里面用到哪些源文件,然后通过内置语法分析器解析得到符号表等信息,从而实现高亮,补全等。

当你的工程是针对你开发的PC时,这些都没问题,但是如果是交叉编译时,便会由于无法通过make来获取依赖的源文件,导致接下来的语法分析也无法进行。例如基于openwrt,buildroot开发时,或者编译uboot,kernel。因为这些构建框架都有自己特定的一些环境变量,编译脚本什么的,导致clion这种IDE无法简单的通过指定工具链来执行make,来分析依赖的源文件。于是编译数据库这种方式就派上了用场。cmake可以直接生成编译数据库,通过cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1,但是嵌入式开发里面用的一些库,工具可能是基于比较古老的版本,仅支持automake, makefile等。此时需要借助另一个工具bear,ubuntu20.04上直接apt安装即可,或者源码编译。bear的用法十分的简单

bear 编译命令
#例如,builrdroot中编译某个软件
bear make xl2tpd-{dirclean,build}
#或者,openwrt中
bear make package/xl2tpd/{clean,prepare,compile}

它的工作原理好像是创建子进程执行编译命令,然后监听工具链的gcc的调用,类似strace分析gcc的调用,知道gcc执行时,参数是怎么样的,open等系统调用又是怎么样的。最终生成编译数据库文件,其实就是个json文件。这个文件里面对每个gcc处理过的文件作了记录,包括3个值:

  • gcc的参数
  • 源文件名称
  • 源文件目录
{   
        "arguments": [
            "/home/a/workspace/exc-m620d/openwrt/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-5.4.0_musl-1.1.16_eabi/bin/arm-openwrt-linux-muslgnueabi-gcc",
            "-c",
            "-Os",
            "-pipe",
            "-mcpu=cortex-a7",
            "-mfpu=neon-vfpv4",
            "-fno-caller-saves",
            "-fno-plt",
            "-fhonour-copts",
            "-Wno-error=unused-but-set-variable",
            "-Wno-error=unused-result",
            "-mfloat-abi=hard",
            "-iremap/home/a/workspace/exc-m620d/openwrt/build_dir/target-arm_cortex-a7+neon-vfpv4_musl-1.1.16_eabi/xl2tpd-devel-20151125:xl2tpd-devel-20151125",
            "-Wformat",
            "-Werror=format-security",
            "-fstack-protector",
            "-D_FORTIFY_SOURCE=1",
            "-I/home/a/workspace/exc-m620d/openwrt/staging_dir/target-arm_cortex-a7+neon-vfpv4_musl-1.1.16_eabi/usr/include",
            "-I/home/a/workspace/exc-m620d/openwrt/staging_dir/target-arm_cortex-a7+neon-vfpv4_musl-1.1.16_eabi/include",
            "-I/home/a/workspace/exc-m620d/openwrt/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-5.4.0_musl-1.1.16_eabi/usr/include",
            "-I/home/a/workspace/exc-m620d/openwrt/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-5.4.0_musl-1.1.16_eabi/include/fortify",
            "-I/home/a/workspace/exc-m620d/openwrt/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-5.4.0_musl-1.1.16_eabi/include",
            "-DDEBUG_PPPD",
            "-DTRUST_PPPD_TO_DIE",
            "-fno-builtin",
            "-Wall",
            "-DSANITY",
            "-DLINUX",
            "-I./linux/include/",
            "-DUSE_KERNEL",
            "-DIP_ALLOCATION",
            "-o",
            "call.o",
            "call.c"
        ],
        "directory": "/home/a/workspace/exc-m620d/openwrt/build_dir/target-arm_cortex-a7+neon-vfpv4_musl-1.1.16_eabi/xl2tpd-devel-20151125",
        "file": "call.c"
    }

然后语法分析器就知道分析谁了。这样就可以愉快的使用clion阅读编辑跑在ARM上的代码了。不过有个地方需要注意,如果你的交叉编译工具链是通过export到环境变量的方式来执行的,那么编译数据库的的arguments的第一项,gcc就不会是一个绝对路径,导致clion解析异常,这时只要全局替换这个编译数据库文件里面的xxx-gcc为绝对路径即可。其实我认为这个应该是bear需要改进的一个地方,bear在填这个工具链的gcc时,通过realpath就知道工具链的绝对路径。

posted @ 2023-08-29 21:05  thammer  阅读(269)  评论(0编辑  收藏  举报