如何在clang python绑定中使用compile_commands.json?
我有下面的脚本,试图打印出给定C++文件中的所有AST节点。在简单的文件中使用它时,它可以很好地工作(头文件在同一个目录中,等等)。如何在clang python绑定中使用compile_commands.json?
#!/usr/bin/env python
from argparse import ArgumentParser, FileType
from clang import cindex
def node_info(node):
return {'kind': node.kind,
'usr': node.get_usr(),
'spelling': node.spelling,
'location': node.location,
'file': node.location.file.name,
'extent.start': node.extent.start,
'extent.end': node.extent.end,
'is_definition': node.is_definition()
}
def get_nodes_in_file(node, filename, ls=None):
ls = ls if ls is not None else []
for n in node.get_children():
if n.location.file is not None and n.location.file.name == filename:
ls.append(n)
get_nodes_in_file(n, filename, ls)
return ls
def main():
arg_parser = ArgumentParser()
arg_parser.add_argument('source_file', type=FileType('r+'),
help='C++ source file to parse.')
arg_parser.add_argument('compilation_database', type=FileType('r+'),
help='The compile_commands.json to use to parse the source file.')
args = arg_parser.parse_args()
compilation_database_path = args.compilation_database.name
source_file_path = args.source_file.name
clang_args = ['-x', 'c++', '-std=c++11', '-p', compilation_database_path]
index = cindex.Index.create()
translation_unit = index.parse(source_file_path, clang_args)
file_nodes = get_nodes_in_file(translation_unit.cursor, source_file_path)
print [p.spelling for p in file_nodes]
if __name__ == '__main__':
main()
不过,我得到一个clang.cindex.TranslationUnitLoadError: Error parsing translation unit.
,当我运行该脚本,并提供了在其父目录compile_commands.json文件的有效的C++文件。这段代码运行并使用CMake与叮当良好建立,但我似乎无法弄清楚如何正确地指向compile_commands.json传递参数。
我在clang文档中也找不到这个选项,并且无法使-ast-dump
正常工作。但是,通过传递文件路径,clang-check可以正常工作!
您自己接受的答案不正确。 libclang
does support compilation databases和so does cindex.py,libclang python绑定。
混淆的主要原因可能是libclang知道/使用的编译标志只是可以传递给clang前端的所有参数的一个子集。编译数据库受支持,但不能自动工作:它必须手动加载和查询。像这样的东西应该工作:
#!/usr/bin/env python
from argparse import ArgumentParser, FileType
from clang import cindex
compilation_database_path = args.compilation_database.name
source_file_path = args.source_file.name
index = cindex.Index.create()
# Step 1: load the compilation database
compdb = cindex.CompilationDatabase.fromDirectory(compilation_database_path)
# Step 2: query compilation flags
try:
file_args = compdb.getCompileCommands(source_file_path)
translation_unit = index.parse(source_file_path, file_args)
file_nodes = get_nodes_in_file(translation_unit.cursor, source_file_path)
print [p.spelling for p in file_nodes]
except CompilationDatabaseError:
print 'Could not load compilation flags for', source_file_path
从我可以告诉Libclang不支持编译数据库,但Libtooling。为了解决这个问题,我以compile_commands.json
作为参数,最后自己解析它以找到感兴趣的文件和相关的包含文件(-I
和-isystem
包含)。
我的答案是不正确的,请参阅接受的答案。 – Lucas
第一次引入了什么版本的clang?当我写这个问题时,我使用了libclang和cindex.py的clang 3.4。 – Lucas
不知道,但我很确定,在那个时代已经有3.8多年了。 –
看起来它也是3.4,一定错过了它。 – Lucas