在构建期间捕获所有编译器调用和命令行参数

时间:2018-02-19 15:50:48

标签: c++ c makefile static-analysis ptrace

我想为make帮助构建的大型软件项目运行静态C / C ++(以及可能的Python,Java等)代码分析工具。众所周知,make(或任何其他构建工具)为指定的源代码文件调用编译器和类似工具。也可以通过定义环境变量来控制编译,以便稍后通过其参数传递给编译器。

准确静态分析的关键是提供定义和包含路径,就像它们传递给编译器一样(基本上它的所有-D-I参数)。这样,该工具将能够遵循编译器遵循的相同代码路径。

问题是,项目的高复杂性意味着无法静态地确定这样的环境,因为不同的文件是使用不同的定义/包含路径和其他编译标志构建的。

这个想法是,应该以某种方式捕获编译器的各个调用,并为每个输入文件传递给它的所有参数。有了这样的信息并且在直接过滤之后(例如,不需要知道-O优化级别或-W警告设置),应该可以为每个输入文件调用静态分析器,并使用相同的集合定义/包含仅用于该输入文件。

问题是:是否存在实现我所描述的想法的现有工具/工作流程?我最感兴趣的是POSIX系统的解决方案,但也欢迎Windows的想法。

我自己想到的一些想法。

  • 最简单的解决方案是收集make输出并在之后处理。但是,某些项目的makefile规则提供了非常简洁的输出而不是详细的输出,因此可能需要对Makefile进行一些修改,这并不总是令人满意的。并行构建也可能使其控制台输出混乱,无法解析。适应其他构建系统(Cmake)也不是一件容易的事,所以它远非最便捷的方式。

  • make下运行ptrace并记录与启动新应用程序相对应的exec*系统调用的所有调用,包括编译器调用。然后需要解析ptrace的输出。这种方法是构建系统和语言无关(将捕获任何语言的任何编译器的所有调用),并且应该适用于并行构建。然而,它似乎在技术上更复杂。由于ptrace位于make后面,构建过程的性能下降也不清楚。将它移植到Windows也会更难,因为程序跟踪API在那里有所不同。

  • Windows上的C ++专有静态分析器(以及最近的Linux AFAIK)PVS-Studio似乎实现了第二种方法,但欢迎他们如何做到这一点的细节。如果有其他IDE /工具已经有类似我需要的东西,请分享它们的信息。

2 个答案:

答案 0 :(得分:4)

有以下几种方法可以收集有关Linux编译参数的信息:

  1. 覆盖环境CC / CXX变量。它在Clang Analyzer的实用程序scan-build中使用。此方法仅对Make的简单项目可靠。

  2. procfs - 有关流程的所有信息都存储在/proc/PID/...中。从磁盘读取是一个缓慢的过程,您可能无法接收有关构建的所有进程的信息。

  3. strace实用程序(ptrace库)。此实用程序的输出包含许多有用的信息,但它需要复杂的解析,因为信息是随机写入的。如果您不使用许多线程来构建项目,那么收集有关进程的信息是一种相当可靠的方法。它用于PVS-Studio。

  4. CMake中的JSON编译数据库。您可以使用定义-DCMAKE_EXPORT_COMPILE_COMMANDS=On获取所有编译参数。如果项目不依赖于非标准环境变量,那么这是一种可靠的方法。此外,CMake项目可能会出错并发出错误的Json,尽管这不会影响项目构建。它在PVS-Studio中得到支持。

  5. Bear实用程序(使用LD_PRELOAD进行函数替换)。您可以为任何项目获取JSON数据库编译。但是如果没有环境变量,就不可能为某些项目运行分析器。此外,您不能将它用于已经使用LD_PRELOAD进行构建的项目。它在PVS-Studio中得到支持。

  6. 收集有关在Windows中为PVS-Studio编译的信息:

    1. Visual Studio API获取标准项目的编译参数;

    2. MSBuild API获取标准项目的编译参数;

    3. Win API以获取有关任何编译过程的信息,例如,Windows任务管理器执行此操作。

答案 1 :(得分:0)

VERBOSE=true是默认的make选项,用于显示包含所有参数的所有命令。例如,它也适用于CMake。

您可能需要查看Coverity。他们将他们的工具附加到编译器以获取编译器接收的所有内容。您可以覆盖环境变量CCCXX以首先收集所有内容,然后照常调用编译器。