如何在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可以正常工作!

您自己接受的答案不正确。 libclangdoes support compilation databasesso 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 
+0

第一次引入了什么版本的clang?当我写这个问题时,我使用了libclang和cindex.py的clang 3.4。 – Lucas

+0

不知道,但我很确定,在那个时代已经有3.8多年了。 –

+0

看起来它也是3.4,一定错过了它。 – Lucas

从我可以告诉Libclang不支持编译数据库,但Libtooling。为了解决这个问题,我以compile_commands.json作为参数,最后自己解析它以找到感兴趣的文件和相关的包含文件(-I-isystem包含)。

+0

我的答案是不正确的,请参阅接受的答案。 – Lucas