2.2. 命令行使用:scan-build 和 CodeChecker

本文档提供有关从命令行在整个项目上运行静态分析器的指南。CodeChecker 和 scan-build 是用于在多个文件(翻译单元)上使用 CSA 的两个 CLI 工具。两者都提供了一种驱动分析器、检测编译标志和生成报告的方法。CodeChecker 维护得更为积极,它提供用于处理流行编译器的多个版本的启发式算法,并且还附带基于 Web 的 GUI 用于查看、过滤、分类和抑制结果。因此,如果您需要上述任何功能,或者只是需要更一般的可定制性,建议使用 CodeChecker。

2.2.1. CodeChecker 和 scan-build 的比较

静态分析器最初旨在作为 GUI 工具供 XCode IDE 使用。它的目的是在程序中查找有问题的执行路径,而查看非交互式标准输出很难理解这些路径。但是,可以从命令行调用静态分析器以获取分析结果,然后稍后在图形界面中交互式地查看它们。以下工具通常用于从命令行运行分析器。这两个工具都是包装脚本,用于驱动分析以及 Clang 编译器的底层调用

  1. scan-build 是一种旧的简单命令行工具,它在编译项目时将静态分析器警告作为 HTML 文件发出。您可以在 Web 浏览器中查看分析结果。
    • 适用于只需要在桌面上查看静态分析结果的个人开发人员,或者是在非常简单的协作环境中。

    • 适用于所有主要平台(Windows、Linux、macOS),并且在许多 Linux 发行版中都可用作软件包。

    • 不支持跨翻译单元分析。

  2. CodeChecker 是一种驱动程序和 Web 服务器,它根据需要在您的项目上运行静态分析器,并维护一个问题数据库。
    • 非常适合在协作环境中管理大量的静态分析器警告。

    • 通常比 scan-build 功能更丰富。

    • 支持增量分析:结果可以存储在数据库中,后续分析运行可以进行比较,以列出新添加的缺陷。

    • 跨翻译单元 (CTU) 分析 在 Linux 上通过 CodeChecker 获得完全支持。

    • 也可以运行 clang-tidy 检查器。

    • 开源,但不在树外,即不是 LLVM 项目的一部分。

2.2.2. scan-build

scan-build 是一种命令行实用程序,允许用户在执行常规构建(从命令行)时在其代码库上运行静态分析器。

2.2.2.1. 它是如何工作的?

在项目构建期间,当编译源文件时,静态分析器也会同时对其进行分析。

构建完成后,结果将通过 Web 浏览器显示给用户。

2.2.2.2. 它适用于任何构建系统吗?

scan-build 对您如何构建代码了解甚少。它的工作原理是覆盖 CCCXX 环境变量,以(希望)将您的构建更改为使用“假”编译器,而不是通常用于构建项目的编译器。此假编译器执行 clanggcc(取决于平台)来编译您的代码,然后执行静态分析器来分析您的代码。

这种“穷人插值”在许多情况下都能很好地工作,但在其他情况下却会失败。请参考此页面上的信息,了解如何充分利用 scan-build,其中包括当上述技巧无法使用时如何使其工作。

../../_images/scan_build_cmd.png ../../_images/analyzer_html.png

在 Web 浏览器中查看静态分析器结果

2.2.2.3. 基本用法

scan-build 的基本用法旨在保持简单:只需将“scan-build”放在构建命令前面即可

$ scan-build make
$ scan-build xcodebuild

在第一种情况下,scan-build 分析了使用 make 构建的项目的代码,而在第二种情况下,scan-build 分析了使用 xcodebuild 构建的项目。

以下是调用 scan-build 的一般格式

$ scan-build [scan-build options] <command> [command options]

在操作上,scan-build 会将所有后续选项传递给 <command> 来真正运行 <command>。例如,可以将 -j4 传递给 make 以在 4 个内核上进行并行构建

$ scan-build make -j4

在几乎所有情况下,scan-build 不会尝试解释构建命令后的选项;它只是将它们传递过去。一般来说,scan-build 应该支持并行构建,但不支持 分布式构建

还可以使用 scan-build 分析特定文件

$ scan-build gcc -c t1.c t2.c

此示例将导致分析文件 t1.ct2.c

2.2.2.4. 适用于 Windows 用户

Windows 用户必须安装 Perl 才能使用 scan-build。

scan-build.bat 脚本允许您以与上述基本用法部分中描述相同的方式启动 scan-build。若要从任意位置调用 scan-build,请将包含 scan-build.bat 的文件夹的路径添加到 PATH 环境变量中。

如果您在使用 MinGW/MSYS 运行 scan-build 时遇到意外的编译/制作问题,以下信息可能会有所帮助

  • 如果您在使用 Windows cmd 中的 MSYS make 构建时遇到意外的 "fatal error: no input files",请尝试以下解决方案之一:- 使用 MinGW mingw32-make 而不是 MSYS make,并将 MSYS 的路径从 PATH 中排除,以防止 mingw32-make 使用 MSYS 实用程序。MSYS 实用程序依赖于 MSYS 运行时,不打算从 Windows cmd 运行。具体来说,当传递用于执行时,使用反斜杠引用的 makefile 命令可能会严重损坏。- 从 sh shell 运行 make

    $ scan-build [scan-build options] sh -c "make [make options]"
    
  • 如果您在使用 GNU Make 3.81 时遇到 "Error : *** target pattern contains no `%'",请尝试使用其他版本的 make。

2.2.2.5. 其他选项

如上所述,可以将额外选项传递给 scan-build。这些选项位于构建命令之前。例如

$ scan-build -k -V make
$ scan-build -k -V xcodebuild

以下是部分有用选项

  • -o:HTML 报告文件的目标目录。将根据需要创建子目录来表示分析器的单独“运行”。如果未指定此选项,则将在 /tmp 中创建一个目录来存储报告。

  • -h (或无参数):显示所有 scan-build 选项。

  • -k, –keep-going:在指定的构建命令中添加“继续执行”选项。此选项当前支持 makexcodebuild。这是一个便捷选项;可以使用构建选项直接指定此行为。

  • -v:来自 scan-build 和分析器的详细输出。 第二个和第三个“-v”会提高详细程度,这对于针对分析器提交错误报告非常有用。

  • -V:构建命令完成后,在 Web 浏览器中查看分析结果。

  • –use-analyzer Xcode (或) –use-analyzer [clang 路径]scan-build 使用相对于自身的“clang”可执行文件进行静态分析。可以使用此选项通过使用 Xcode(在 OS X 上)或 PATH 中打包的“clang”来覆盖此行为。

可以通过运行 scan-build 并省略参数来获取所有选项的完整列表。

2.2.2.6. scan-build 的输出

scan-build 的输出是一组 HTML 文件,每个文件代表一个单独的错误报告。将生成单个 index.html 文件来查看所有错误。然后,您只需在 Web 浏览器中打开 index.html 即可查看错误报告。

HTML 文件的生成位置由传递给 scan-build-o 选项指定。如果没有指定 -o,则将在 /tmp 中创建一个目录来存储这些文件(scan-build 将打印一条消息告诉您它们在哪里)。如果您希望在构建完成后立即查看报告,请将 -V 传递给 scan-build

2.2.2.8. 始终在项目的“调试”配置中分析项目

大多数项目都可以在启用断言的“调试”模式下构建。静态分析器会拾取断言以修剪不可行的路径,在某些情况下,这可以极大地减少工具发出的误报(虚假错误报告)数量。

另一个选择是使用 scan-build 工具的 --force-analyze-debug-code 标志,这将自动启用断言。

2.2.2.9. 调试 scan-build 时使用详细输出

scan-build 接受一个 **-v** 选项来输出有关其操作的详细信息;两个 **-v** 选项会输出更多信息。将 scan-build 的输出重定向到文本文件(确保重定向标准错误)对于提交针对 scan-build 或分析器的错误报告非常有用,因为我们可以看到传递给分析器的确切选项(和文件)。为了获得更易懂的日志,不要进行并行构建。

2.2.2.10. 通过 scan-build 运行 ‘./configure’

如果要分析的项目使用 autoconf 生成的 configure 脚本,则可能需要通过 scan-build 运行 configure 脚本才能分析项目。

示例:

$ scan-build ./configure
$ scan-build --keep-cc make

configure 也需要通过 scan-build 运行的原因是 scan-build 通过插入编译器来扫描源文件。此插入目前由 scan-build 临时设置环境变量 CCccc-analyzer 来完成。程序 ccc-analyzer 就像一个假的编译器,将它的命令行参数转发给编译器以执行常规编译,并将它们转发给 clang 以执行静态分析。

运行 configure 通常会生成带有硬编码编译器路径的 makefile,通过 scan-build 运行 configure 会将该路径设置为 ccc-analyzer

2.2.2.11. 分析 iPhone 项目

从概念上讲,用于 iPhone 应用程序的 Xcode 项目几乎与用于桌面应用程序的项目相同。**scan-build** 也可以分析这些项目,但用户经常会遇到从命令行构建 iPhone 项目的问题,因为他们需要采取一些额外的准备步骤(例如,设置代码签名)。

2.2.2.12. 建议:使用“构建并分析”

分析 iPhone 项目的最简单方法是使用 Xcode 中的 分析功能(基于静态分析器)。用户可以在菜单中直接分析他们的项目,而无需进行大多数后面描述的设置。

本网站上提供了说明,介绍如何使用分析器的开源版本来替换捆绑在 Xcode 中的版本。

2.2.2.13. 直接使用 scan-build

如果你想在 iPhone 项目中使用 **scan-build**,请牢记以下几点

  • Debug 配置中分析你的项目,方法是使用 Xcode 将其设置为你的配置,或者将 -configuration Debug 传递给 xcodebuild

  • 使用 Simulator 作为你的基本 SDK 来分析你的项目。可以在针对设备时分析你的代码,但这在使用 Xcode 的构建并分析功能时要容易得多。

  • 检查你的代码签名 SDK 是否也设置为模拟器 SDK,并确保此选项设置为 Don't Code Sign

请注意,你可以在不修改项目的情况下完成大部分操作。例如,如果你的应用程序面向 iPhoneOS 2.2,你可以从命令行以以下方式运行 **scan-build**

$ scan-build xcodebuild -configuration Debug -sdk iphonesimulator2.2

或者,如果你的应用程序面向 iPhoneOS 3.0

$ scan-build xcodebuild -configuration Debug -sdk iphonesimulator3.0

2.2.2.14. 问题:使用正确的编译器

请记住,**scan-build** 通过使用编译器编译项目并使用 clang 分析项目来分析你的项目。该脚本使用简单的启发式方法来确定应该使用哪个编译器(默认情况下在 Darwin 上使用 clang,在其他平台上使用 gcc)。在分析 iPhone 项目时,**scan-build** 可能会选择错误的编译器,而不是 Xcode 用于构建项目的编译器。例如,这可能是因为你的系统上可能安装了多个版本的编译器,尤其是在你为 iPhone 进行开发时。

在编译你的应用程序以在模拟器上运行时,确保 **scan-build** 找到了 gcc/clang 的正确版本非常重要。否则,你可能会看到奇怪的构建错误,这些错误只在运行 scan-build 时才会发生。

**scan-build** 提供了 --use-cc--use-c++ 选项来硬编码 scan-build 应该用于构建代码的编译器。请注意,虽然你主要对分析你的项目感兴趣,但请记住,运行分析器与构建密切相关,无法编译代码意味着它将无法完全分析(如果有的话)。

如果你不确定 Xcode 使用哪个编译器来构建你的项目,尝试运行 xcodebuild(不使用 **scan-build**)。你应该会看到 Xcode 使用的编译器的完整路径,并将其用作 --use-cc 的参数。

2.2.3. CodeChecker

2.2.3.1. 基本用法

按照此处的说明安装 CodeChecker:CodeChecker 安装指南

创建编译数据库。如果你使用 cmake,则将 -DCMAKE_EXPORT_COMPILE_COMMANDS=1 参数传递给 cmake。Cmake 将创建一个 compile_commands.json 文件。如果你有基于 Makefile 或类似的构建系统,则可以使用 CodeChecker 的帮助来记录构建命令

make clean
CodeChecker log -b "make" -o compile_commands.json

分析你的项目

CodeChecker analyze compile_commands.json -o ./reports

查看分析结果。在命令行中打印详细结果

CodeChecker parse --print-steps ./reports

或在浏览器中查看详细结果

CodeChecker parse ./reports -e html -o ./reports_html
firefox ./reports_html/index.html

可选:将分析结果存储在数据库中

mkdir ./ws
CodeChecker server -w ./ws -v 8555 &
CodeChecker store ./reports --name my-project --url http://localhost:8555/Default

可选:在你的 Web 浏览器中管理(分类、抑制)结果

firefox http://localhost:8555/Default

2.2.3.2. 详细用法

有关扩展文档,请参阅 CodeChecker 的官方网站