sodgeit/CMake-SBOM-Builder
GitHub: sodgeit/CMake-SBOM-Builder
一个基于 CMake 的 SBOM 生成工具,帮助项目自动生成符合 SPDX 和 BSI 规范的软件物料清单。
Stars: 9 | Forks: 7
# CMake SBOM 生成器
为任意 CMake 项目生成 SPDX 软件物料清单(SBOM)。
CMake-SBOM-Builder 旨在遵循以下规范:
- [BSI 技术指南 TR-03183](https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/TechGuidelines/TR03183/BSI-TR-03183-2.pdf?__blob=publicationFile&v=5)(德国联邦信息安全办公室)
- 美国 [行政命令 14028](https://www.nist.gov/itl/executive-order-14028-improving-nations-cybersecurity/software-security-supply-chains-software-1)
- [SPDX 规范 2.3](https://spdx.github.io/spdx-spec/v2.3/)
该 SBOM 生成器设计为能够无缝集成到您的 CMake 项目中。它会根据您安装的文件和指定的包依赖关系,为项目生成一个 SBOM。
它还提供了版本提取功能,可以从 Git 仓库生成版本信息,并在 CMake 文件、C/C++ 代码(通过 cmake 目标)以及 Shell 环境(通过脚本)中可用。
要开始使用,请查看 [示例](#example) 以及如何 [将 SBOM-Builder 添加到您的项目](#adding-sbom-builder-to-your-project)。
**注意:**
该项目最初从 [cmake-sbom](https://github.com/DEMCON/cmake-sbom) 分支而来。
虽然原始项目提供了坚实的基础,但我们发现一些需要修改和改进的地方,以更好地符合我们的需求并在工作流程中有效使用。
主要变更包括:
- **单文件集成**:我们将所有内容合并为一个文件,以简化与 CMake `file` 命令的集成,使用起来更简单高效。
- **多配置生成器增强**:SBOM 生成更好地与 Visual Studio 和 Ninja Multi-Config 等多配置生成器集成。为每种配置生成不同的 SBOM。
- **现代化 CMake**:提高最低要求版本(>=3.16),确保更好的兼容性并利用更新的功能。
- **更广泛的 SPDX 2.3 支持**:支持更多 SPDX 字段,以更好符合 SPDX 2.3 规范。
- **符合 BSI 指南**
- **改进的文档**
## 目录
- [如何使用](#how-to-use)
- [将 SBOM-Builder 添加到您的项目](#adding-sbom-builder-to-your-project)
- [生成 SBOM 的步骤](#steps-to-generate-an-sbom)
- [构建并安装您的项目](#build-and-install-your-project)
- [示例](#example)
- [可用的函数和参数](#available-functions-and-arguments)
- [`sbom_generate`](#sbom_generate)
- [`sbom_add_[file|directory|target]`](#sbom_add_filedirectorytarget)
- [`sbom_add_package`](#sbom_add_package)
- [`sbom_add_external`](#sbom_add_external)
- [`sbom_finalize`](#sbom_finalize)
- [`sbom_spdxid`](#sbom_spdxid)
- [版本提取](#version-extraction)
- [`version_extract()`](#version_extract)
- [`version_generate()`](#version_generate)
- [兼容性策略](#compatibility-strategy)
- [许可证](#license)
- [致谢](#acknowledgements)
## 如何使用
### 将 SBOM-Builder 添加到您的项目
有多种方法可以实现这一点。我们推荐直接使用 CMake 以保持简单。
要下载特定版本:
```
file(
DOWNLOAD
https://github.com/sodgeit/CMake-SBOM-Builder/releases/download/v0.2.1/sbom.cmake
${CMAKE_CURRENT_BINARY_DIR}/cmake/sbom.cmake
EXPECTED_HASH SHA256=f87f040c470f86e119e36f1043818a380ad6f81150df7fec60d4504bb38ae2e2
)
```
或始终下载最新版本。
然后只需包含该文件:
```
include(${CMAKE_CURRENT_BINARY_DIR}/cmake/sbom.cmake)
```
### 生成 SBOM 的步骤
1. 使用 `sbom_generate()` 定义 SBOM 创建者并提供所构建包的一般信息。假设您的 CMake 项目生成一个包。
2. 使用 `sbom_add_file()`、`sbom_add_directory()` 或 `sbom_add_target()` 声明包的内容。这些应涵盖通过 CMake 的 `install()` 命令安装的所有文件、可执行文件、库等。
3. 使用 `sbom_add_package()` 定义包的依赖关系。对于单个文件依赖项,使用 `RELATIONSHIP` 参数覆盖默认行为。所有依赖项都被视为黑盒,不会进一步指定或分析其内部内容。
4. 最后调用 `sbom_finalize()` 完成 SBOM 定义。
### 构建并安装您的项目
使用单配置生成器(Makefiles、Ninja):
```
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=build/install -DCMAKE_BUILD_TYPE={Debug,Release,...}
cmake --build build --target all
cmake --install build
```
使用多配置生成器(Visual Studio、Ninja Multi-Config):
```
cmake -S . -B build -G "Ninja Multi-Config"
cmake --build build --target all --config {Debug,Release,...} #--target ALL_BUILD for Visual Studio
cmake --install build --config {Debug,Release,...} --prefix build/install/{Debug,Release,...}
```
我们建议在使用多配置生成器时使用 `--prefix` 选项覆盖安装前缀。这允许为每个配置在独立位置生成 SBOM。
如果不使用 `--prefix` 选项,SBOM 将在所有配置中生成到同一位置并相互覆盖。
默认情况下,SBOM 将生成在 `${CMAKE_INSTALL_PREFIX}/share/${PROJECT_NAME}-sbom-${GIT_VERSION_PATH}.spdx`(请参见 CMake 输出)。
```
-- Installing: .../build/install/share/example-sbom-0.2.1.spdx
...
-- Finalizing: .../build/install/share/example-sbom-0.2.1.spdx
```
### 示例
```
cmake_minimum_required(VERSION 3.16)
project(Example)
include(cmake/sbom.cmake)
sbom_generate(
SUPPLIER ORGANIZATION "sodgeIT"
PACKAGE_NAME "Example"
PACKAGE_VERSION "1.0.0"
PACKAGE_LICENSE "MIT"
)
sbom_add_package(Boost
VERSION 1.88
SUPPLIER ORGANIZATION "Boost Foundation"
LICENSE "BSL-1.0"
)
sbom_add_package(cxxopts
VERSION 3.2.0
SUPPLIER PERSON "Jarryd Beck"
LICENSE "MIT"
)
add_library(example_lib SHARED)
target_sources(example_lib PRIVATE
source1.c
source2.cpp
header1.h
)
target_link_libraries(example_lib PUBLIC Boost::algorithm)
add_executable(cli main.cpp)
target_link_libraries(cli PRIVATE example_lib cxxopts)
install(TARGETS cli RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(TARGETS example_lib LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(FILE header1.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
sbom_add_target(cli)
sbom_add_target(example_lib)
sbom_add_file(${CMAKE_INSTALL_INCLUDEDIR}/header1.h LICENSE "MIT")
sbom_finalize()
```
## 可用的函数和参数
以下是 SBOM-Builder 提供的函数概述。这里仅列出最重要且最可能使用的参数。
完整的函数签名请参考 [此处](./doc/full_signature.md)。
### sbom_generate
```
sbom_generate(
CREATOR [EMAIL ]
PACKAGE_LICENSE
[PACKAGE_NAME ]
[PACKAGE_VERSION ]
[PACKAGE_COPYRIGHT >]
)
```
- `CREATOR`:包和 SBOM 的提供者。
- 必须提供 `` 之一。
- `EMAIL` 可选。
- `PACKAGE_LICENSE`:SBOM 中描述的包的许可证。
- `PACKAGE_NAME`:包名称。
- 默认值为 `${PROJECT_NAME}`。
- `PACKAGE_VERSION`:包版本字段。
- 默认值为 `${GIT_VERSION}`。(参见[版本提取](#version-extraction))
- `PACKAGE_COPYRIGHT`:版权信息。
- 默认值为 ` `,其中 `` 是 `CREATOR` 的名称。
### sbom_add_[file|directory|target]
```
sbom_add_[file|directory|target](
[LICENSE ]
[COPYRIGHT >]
[RELATIONSHIP ...]
)
```
- `filename|path|target`:
- 相对于 `CMAKE_INSTALL_PREFIX` 的文件/目录路径,或要添加的目标名称(目标必须使用 `install(TARGETS ...)` 安装)。
- 支持生成器表达式。
- `LICENSE`:文件的许可证。
- 默认值为包的许可证(来自 `sbom_generate()` 的 `PACKAGE_LICENSE`)。
- 如果添加的是依赖项中的目标或文件,请指定其许可证。
- 有关此类情况的完整签名,请参见完整签名。
- `COPYRIGHT`:
- 默认值为包的版权(来自 `sbom_generate()` 的 `PACKAGE_COPYRIGHT`)。
- 如果添加的是依赖项中的目标或文件,请指定其版权信息。
- 使用 `NOASSERTION` 或 `NONE` 表示无法确定或未指定该信息。
- `RELATIONSHIP`:
- 描述 SBOM 组件之间关系的一个或多个字符串。
- 默认值为 ` CONTAINS `。
- `` 和 `` 是自动生成的 SPDX 标识符占位符。
- 使用此参数覆盖默认行为。请参见[SPDX 第 11 条款](https://spdx.github.io/spdx-spec/v2.3/relationships-between-SPDX-elements/)了解更多信息。
### sbom_add_package
```
sbom_add_package(
LICENSE
VERSION
SUPPLIER [EMAIL ]
[RELATIONSHIP ...]
...
)
```
- `name`:包的名称。
- `LICENSE`:包的许可证。
- 如许可证未指定、无法确定或包含例外,请参见完整签名。
- `VERSION`:包的版本。
- `SUPPLIER`:包的提供者。
- 必须提供 `` 之一。
- `EMAIL` 可选。
- `RELATIONSHIP`:
- 描述 SBOM 组件之间关系的一个或多个字符串。
- 默认值为:
- ` DEPENDS_ON `
- ` CONTAINS NOASSERTION`。
- `` 和 `` 是自动生成的 SPDX 标识符占位符。
- 使用此参数覆盖默认行为。请参见[SPDX 第 11 条款](https://spdx.github.io/spdx-spec/v2.3/relationships-between-SPDX-elements/)了解更多信息。
- 示例:在下面的示例中,依赖项 `cxxopts` 仅被 `cli` 使用,而非整个包。关系可以按如下方式覆盖:
```
sbom_add_target(cli)
set(cli_spdxid ${SBOM_LAST_SPDXID})
sbom_add_package(cxxopts ... RELATIONSHIP "${cli_spdxid} DEPENDS_ON @SBOM_LAST_SPDXID@" )
```
- `${SBOM_LAST_SPDXID}` 设置为最后一个添加的文件/包/目标的 SPDX 标识符。
- `@SBOM_LAST_SPDXID@` 是 `cxxopts` 生成的 SPDX 标识符的占位符。
### sbom_add_external
```
sbom_add_external(
[RENAME ]
[RELATIONSHIP ...]
[SPDXID ]
)
```
- `id`:外部文件中包的 SPDX 标识符。
- `path`:引用另一个 SPDX 文件作为外部文档引用。然后依赖该文档中指定的包。外部 SPDX 文件将复制到 SBOM 旁边。支持生成器表达式。
- `RENAME`:将外部文档重命名为给定文件名(不含目录)。
- `SPDXID`:外部文档的标识符,用作包标识符的前缀。默认为唯一标识符。包标识符会自动添加。变量 `SBOM_LAST_SPDXID` 会被设置为使用的标识符。
- `RELATIONSHIP`:
- 描述 SBOM 组件之间关系的一个或多个字符串。
- 默认为 ` DEPENDS_ON `。
- `` 是生成描述整个包的 SPDXID 的占位符。
### sbom_finalize
完成 SBOM 定义。
```
sbom_finalize()
```
### sbom_spdxid
***这通常不应直接使用。*** 所有 `sbom_add_*` 函数都会自动调用此函数来生成唯一的 SPDX 标识符。
生成唯一的 SPDX 标识符。
```
sbom_spdxid(
VARIABLE
[CHECK | HINTS ...]
)
```
- `VARIABLE`:用于生成唯一 SDPX 标识符的输出变量。
- `CHECK`:验证并返回给定的标识符。
- `HINTS`:一个或多个提示,转换为有效的标识符。第一个非空提示将被使用。如果未指定提示,则返回一个格式未指定的唯一标识符。
## 版本提取
版本提取包含在 `sbom.cmake` 中,并由 `sbom_generate()` 函数用于在 SPDX 文档中填充版本信息。它也可在项目中使用。
### version_extract()
此函数在当前范围内为当前项目设置以下变量:
- `GIT_HASH`:完整的 Git 哈希值。
- `GIT_HASH_SHORT`:短 Git 哈希值。
- `GIT_VERSION`:
- 如果当前提交有标签,标签名称:`v1.2.3`
- 如果没有标签,`git-describe` + 分支:`v1.2.3-4-g1234567+feature/xyz`
- 如果有修改,`+dirty` 后缀会添加到两种情况中:`v1.2.3-4-g1234567+feature/xyz+dirty` 或 `v1.2.3+dirty`
- 我们对“脏”的判定非常严格,即使未跟踪的文件也会被视为脏。
- `GIT_VERSION_PATH`:
- `GIT_VERSION` 的值,但可用于文件名。
- 例如,`v1.2.3-4-g1234567+feature/xyz+dirty` 会变成 `v1.2.3-4-g1234567+feature_xyz+dirty`
- `VERSION_TIMESTAMP`:当前构建时间。
此外,如果 `GIT_VERSION` 以符合[语义化版本 2.0.0](https://semver.org/)(可选带 `v` 前缀)的标签开头,则会设置以下变量:
- `GIT_VERSION_TRIPLET`:从 `GIT_VERSION` 提取的 major.minor.patch 三元组。
- 例如,`v1.2.3-4-g1234567+feature/xyz+dirty` -> `1.2.3`
- `GIT_VERSION_MAJOR`:`GIT_VERSION_TRIPLET` 的主版本号。
- `GIT_VERSION_MINOR`:`GIT_VERSION_TRIPLET` 的次版本号。
- `GIT_VERSION_PATCH`:`GIT_VERSION_TRIPLET` 的修订号。
- `GIT_VERSION_SUFFIX`:三元组之后的所有内容。
- 例如,`v1.2.3-4-g1234567+feature/xyz+dirty` -> `-4-g1234567+feature/xyz+dirty`
### version_generate()
此函数生成以下文件,其中包含上述变量:
- `version.[sh|ps1]`:设置环境变量的脚本文件。
- `version.txt`:用于文档的文本文件。
- 仅包含 `GIT_VERSION` 变量。
- `${PROJECT_NAME}-version`:一个接口库目标,提供单个头文件 `${PROJECT_NAME}-version.h`。
- **注意**:变量以 `${PROJECT_NAME}_` 为前缀,而不是 `GIT_`。
- 链接目标 `${PROJECT_NAME}-version` 并包含 `${PROJECT_NAME}-version.h` 以在 C/C++ 中访问版本信息([示例](example/CMakeLists.txt))。
所有文件生成在 `${PROJECT_BINARY_DIR}/version/[scripts|include|doc]` 中。CMake 变量 `VERSION_SCRIPT_DIR`、`VERSION_INC_DIR` 和 `VERSION_DOC_DIR` 指向这些目录。
## 兼容性策略
CMake 频繁发布新功能和改进,有时会弃用或取代旧功能。为了确保脚本保持功能并利用这些更新,我们将根据所支持的最旧的 Ubuntu LTS 版本同步更新最低要求的 CMake 版本。
截至撰写本文时,所支持的最旧 Ubuntu LTS 版本是 Ubuntu 20.04,其包含 CMake 3.16。当对 Ubuntu 20.04 的支持在 2025 年 5 月结束后,我们将更新最低要求版本以与下一个最旧的受支持 Ubuntu LTS 版本对齐。(Ubuntu 22.04,包含 CMake 3.22)
我们的测试策略也将与此方法保持一致。
我们相信这种方法在确保稳定和长期平台用户的广泛兼容性与利用 CMake 的更新功能和改进之间取得了平衡。
## 许可证
本仓库中的大部分代码采用 MIT 许可证。
## 致谢
我们感谢该项目的原始作者和贡献者的辛勤工作。他们的努力为此分支提供了坚实的基础。
标签:Bash脚本, C/C++, CMake, Cutter, Git版本信息, Ninja, NIST, SBOM, SEO, SPDX, TR-03183, Visual Studio, 事务性I/O, 单文件集成, 合规指南, 多配置生成器, 开源合规, 构建系统, 版本提取, 硬件无关, 网络安全, 跌倒检测, 软件物料清单, 隐私保护