cmake-instrumentation(7)

4.0 版本新增。

简介

注意

此功能仅在已通过 CMAKE_EXPERIMENTAL_INSTRUMENTATION 门启用实验性检测支持时可用。

CMake 仪器 API 允许在 CMake 项目的配置、生成、构建、测试和安装步骤中收集计时数据、目标信息和系统诊断信息。

此功能仅适用于使用 Makefile GeneratorsNinja GeneratorsFASTBuild 的项目。

与 CMake 仪器 API 的所有交互都必须同时指定 API 版本和数据版本。目前,这两者只有一个版本:API v1Data v1

数据收集

每当启用仪器功能的命令执行时,都会在项目构建树中创建一个 v1 片段文件,其中包含该命令的特定数据。这些文件会保留到 索引 发生之后。

CMake 将 RULE_LAUNCH_COMPILERULE_LAUNCH_LINKRULE_LAUNCH_CUSTOM 全局属性设置为使用 ctest --instrument 启动器,以捕获每个编译、链接和自定义命令的详细信息。如果项目已使用 CTestUseLaunchers 配置,则 ctest --instrument 还将包括通常由 ctest --launch 执行的行为。

索引

索引是整理生成的数据的过程。索引在称为钩子的特定时间间隔发生,例如每次构建之后。这些钩子是作为 v1 查询文件 的一部分配置的。每当触发钩子时,就会生成一个索引文件,其中包含比前一次索引更新的片段文件列表。

还可以通过手动调用 ctest --collect-instrumentation <build> 来执行索引。

回调

作为 v1 查询文件 的一部分,用户可以提供一个回调列表,用于处理此功能收集的数据。

每当发生 索引 时,每个提供回调都会被执行,并将生成的索引文件的路径作为参数传递。

这些回调(在用户级或项目级定义)应读取仪器数据并执行任何所需的处理。索引文件及其列出的片段在所有回调完成后会被 CMake 自动删除。请注意,回调不应手动移动或删除这些数据文件,因为其他回调可能需要它们。

启用仪器

仪器功能可以为单个 CMake 项目启用,也可以为用户配置和构建的所有 CMake 项目启用。对于这两种情况,请参阅 v1 查询文件 以了解配置此功能的详细信息。

启用项目级仪器

项目代码可以使用 cmake_instrumentation() 命令包含仪器查询。

此外,查询文件可以手动放置在构建树顶部的 <build>/.cmake/instrumentation/<version>/query/ 目录下。此版本的 CMake 只支持一种版本架构,即 API v1

启用用户级仪器

可以通过将查询文件放在 CMAKE_CONFIG_DIR 下的 <config_dir>/instrumentation/<version>/query/ 目录中来启用用户级的仪器功能。

启用 CDash 提交的仪器

当使用 CTest 的 Dashboard Client 模式时,可以通过设置 CTEST_USE_INSTRUMENTATION 环境变量来启用仪器功能。这样做会自动启用 dynamicSystemInformation 选项。

下表显示了每种类型的仪器化命令如何映射到相应的 CTest XML 文件类型。

片段角色

CTest XML 文件

configure

Configure.xml

generate

Configure.xml

compile

Build.xml

link

Build.xml

自定义

Build.xml

构建

unused!

cmakeBuild

Build.xml

cmakeInstall

Build.xml

安装

Build.xml

ctest

Build.xml

测试

Test.xml

默认情况下,报告给 CDash 的命令行在第一个空格处被截断。您可以通过将 CTEST_USE_VERBOSE_INSTRUMENTATION 设置为 1 来选择报告完整的命令行(包括参数)。

或者,您可以使用 v1 查询文件 使用 cdashSubmitcdashVerbose 选项来启用 CDash 的仪器功能。

为了使提交的 Build.xml 文件正确分组片段文件,所有配置和构建命令都应与 CTest 一起在 Dashboard Client 模式下执行。

API v1

API 版本指定了仪器目录的布局,以及查询文件和 cmake_instrumentation() 命令参数的通用格式。

仪器 API v1 位于 <build>/.cmake/ 下的 instrumentation/v1/ 目录中,用于输出数据和项目级查询,或者位于 <config_dir>/ 下,用于用户级查询。此目录的 v1 组件表示 API 版本。它有以下子目录:

query/

包含由用户或客户端编写的查询文件。任何扩展名为 .json 的文件都将被识别为查询文件。这些文件属于创建它们的客户端或用户。

query/generated/

包含由 CMake 项目使用 cmake_instrumentation() 命令或 CTEST_USE_INSTRUMENTATION 变量生成的查询文件。这些文件由 CMake 拥有,并在 CMake 配置步骤中自动删除和重新生成。

data/

包含收集到的仪器数据。CMake 拥有所有数据文件,不应由其他进程删除。此处收集的数据会保留到 索引 发生且所有 回调 执行完毕之后。

data/index/

收集数据的子集,包含任何 v1 索引文件

data/content/

收集数据的子集,包含任何 v1 CMake 内容文件

data/trace/

收集数据的子集,包含最近一次 索引 生成的 Google Trace 文件。与其他数据文件不同,最新的 trace 文件在 索引 发生且所有 回调 执行完毕后仍会保留,直到下一次 索引 发生。

cdash/

包含用于生成要提交到 CDash 的 XML 内容的临时文件。

v1 查询文件

位于 instrumentation/v1/query/ 目录下的任何扩展名为 .json 的文件都将被识别为仪器数据的查询。

这些文件必须包含一个 JSON 对象,其中包含以下键。 version 键是必需的,但所有其他字段都是可选的。

版本

要生成的片段文件的**数据版本**,一个整数。目前唯一支持的版本是 1

callbacks

用于 回调 处理收集到的仪器数据的命令行字符串列表。每当执行这些回调时,都会将生成的 v1 索引文件 的完整路径追加到字符串中包含的参数之后。

hooks

指定何时自动执行 索引 的字符串列表。这些是应收集仪器数据并调用用户 回调 来处理数据的间隔。此列表中的元素应为以下之一:

  • postGenerate

  • preBuild(在调用 ninjamake 时调用)

  • postBuild(在 ninjamake 完成时调用)

  • preCMakeBuild(在调用 cmake --build 时调用)

  • postCMakeBuild(在 cmake --build 完成时调用)

  • postCMakeInstall

  • postCTest

preBuildpostBuild 在使用 MSYS MakefilesFASTBuild 生成器时不受支持。此外,当构建工具通过 cmake --build 调用时,它们也不会被触发。

options

用于启用某些可选行为的字符串列表,包括收集某些附加数据。此列表中的元素应为以下之一:

staticSystemInformation

启用收集正在运行 CMake 的主机机器的静态信息。此数据在 索引 期间收集,并包含在生成的 v1 索引文件 中。

dynamicSystemInformation

启用收集正在运行 CMake 的主机机器的动态信息。为 CMake 生成的每个 v1 片段文件 收集数据,并包含命令执行前后立即的信息。

cdashSubmit

启用将仪器数据包含在 CDash 中。这不会自动启用 dynamicSystemInformation,但否则等同于启用了 CTEST_USE_INSTRUMENTATION 环境变量。

cdashVerbose

启用将完整的未截断命令包含在提交给 CDash 的数据中。等同于启用了 CTEST_USE_VERBOSE_INSTRUMENTATION 环境变量。

trace

索引 期间启用生成 Google Trace 文件,以可视化从收集的 v1 片段文件 中的数据。

在指定钩子期间,会*至少*调用列出的 callbacks。当有多个查询文件时,它们之间的 callbackshooksoptions 将被合并。因此,如果任何查询文件包含任何 hooks,那么所有查询文件中的每个 callback 都将在所有查询文件中的每个 hook 处执行。此外,如果任何查询文件使用 options 字段请求可选数据,那么任何相关数据都将存在于所有片段文件中。用户编写的 callbacks 应能够处理此可选数据的存在,因为它可能被不相关的查询请求。

示例

{
  "version": 1,
  "callbacks": [
    "/usr/bin/python callback.py",
    "/usr/bin/cmake -P callback.cmake arg",
  ],
  "hooks": [
    "postCMakeBuild",
    "postCMakeInstall"
  ],
  "options": [
    "staticSystemInformation",
    "dynamicSystemInformation",
    "cdashSubmit",
    "trace"
  ]
}

在此示例中,每次调用 cmake --buildcmake --install 后,将在 <build>/.cmake/instrumentation/v1/data/index 中生成一个索引文件 index-<timestamp>.json,其中包含自上次索引以来创建的数据片段文件的列表。命令 /usr/bin/python callback.py index-<timestamp>.json/usr/bin/cmake -P callback.cmake arg index-<timestamp>.json 将按此顺序执行。索引文件将包含 staticSystemInformation 数据,并且索引中列出的每个片段文件将包含 dynamicSystemInformation 数据。此外,索引文件还将包含生成的 Google Trace 文件 的路径。一旦两个回调都完成,索引文件以及其中列出的数据文件(包括片段文件,但不包括 trace 文件)将从项目构建树中删除。仪器数据将存在于提交给 CDash 的 XML 文件中,但命令字符串会被截断,因为 cdashVerbose 未启用。

数据 v1

数据版本指定了 CMake 仪器 API 在 数据收集索引 中生成的输出文件的内容。当之前包含的数据被删除或重新格式化,导致用于解析此数据的脚本可能与新格式不兼容时,将创建一个新的版本号。会生成四种类型的数据文件:v1 片段文件v1 索引文件v1 CMake 内容文件Google Trace 文件。在使用 API v1 时,这些文件位于项目构建树下的 <build>/.cmake/instrumentation/v1/data/ 中。

v1 片段文件

片段文件为 CMake 构建或安装步骤中调用的每个编译、链接和自定义命令生成,并包含有关执行命令的仪器数据。此外,还会为以下内容创建片段文件:

  • CMake 配置步骤

  • CMake 生成步骤

  • 整个构建步骤(使用 cmake --build 执行)

  • 整个安装步骤(使用 cmake --install 执行)

  • 每次 ctest 调用

  • ctest 执行的每个单独的测试。

这些文件会保留在构建树中,直到 索引 发生且任何用户指定的 回调 执行完毕。

片段文件的文件名语法为 <role>-<hash>-<timestamp>.json,包含以下数据:

版本

片段文件的**数据版本**,一个整数。目前版本始终为 1

命令

执行的**完整命令**。当 rolebuild 时排除。

workingDir

执行 command 的工作目录。

result

命令的退出代码,一个整数。当 rolebuild 时,此值为 null

role

执行命令的类型,将是以下值之一:

  • configure:CMake 配置步骤

  • generate:CMake 生成步骤

  • compile:构建过程中调用的单个编译步骤

  • link:构建过程中调用的单个链接步骤

  • custom:构建过程中调用的单个自定义命令

  • build:完整的 makeninja 调用(非通过 cmake --build)。

  • cmakeBuild:完整的 cmake --build 调用

  • cmakeInstall:完整的 cmake --install 调用

  • install:单个 cmake -P cmake_install.cmake 调用

  • ctest:完整的 ctest 调用

  • test:CTest 执行的单个测试

目标

与命令关联的 CMake 目标。仅在 rolecompilelink 时包含。结合 cmakeContent,可用于查找目标类型和标签。

timeStart

命令开始的时间,表示为自系统纪元以来的毫秒数。

duration

命令运行的时长,以毫秒为单位。

outputs

命令的输出文件,一个数组。仅在 role 为以下之一时包含:compilelinkcustom

outputSizes

outputs 的大小(字节),一个数组。对于不存在的文件,大小为 0。在与 outputs 字段相同的条件下包含。

正在编译的源文件。仅在 rolecompile 时包含。

language

正在编译的源文件的语言。仅在 rolecompilelink 时包含。

testName

正在执行的测试的名称。仅在 roletest 时包含。

config

构建类型,例如 ReleaseDebug。仅在 role 为以下之一时包含:compilelinkcustominstalltest

dynamicSystemInformation

指定正在运行 CMake 的主机机器的动态信息。为 CMake 生成的每个片段文件收集数据,并包含命令执行前后立即的数据。仅在通过 v1 查询文件 启用时包含。

beforeHostMemoryUsed

timeStart 时的**主机内存使用量**(以 KiB 为单位)。

afterHostMemoryUsed

timeStart + duration 时的**主机内存使用量**(以 KiB 为单位)。

beforeCPULoadAverage

timeStart 时的**平均 CPU 负载**,如果无法确定则为 null

afterCPULoadAverage

timeStart + duration 时的**平均 CPU 负载**,如果无法确定则为 null

cmakeContent

指向 data 下的 v1 CMake 内容文件 的路径,该文件包含有关负责生成此片段中 command 的 CMake 配置和生成步骤的信息。

showOnly

一个布尔值,表示是否将 --show-only 选项传递给了 ctest。仅在 rolectest 时包含。

示例

{
  "version": 1,
  "command" : "\"/usr/bin/c++\" \"-MD\" \"-MT\" \"CMakeFiles/main.dir/main.cxx.o\" \"-MF\" \"CMakeFiles/main.dir/main.cxx.o.d\" \"-o\" \"CMakeFiles/main.dir/main.cxx.o\" \"-c\" \"<src>/main.cxx\"",
  "role" : "compile",
  "return" : 1,
  "target": "main",
  "language" : "C++",
  "outputs" : [ "CMakeFiles/main.dir/main.cxx.o" ],
  "outputSizes" : [ 0 ],
  "source" : "<src>/main.cxx",
  "config" : "Debug",
  "dynamicSystemInformation" :
  {
    "afterCPULoadAverage" : 2.3500000000000001,
    "afterHostMemoryUsed" : 6635680.0
    "beforeCPULoadAverage" : 2.3500000000000001,
    "beforeHostMemoryUsed" : 6635832.0
  },
  "timeStart" : 1737053448177,
  "duration" : 31,
  "cmakeContent" : "content/cmake-2025-07-11T12-46-32-0572.json"
}

v1 索引文件

索引文件包含 v1 片段文件 的列表。它作为导航仪器数据的入口点。它们在 索引 发生时生成,并在任何用户指定的 回调 执行后删除。

版本

索引文件的**数据版本**,一个整数。目前版本始终为 1

buildDir

CMake 项目的构建目录。

dataDir

<build>/.cmake/instrumentation/v1/data/ 目录的完整路径。

hook

负责生成索引文件的钩子名称。除了可以通过 v1 查询文件 指定的钩子外,如果通过调用 ctest --collect-instrumentation <build> 来执行索引,此值可以设置为 manual

snippets

包含 v1 片段文件 的列表。这包括自上一个索引文件创建以来生成的所有片段文件。文件路径相对于 dataDir

trace:

包含 Google Trace 文件 的路径。这包括索引文件中所有相应 snippets 的数据。文件路径相对于 dataDir。仅在通过 v1 查询文件 启用时包含。

staticSystemInformation

指定正在运行 CMake 的主机机器的静态信息。仅在通过 v1 查询文件 启用时包含。

  • OSName

  • OSPlatform

  • OSRelease

  • OSVersion

  • familyId

  • hostname

  • is64Bits

  • modelId

  • numberOfLogicalCPU

  • numberOfPhysicalCPU

  • processorAPICID

  • processorCacheSize

  • processorClockFrequency

  • processorName

  • totalPhysicalMemory

  • totalVirtualMemory

  • vendorID

  • vendorString

示例

{
  "version": 1,
  "hook": "manual",
  "buildDir": "<build>",
  "dataDir": "<build>/.cmake/instrumentation/v1/data",
  "snippets": [
    "configure-<hash>-<timestamp>.json",
    "generate-<hash>-<timestamp>.json",
    "compile-<hash>-<timestamp>.json",
    "compile-<hash>-<timestamp>.json",
    "link-<hash>-<timestamp>.json",
    "install-<hash>-<timestamp>.json",
    "ctest-<hash>-<timestamp>.json",
    "test-<hash>-<timestamp>.json",
    "test-<hash>-<timestamp>.json",
  ],
  "trace": "trace/trace-<timestamp>.json"
}

v1 CMake 内容文件

CMake 内容文件包含有关 CMake 配置和生成步骤的信息。每个 v1 片段文件 都提供指向一个对应于负责生成其命令的 CMake 调用的文件的路径。

每个 CMake 内容文件包含以下内容:

自定义

一个包含用户使用 cmake_instrumentation() 命令的 自定义 CMake 内容 功能指定的任意 JSON 数据对象。

targets

一个包含 CMake 目标的对象,按名称索引,这些目标具有相应的仪器数据。每个目标包含以下内容:

type

目标类型。是 EXECUTABLESTATIC_LIBRARYSHARED_LIBRARYOBJECT_LIBRARY 之一。

labels

目标的 LABELS 属性。

Google Trace 文件

Trace 文件遵循 Google Trace Event Format。它们包含当前索引文件中列出的所有 v1 片段文件 的数据。这些文件在 索引 发生且所有 回调 执行后仍保留在构建树中,直到下一次 索引 发生。

Trace 文件以 JSON Array Format 存储,其中每个 v1 片段文件 对应一个 trace 事件对象。每个 trace 事件包含以下数据:

名称

一个由 CMake 根据给定的片段数据生成的描述性名称。

cat

来自 v1 片段文件role

ph

目前,始终为 "X",表示 Complete Events

ts

来自 v1 片段文件timeStart,从毫秒转换为微秒。

dur

来自 v1 片段文件duration,从毫秒转换为微秒。

pid

未使用(始终为零)。

tid

一个整数,范围从零到正在索引的进程运行的并发作业数。这是一个由 CMake 根据所有正在索引的片段文件的 tsdur 计算出的合成 ID,以生成更有效的进程并发可视化。

args

包含来自此 trace 事件对应的 v1 片段文件 的所有数据。