在构建期间捕获所有编译器调用和命令行参数
Capture all compiler invocations and command line parameters during build
我想要 运行 静态工具 C/C++(可能还有 Python、Java 等)代码分析,用于在帮助下构建的大型软件项目make
。众所周知,make
(或任何其他构建工具)为指定的源代码文件调用编译器和类似工具。也可以通过定义环境变量来控制编译,稍后通过其参数传递给编译器。
准确静态分析的关键是提供与传递给编译器的路径完全相同的定义和包含路径(基本上是所有 -D
和 -I
参数)。这样,该工具将能够遵循编译器遵循的相同代码路径。
问题是,项目的高度复杂性意味着无法静态确定此类环境,因为不同的文件是使用不同的 defines/include 路径集和其他编译标志构建的。
这个想法是,应该能够以某种方式捕获编译器的单个调用,以及为每个输入文件传递给它的所有参数。有了这些信息并经过直接过滤(例如,无需知道 -O
优化级别或 -W
警告设置),应该可以为每个输入文件调用静态分析器defines/includes 仅用于该输入文件。
问题是:是否存在 tools/workflows 实现我所描述的想法的方法? 我最感兴趣的是 POSIX 系统的解决方案, 但也欢迎 Windows 的想法。
我自己想到的一些想法。
最简单的解决方案是收集 make
输出并在之后进行处理。但是,某些项目的 makefile 规则可以提供非常简洁的输出而不是冗长的输出,因此可能需要对 Makefile 进行一些修改,这并不总是可取的。并行构建也可能会混淆它们的控制台输出并且无法解析。适应其他构建系统(Cmake)也不是一件容易的事,所以它远不是最方便的方式。
运行 make
在 ptrace
下并记录所有 exec*
系统调用对应于启动新应用程序的调用,包括编译器调用。然后需要解析 ptrace
的输出。这种方法与构建系统和语言无关(将捕获任何编译器对任何语言的所有调用)并且应该适用于并行构建。然而,它似乎在技术上更复杂。由于 ptrace
坐在 make
的背上导致构建过程的性能下降也不清楚。将它移植到 Windows 也将更加困难,因为程序跟踪 API 在那里有些不同。
Windows(以及最近 Linux AFAIK)上的 C++ 专有静态分析器 PVS-Studio 似乎实现了第二种方法,但是有关它们如何实现的详细信息是欢迎。如果有其他IDEs/tools已经有类似我需要的东西,请分享他们的信息。
VERBOSE=true
是默认的 make 选项,用于显示带有所有参数的所有命令。例如,它也适用于 CMake。
您可能想看看 Coverity。他们将他们的工具附加到编译器以获取编译器接收到的所有内容。您可以覆盖环境变量 CC
或 CXX
以首先收集所有内容,然后像往常一样调用编译器。
Linux编译参数的收集方式有以下几种:
覆盖环境 CC/CXX 变量。它用于 Clang Analyzer 的实用程序 scan-build。此方法仅适用于 Make 的简单项目。
procfs - 有关进程的所有信息都存储在 /proc/PID/...
中。从磁盘读取是一个缓慢的过程,您可能无法接收有关构建的所有进程的信息。
strace 实用程序(ptrace 库)。该实用程序的输出包含很多有用的信息,但需要进行复杂的解析,因为信息是随机写入的。如果您不使用许多线程来构建项目,这是一种收集有关进程信息的相当可靠的方法。用于PVS-Studio.
JSON CMake 中的编译数据库。您可以使用定义 -DCMAKE_EXPORT_COMPILE_COMMANDS=On
获取所有编译参数。如果项目不依赖 non-standard 环境变量,这是一种可靠的方法。此外,CMake 的项目可能会编写错误并发出不正确的 Json,尽管这不会影响项目构建。 PVS-Studio.
支持
Bear 实用程序(使用 LD_PRELOAD 的函数替换)。您可以获得任何项目的 JSON 数据库编译。但是如果没有环境变量,某些项目将无法 运行 分析器。此外,您不能将它用于已经使用 LD_PRELOAD 进行构建的项目。 PVS-Studio.
支持
正在为 PVS-Studio 收集有关在 Windows 中编译的信息:
Visual Studio API获取标准工程的编译参数;
MSBuild API获取标准项目的编译参数;
Win API 获取任何编译过程的信息,例如,Windows 任务管理器就是这样做的。
我想要 运行 静态工具 C/C++(可能还有 Python、Java 等)代码分析,用于在帮助下构建的大型软件项目make
。众所周知,make
(或任何其他构建工具)为指定的源代码文件调用编译器和类似工具。也可以通过定义环境变量来控制编译,稍后通过其参数传递给编译器。
准确静态分析的关键是提供与传递给编译器的路径完全相同的定义和包含路径(基本上是所有 -D
和 -I
参数)。这样,该工具将能够遵循编译器遵循的相同代码路径。
问题是,项目的高度复杂性意味着无法静态确定此类环境,因为不同的文件是使用不同的 defines/include 路径集和其他编译标志构建的。
这个想法是,应该能够以某种方式捕获编译器的单个调用,以及为每个输入文件传递给它的所有参数。有了这些信息并经过直接过滤(例如,无需知道 -O
优化级别或 -W
警告设置),应该可以为每个输入文件调用静态分析器defines/includes 仅用于该输入文件。
问题是:是否存在 tools/workflows 实现我所描述的想法的方法? 我最感兴趣的是 POSIX 系统的解决方案, 但也欢迎 Windows 的想法。
我自己想到的一些想法。
最简单的解决方案是收集
make
输出并在之后进行处理。但是,某些项目的 makefile 规则可以提供非常简洁的输出而不是冗长的输出,因此可能需要对 Makefile 进行一些修改,这并不总是可取的。并行构建也可能会混淆它们的控制台输出并且无法解析。适应其他构建系统(Cmake)也不是一件容易的事,所以它远不是最方便的方式。运行
make
在ptrace
下并记录所有exec*
系统调用对应于启动新应用程序的调用,包括编译器调用。然后需要解析ptrace
的输出。这种方法与构建系统和语言无关(将捕获任何编译器对任何语言的所有调用)并且应该适用于并行构建。然而,它似乎在技术上更复杂。由于ptrace
坐在make
的背上导致构建过程的性能下降也不清楚。将它移植到 Windows 也将更加困难,因为程序跟踪 API 在那里有些不同。Windows(以及最近 Linux AFAIK)上的 C++ 专有静态分析器 PVS-Studio 似乎实现了第二种方法,但是有关它们如何实现的详细信息是欢迎。如果有其他IDEs/tools已经有类似我需要的东西,请分享他们的信息。
VERBOSE=true
是默认的 make 选项,用于显示带有所有参数的所有命令。例如,它也适用于 CMake。
您可能想看看 Coverity。他们将他们的工具附加到编译器以获取编译器接收到的所有内容。您可以覆盖环境变量 CC
或 CXX
以首先收集所有内容,然后像往常一样调用编译器。
Linux编译参数的收集方式有以下几种:
覆盖环境 CC/CXX 变量。它用于 Clang Analyzer 的实用程序 scan-build。此方法仅适用于 Make 的简单项目。
procfs - 有关进程的所有信息都存储在
/proc/PID/...
中。从磁盘读取是一个缓慢的过程,您可能无法接收有关构建的所有进程的信息。strace 实用程序(ptrace 库)。该实用程序的输出包含很多有用的信息,但需要进行复杂的解析,因为信息是随机写入的。如果您不使用许多线程来构建项目,这是一种收集有关进程信息的相当可靠的方法。用于PVS-Studio.
JSON CMake 中的编译数据库。您可以使用定义
-DCMAKE_EXPORT_COMPILE_COMMANDS=On
获取所有编译参数。如果项目不依赖 non-standard 环境变量,这是一种可靠的方法。此外,CMake 的项目可能会编写错误并发出不正确的 Json,尽管这不会影响项目构建。 PVS-Studio. 支持
Bear 实用程序(使用 LD_PRELOAD 的函数替换)。您可以获得任何项目的 JSON 数据库编译。但是如果没有环境变量,某些项目将无法 运行 分析器。此外,您不能将它用于已经使用 LD_PRELOAD 进行构建的项目。 PVS-Studio.
支持
正在为 PVS-Studio 收集有关在 Windows 中编译的信息:
Visual Studio API获取标准工程的编译参数;
MSBuild API获取标准项目的编译参数;
Win API 获取任何编译过程的信息,例如,Windows 任务管理器就是这样做的。