c++ 如何将makefile转换为JSON编译数据库?

dy2hfwbg  于 2023-03-25  发布在  其他
关注(0)|答案(7)|浏览(260)

假设我们的项目有make文件(不是cmake/premake/ninja等),它们可以为gcc和clang工作。我们想从它们生成JSON编译数据库,将其馈送到clang-modernize工具中。如何做到这一点?(clang基础设施中是否有任何解析器或一些脚本,如make CC='cc_args.py gcc' CXX='cc_args.py g++'或其他工具)?

qzlgjiam

qzlgjiam1#

我没有使用它的个人经验,但Bear似乎是针对您的场景的(它是从clang-modernize站点链接的)。

5jvtdoz2

5jvtdoz22#

Make有一个通常不受欢迎的功能,即将编译器命令行发送到其标准输出,但在这种情况下,您可以将其与shell(和jq)管道一起使用。使用GNU Make on Bash:

make --always-make --dry-run \
 | grep -wE 'gcc|g\+\+' \
 | grep -w '\-c' \
 | jq -nR '[inputs|{directory:".", command:., file: match(" [^ ]+$").string[1:]}]' \
 > compile_commands.json

在Windows上,cmd.exe语法类似:

  • 使用^代替\作为行的延续
  • 仅使用"分隔的字符串
  • 使用"""转义"分隔字符串中的"
  • 使用^^转义"分隔字符串中的^

但是,这不能处理makefile使用-C参数递归调用子目录中的自身(或其他makefile)的情况。

4urapxun

4urapxun3#

也许有人和我的情况一样。我有一个macOS,Bear生成了一个空的compile_commands.json文件。他们在README中承认了这个问题,并建议使用scan-build作为解决方案。不幸的是,我仍然得到一个空文件。我找到了两个替代解决方案:

  • compiledb,这在我的情况下工作。
  • clang++编译器的-MJ选项加上sed的组合,在这里详细介绍,它看起来很简单,很容易转换成make目标。
q1qsirdb

q1qsirdb4#

由于我还没有足够的点数来对答案做出React,我想在@Tanz87的答案下发表评论,他建议干运行make,并使用grepjq来格式化输出。
我的CMake检测到/usr/bin/c++是默认编译器(我使用的是WSL 2,Ubuntu 21.10),因此grep -wE 'gcc|g\+\+'命令不起作用,就像@Hi-Angel一样,我的compile_commands.json最终得到了[]
修复方法是也为c++使用grep,因此整个命令变为:

make --always-make --dry-run \
 | grep -wE 'gcc|g\+\+|c\+\+' \
 | grep -w '\-c' \
 | jq -nR '[inputs|{directory:".", command:., file: match(" [^ ]+$").string[1:]}]' \
 > compile_commands.json

编辑:也就是说,虽然解决方案似乎确实生成了一个compile_commands.json文件,但在build目录中运行clang-tidy会从clang后端为编译数据库中的每个文件打印一个错误:

error: no such file or directory: '&&' [clang-diagnostic-error]

compile_commands.json文件中的每个command条目如下所示:

"cd /build/src && /usr/bin/c++  -I/src/src -std=gnu++2a -o CMakeFiles/project.dir/subdir/subsubdir/sourcefile.cpp.o -c /project/src/subdir/subsubdir/sourcefile.cpp

这个项目使用CMake来生成Make构建系统文件。不幸的是,还没有解决方案。
编辑:编辑:从compile_commands.json中的每个command中删除cd /build/src &&修复了该特定错误。使用sed

sed 's|cd.*.&&||g' compile_commands.json

编辑:编辑:编辑:作为一个oneliner,它需要一些额外的斜线用于&&令牌:

make --always-make --dry-run
 | grep -wE 'gcc|g\+\+|c\+\+'
 | grep -w '\-c'
 | sed 's|cd.*.\&\&||g'
 | jq -nR '[inputs|{directory:".", command:., file: match(" [^ ]+$").string[1:]}]' \
 > compile_commands.json
arknldoa

arknldoa5#

如果您没有安装Bear/compiledb的权限,或者您无法从源代码构建Bear,那么Web应用程序可以提供帮助。
我在https://texttoolkit.com/compilation-database-generator上构建了这样一个简单的Web应用程序,它从make输出生成compile_commands.json

0sgqnhkj

0sgqnhkj6#

我把这个编译器 Package ,你可能想按摩if子句提取文件名参数。它只检测。c文件
我这样调用它:make ... CC="cc_wrapper $CC"
或:make ... CC="cc_wrapper gcc"

#! /bin/bash

# Writing to a common output file, so buffer for atomic output
if file=($(printf "%s\n" "$@" | grep '\.c$'))
then JSON="$(jq -nR '[inputs|{directory:$pwd, arguments:[$ARGS.positional[]], file:.}]' --arg pwd "$PWD" --args -- "$@" <<< "${file}")"
     # c2rust transpile "$file.compile_commands.json" will still look for a file called compile_commands.json so we have to provide it
     mkdir -p "$file.c2rs"
     echo "$JSON" > "$file.c2rs/compile_commands.json"
fi
exec "$@"
fiei3ece

fiei3ece7#

我发现对于某些make项目,compiledb能够拦截make输出并生成有效的compile_commands.json文件。然而,对于某些项目,它生成空([ ])compile_commands.json文件。对我来说总是有效的解决方案如下所示。

>make clean;make VERBOSE=y all &> make_output.txt
>compiledb --parse make_output.txt

这总是会生成一个有效的compile_commands.json文件,即使对于compiledb无法直接拦截make输出的make项目也是如此。希望这能有所帮助。

相关问题