编译数据库的生成

编译数据库是一个json格式,它提供了编译源文件时的命令、参数、源文件、工作目录等信息,可以基于编译数据库对C/C++代码进行分析。一般的生成文件名为compile_commands.json

这里包含对Compilation database — Sarcasm notebook的整理。

主流的支持基于编译数据库分析的工具有:clang-checkclang-docclang-include-fixerclang-renameclang-tidyclangd

如何获得项目的编译数据库

使用cmake构建项目

原来是cmake的地方替换成cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1

生成的编译数据库形如:

[{ "directory": "/home/user/llvm/build", "arguments": ["/usr/bin/clang++", "-Irelative", "-DSOMEDEF=With spaces, quotes and \\-es.", "-c", "-o", "file.o", "file.cc"], "file": "file.cc" }, { "directory": "/home/user/llvm/build", "command": "/usr/bin/clang++ -Irelative -DSOMEDEF=\"With spaces, quotes and \\-es.\" -c -o file.o file.cc", "file": "file2.cc" }, ]

注意到这里有argumentscommand两种输出形式,一般认为arguments结果要好。

使用bazel构建项目

使用ninja构建项目

使用如下格式生成。

ninja -t compdb > compile_commands.json

使用clang编译单个文件

使用类似 clang -MJ c_struct.o.json c_struct.c -o c_struct.o的选项生成。生成的格式形如下。注意如下几个细节:

  • 生成文件的末尾的,,这并不是标准的json;同时缺乏通常的编译数据库生成的[]。因此,基于这种方案生成的编译数据库文件需要手动调整(这里提供一个自动化脚本)。
  • argumentsclang的命令被替换成非软链接的绝对路径,且添加上了一些选项如-xc--target=x86_64-pc-linux-gnu。这样的编译数据库,是使用了clang编译器而不是driver。
  • 除了arguments还有output项,且/tmp/c_struct-d6903c.oc_struct.o并不一样。

{ "directory": "/root", "file": "c_struct.c", "output": "/tmp/c_struct-3faa5e.o", "arguments": ["/usr/lib/llvm-14/bin/clang", "-xc", "c_struct.c", "--target=x86_64-pc-linux-gnu"]},

使用bear进行wrap

使用bear build这个回复中提到不建议使用scan-build中的intercept-build

优势

  • 可以搞定任何构建命令的编译数据库生成问题。
  • 生成的编译数据库使用arguments而不是command,避免了转义的问题(但很多对编译数据库的分析工具可能仅支持command项)。

不足

  • 由于bear仅监控本次实际构建的命令,因此如果是项目的增量式构建则只会输出部分编译数据库结果,但全量构建可能会非常耗时。经常会出现,"全版本动辄近一个小时,很影响效率,大部分时间都浪费在等待编译结束"。

使用compiledb对make进行wrap(推荐)

compiledb有所有bear的优势,且弥补了bear的不足;性能方面也有优势。改进之处包括:

  1. 可以跳过时间构建而只生成compile_commands.json,如compiledb -n make

  2. 可以基于build-log来生成编译数据库。

    make -Bnwk > build-log.txt compiledb --parse build-log.txt # 或 compiledb < build-log.txt # 使用管道的方式也行 make -Bnwk | compiledb -o-
  3. 使用command风格的编译数据库:

    compiledb --command-style make # 根据我的实验,在已经构建完成之后使用该命令,仍然能够得到编译数据库
    

不足:

  • 仅能够对make指令进行wrap。
    bash

    复制代码

    # 可编译 > gcc testnum.c main.c # bear可wrap > bear -- gcc testnum.c main.c #compiledb不可wrap > compiledb gcc testnum.c main.c Usage: compiledb [OPTIONS] COMMAND [ARGS]... Try 'compiledb -h' for help. Error: No such command 'gcc'.

TODO:

  • 补全citnamesintercept命令行的使用(bear相关)。
  • 补全交叉编译时的问题。
  • 补全编译数据库供基于clang的分析工具时的局限性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值