我正在尝试获取每个编译单元的编译参数,以便我可以为我的 vcxproj 创建可与 clang 的 libTooling 一起使用的“compilation_commands.json”。
libTooling 教程 建议使用
CompilationDatabase
为项目中的所有 cpp 文件提供编译参数。本教程显示 CMake 可以为基于 CMake 的项目生成compilation_commands.json。
由于 clang 可以通过
clang.exe --driver-mode=cl
或 clang-cl.exe
进入“MSVC 模式”,我的想法是,如果我可以获得 VS2012 项目中每个 cpp 文件的编译参数,我可以为 vcxproj 创建compilation_commands.json。
但是,我在 VS2012 SDK 中找不到用于遍历 vcxproj 并检索每个编译单元的编译参数的 API。有人能给我指出正确的 API 吗?
我知道这确实很旧,但问题仍然相关,所以对于那些仍在寻找答案的人来说,我最近终于使用 this 小 VS 扩展做到了这一点。
只需安装它,就会出现一个新的“Sourcetrail”菜单,其中包含“创建编译数据库”条目(我发现需要启用 Intellisense 才能单击)。这将让您自定义要包含的内容并生成一个
compile_commands.json
,您可以将其与其他基于 clang 的工具等一起使用。
您可以尝试解析中间目录下的CL.command.*文件。
https://gist.github.com/Trass3r/f3fbe6807d28106e917368c33abf45d4
这是一项 DIY 工作。 VS IDE 项目具有每个 .cpp 文件的属性。通过选择 .cpp,然后右键单击 -> 属性 -> 配置属性 -> C/C++ -> 命令行,您将获得编译该特定文件所需的选项。 64 美元的问题是如何为项目/解决方案中的每个文件执行此操作。答案并不简单,但它是可行的。至少我在 VS 2010 上做到了,并且我很确定它可以在 VS 2012/3 上工作
秘密在于所谓的 VCEngine。它是一个评估项目中所有属性或文件的工具。所以真正的问题是如何评估每个文件的“命令行”属性。您需要遍历所有 .cpp 文件并为“命令行”属性调用 VCProject 的 Evaluate 方法。
我认为最简单的方法是为 VS IDE 编写一个插件,从而访问 VCEngine 实例。有很多关于如何做到这一点的例子。请注意,VCEngine 与版本相关。
无论如何,对于具有数千个.cpp文件的项目/解决方案,您需要自动创建编译数据库。
等我有时间我会把解决方案放在github上
您可能有兴趣阅读本文 compile_commands.json 适用于 Windows/MSVC
您可以通过劫持编译器来做到这一点。主要缺点是您将不再收到编译器二进制文件的名称。
将此 Python 脚本嵌入到
cc.bat
中(这还会将 INCLUDE=...
环境变量转换为 /external:I...
参数):@python3 -u -s -E -I -c "import io, json, os, subprocess, sys; argv = sys.argv[1:]; cc = 'cl.exe'; includes = ['/external:I' + s for s in os.getenv('INCLUDE', '').split(os.pathsep) if s]; is_resp = len(argv) > 0 and argv[0].startswith('@'); cmdline = io.open(argv[0][1:], 'r', encoding='utf-16-le').read().lstrip('\uFEFF') if is_resp else None; filename = (cmdline[cmdline.rfind('\x22', 0, len(cmdline) - 2):].strip('\x22') if cmdline.rstrip().endswith('\x22') else cmdline[cmdline.rfind(' ') + 1:]) if is_resp else argv[-1]; json.dump({'directory': os.getcwd(), 'file': filename, ('command' if is_resp else 'arguments'): subprocess.list2cmdline([cc]) + ' ' + cmdline + (' ' + subprocess.list2cmdline(includes) if includes else '') if is_resp else [cc] + argv + includes}, sys.stdout)" %*
然后调用 MSBuild,并将
MultiProcCL
设置为 true
(这很重要,因为否则您将在同一编译命令中收到多个文件名):MSBuild -noLogo -v:m -t:ClCompile -p:BuildInParallel=false -m:1 -p:MultiProcCL=true -p:CLToolExe="%CD%\cc.bat"
现在标准输出上有一堆 JSON 行,每个文件一个,您可以使用逗号手动连接(并嵌入括号内)以创建 JSON 数组。