跳到主要内容

二进制缓存问题排查指南

本指南适用于遇到 二进制缓存 相关问题的用户。

启用 kmpkg 调试信息

遵循本指南时,强烈建议启用调试输出以获取详细日志。

  • 经典模式:在命令中添加 --debug 参数。
  • CMake 工具链:在 CMake 配置命令或 CMakePresets.json 文件中添加 -DKMPKG_INSTALL_OPTIONS="--debug"
  • MSBuild/Visual Studio:将属性 KmpkgAdditionalInstallOptions 设置为 --debug
  • 设置环境变量 KMPKG_INSTALL_OPTIONS--debug

NuGet 推送到 url 失败

请将 kmpkg 工具更新到最新版本。此外,启用 调试输出 以获取完整错误日志。

使用 NuGet 二进制源时出现以下错误:

Pushing NuGet to url failed. Use --debug for more information.

使用 NuGet 配置文件二进制源时出现以下错误:

Pushing NuGet config to url failed. Use --debug for more information.

该错误是由于 kmpkg 尝试通过 NuGet 命令行将包上传到 NuGet 源时失败导致的。

原因 1:用户写入权限不足

出现以下错误信息:

System.Net.Http.HttpRequestException: Response status code does not indicate success: 403 (Forbidden - User <user> lacks permission to complete this action. You need to have 'AddPackage'.

远程源拒绝推送请求,因为用户没有足够的写入权限。

  • 确认你的用户或用户组拥有写入权限。在 NuGet 中,用户至少需要是源的“贡献者”(Contributor)角色。

原因 2:NuGet 源 URL 配置错误

可能出现以下错误:

System.Net.Http.HttpRequestException: Response status code does not indicate success: 405 (Method Not Allowed).

服务器拒绝了 NuGet 的推送请求,因为无法识别请求方法。

  • 验证二进制源中的 URI 是否正确,且指向源的服务索引(通常为 <源基础 URL>/nuget/v3/index.json)。

缓存上传错误

请将 kmpkg 工具更新到最新版本。此外,启用 调试输出 以获取完整错误日志。

将二进制包上传到缓存时遇到错误。

原因 1:二进制缓存提供商上传失败

上传失败可能有多种原因,错误信息通常与具体提供商相关:

  • 确保你已通过缓存提供商的认证(不同提供商的认证方式不同)。
  • 检查缓存的 URI 配置是否正确。
  • 若使用 NuGet 作为二进制源,请参考 推送问题排查
  • 查阅你所使用的缓存提供商的官方文档或问题排查指南。

二进制缓存为空

请将 kmpkg 工具更新到最新版本。此外,启用 调试输出 以获取完整错误日志。

尽管 kmpkg 安装成功且未出现任何错误,但二进制缓存仍然为空。若观察到错误,请参考 NuGet 推送问题排查其他提供商上传问题排查

原因 1:kmpkg 缺少二进制缓存的写入权限

输出中缺少以下信息:

Uploading binaries for 'rapidjson:x64-windows' to `<binary source>` source `<url>`.
Stored binaries in 1 destinations in 1.5 s.

kmpkg 跳过了将二进制包上传到缓存的步骤。

未使用远程二进制缓存,而是重新构建库

请将 kmpkg 工具更新到最新版本。此外,启用 调试输出 以获取完整错误日志。

即使远程二进制缓存中存在所需的二进制包,系统仍然在本地重新构建库。

输出中缺少以下信息:

Restored 1 package(s) from <remote binary cache> in 1.1 s. Use --debug to see more details.

原因 1:kmpkg 缺少远程二进制缓存的读取权限

kmpkg 选择读取默认二进制缓存,而非远程缓存。

原因 2:远程二进制缓存为空

远程缓存中应包含你已推送的二进制包列表。

原因 3:本地与远程构建环境存在差异

二进制缓存中的每个包都标记有 ABI 哈希,该哈希包含编译器版本、源码和其他用于区分二进制包的信息。若本地计算的 ABI 哈希与远程存储的哈希不匹配,则无法获取远程包。

意外或频繁地重新构建库

请将 kmpkg 工具更新到最新版本。此外,启用 调试输出 以获取完整错误日志。

在环境未变更且未更新 kmpkg 的情况下,仍然需要偶尔重新构建库。

原因 1:构建环境中未检测到的变更

二进制缓存中的每个包都标记有 ABI 哈希,该哈希包含编译器版本、源码和其他用于区分二进制包的信息。若本地计算的 ABI 哈希与远程存储的哈希不匹配,则无法获取远程包。

ABI 哈希不匹配问题排查

请将 kmpkg 工具更新到最新版本。此外,启用 调试输出 以获取完整错误日志。

本指南适用于诊断两个名称相同的二进制包为何具有不同 ABI 哈希的问题。

比较两个二进制包

要确定两个名称相同的包之间的差异,需要比较多种数据:源码、工具版本、编译器和目标平台。ABI 哈希 是这些数据的简洁表示。计算 ABI 哈希时,kmpkg 会考虑所有相关数据(包括文件内容、工具版本和系统细节),为每个数据点生成哈希,然后将这些哈希组合为二进制包的单一哈希值。

二进制包 ABI 哈希比较

zlib 库的 ABI 哈希为 bb1c96759ac96102b4b18215db138daedd3eb16c2cd3302ae7bffab2b643eb87

[DEBUG] Trying to hash <path>\buildtrees\zlib\x86-windows.kmpkg_abi_info.txt
[DEBUG] <path>\buildtrees\zlib\x86-windows.kmpkg_abi_info.txt has hash bb1c96759ac96102b4b18215db138daedd3eb16c2cd3302ae7bffab2b643eb87

若同一库在不同运行中哈希值发生变化,说明这两个包是不同的。

编译器版本 ABI 哈希比较

验证两次运行之间编译器版本是否变更:

[DEBUG] -- The C compiler identification is MSVC 19.36.32538.0
[DEBUG] -- The CXX compiler identification is MSVC 19.36.32538.0
[DEBUG] #COMPILER_HASH#f5d02a6542664cfbd4a38db478133cbb1a18f315

上述示例中,编译器哈希为 f5d02a6542664cfbd4a38db478133cbb1a18f315

ABI 条目比较

比较每个包的 ABI 条目(每个条目代表一个影响最终哈希的信息片段):

[DEBUG] <abientries for zlib:x86-windows>
[DEBUG] 0001-Prevent-invalid-inclusions-when-HAVE_-is-set-to-0.patch|750b9542cb55e6328cca01d3ca997f1373b9530afa95e04213168676936e7bfa
[DEBUG] 0002-skip-building-examples.patch|835ddecfed752e0f49be9b0f8ff7ba76541cb0a150044327316e22ca84f8d0c2
[DEBUG] 0003-build-static-or-shared-not-both.patch|d6026271dcb3d8fc74b41e235620ae31576a798e77aa411c3af8cd9e948c02b1
[DEBUG] 0004-android-and-mingw-fixes.patch|37a43eddbcb1b7dde49e7659ae895dfd0ff1df66666c1371ba7d5bfc49d8b438
[DEBUG] cmake|3.26.2
[DEBUG] features|core
[DEBUG] portfile.cmake|ac63047b644fa758860dd7ba48ff9a13b058c6f240b8e8d675b8fbba035976be
[DEBUG] ports.cmake|5a8e00cedff0c898b1f90f7d129329d0288801bc9056562b039698caf31ff3f3
[DEBUG] post_build_checks|2
[DEBUG] powershell|7.3.6
[DEBUG] triplet|x86-windows
[DEBUG] triplet_abi|3e71dd1d4afa622894ae367adbbb1ecbd42c57c51428a86b675fa1c8cad3a581-36b818778ba6f2c16962495caedb9a7b221d5be4c60de1cd3060f549319a9931-f5d02a6542664cfbd4a38db478133cbb1a18f315
[DEBUG] usage|be22662327df993eebc437495add75acb365ab18d37c7e5de735d4ea4f5d3083
[DEBUG] kmpkg-cmake|1b3dac4b9b0bcbef227c954b495174863feebe3900b2a6bdef0cd1cf04ca1213
[DEBUG] kmpkg-cmake-wrapper.cmake|5d49ef2ee6448479c2aad0e5f732e2676eaba0411860f9bebabe6002d66f57d1
[DEBUG] kmpkg.json|bc94e2540efabe36130a806381a001c57194e7de67454ab7ff1e30aa15e6ce23
[DEBUG] kmpkg_copy_pdbs|d57e4f196c82dc562a9968c6155073094513c31e2de475694143d3aa47954b1c
[DEBUG] kmpkg_fixup_pkgconfig|588d833ff057d3ca99c14616c7ecfb5948b5e2a9e4fc02517dceb8b803473457
[DEBUG] kmpkg_from_git|8f27bff0d01c6d15a3e691758df52bfbb0b1b929da45c4ebba02ef76b54b1881
[DEBUG] kmpkg_from_github|b743742296a114ea1b18ae99672e02f142c4eb2bef7f57d36c038bedbfb0502f
[DEBUG] kmpkg_replace_string|d43c8699ce27e25d47367c970d1c546f6bc36b6df8fb0be0c3986eb5830bd4f1
[DEBUG] </abientries>
信息

triplet_abi 条目包含三个哈希值:x86-windows 三元组文件内容的哈希、windows.cmake 工具链的哈希,以及编译器哈希。若切换目标平台,这些哈希值会相应变更。

不匹配原因 1:端口文件

端口文件包括端口脚本(portfile.cmakekmpkg.json)、补丁文件(*.patch)或端口目录中的其他文件:ports/<library>/*

子原因 1:CI 或流水线更新了端口注册表

kmpkg 在 CI 中运行前,克隆了最新的 kmpkg 仓库。

  • 使用 git clone https://github.com/kumose/kmpkg 并执行 bootstrap 脚本时,确保切换到特定的提交版本。
  • 考虑将 kmpkg 作为 git 子模块添加到你的项目中。

子原因 2:GitHub Actions 更新了 kmpkg

你正在使用 GitHub Actions 提供的系统级 kmpkg 副本,该副本已被更新。

  • 克隆你自己的 kmpkg 副本。
  • 考虑将 kmpkg 作为 git 子模块添加到你的项目中。

不匹配原因 2:kmpkg CMake 辅助函数

CMake 辅助函数位于脚本目录:scripts/*,通常以 kmpkg_ 开头。

子原因 1:CI 或流水线更新了辅助脚本

kmpkg 在 CI 中运行前,克隆了最新的 kmpkg 仓库。

  • 使用 git clone https://github.com/kumose/kmpkg 并执行 bootstrap 脚本时,确保切换到特定的提交版本。
  • 考虑将 kmpkg 作为 git 子模块添加到你的项目中。

子原因 2:GitHub Actions 更新了 kmpkg

你正在使用 GitHub Actions 提供的系统级 kmpkg 副本,该副本已被更新。

  • 克隆你自己的 kmpkg 副本。
  • 考虑将 kmpkg 作为 git 子模块添加到你的项目中。

不匹配原因 3:编译器版本

kmpkg 使用不同版本的编译器重新构建了依赖项。

子原因 1:Visual Studio C++ 编译器自动更新

两次运行之间,Visual Studio 自动更新了 C++ 工作负载(包括编译器)。即使是次要版本更新,也会导致 kmpkg 重新构建所有库。

子原因 2:库的构建机器与使用机器不同

一台机器创建二进制包并发布到远程缓存,另一台机器(通常用于开发)从缓存中获取该库。

  • 开发环境中本地重新构建依赖项,后续在持续集成阶段测试并处理相关问题。

子原因 3:自托管镜像更新了编译器

用于构建 kmpkg 依赖项的底层镜像发生变更,导致编译器版本更新。

  • 固定使用稳定且带版本号的镜像,避免拉取“最新”镜像(防止工具或编译器自动更新)。
  • 若需频繁更新镜像,创建镜像时固定 C++ 编译器工具的特定版本。

子原因 4:GitHub 托管运行器更新了底层编译器

GitHub 托管运行器每周更新编译器和工具。

  • 目前无法固定镜像以阻止工具和编译器版本定期更新。请参考 其他选项 部分的替代方案。

不匹配原因 4:两次运行之间工具版本变更

构建库所使用的工具版本(CMake 或 PowerShell)在两次运行之间发生了变更。

子原因 1:Visual Studio 自动更新

两次运行之间,Visual Studio 自动更新(包括相关工具)。即使是次要版本更新,也会导致 kmpkg 重新构建所有库。

  • 在 kmpkg 命令中添加 --x-abi-tools-use-exact-versions 参数。该参数会根据 kmpkgTools.xml 中的版本固定工具的 ABI,必要时 kmpkg 会自行拉取对应版本。

子原因 2:库的构建机器与使用机器不同

一台机器创建二进制包并发布到远程缓存,另一台机器(通常用于开发)从缓存中获取该库。

  • 本地使用与远程机器相同的工具版本。
  • 开发环境中本地重新构建依赖项,后续在持续集成阶段测试并处理相关问题。
  • 在 kmpkg 命令中添加 --x-abi-tools-use-exact-versions 参数。该参数会根据 kmpkgTools.xml 中的版本固定工具的 ABI,必要时 kmpkg 会自行拉取对应版本。

子原因 3:自托管镜像更新了工具

用于构建 kmpkg 依赖项的底层镜像发生变更,导致工具版本更新。

  • 固定使用稳定且带版本号的镜像,避免拉取“最新”镜像(防止工具自动更新)。
  • 若需频繁更新镜像,创建镜像时固定相关工具的特定版本。
  • 在 kmpkg 命令中添加 --x-abi-tools-use-exact-versions 参数。该参数会根据 kmpkgTools.xml 中的版本固定工具的 ABI,必要时 kmpkg 会自行拉取对应版本。

子原因 4:GitHub 托管运行器更新了底层工具

GitHub 托管运行器每周更新编译器和工具。

  • 在 kmpkg 命令中添加 --x-abi-tools-use-exact-versions 参数。该参数会根据 kmpkgTools.xml 中的版本固定工具的 ABI,必要时 kmpkg 会自行拉取对应版本。

其他选项

若上述选项均无效,可考虑以下变通方案:

  • 使用 kmpkg export 命令生成依赖项的独立归档包,而非通过清单恢复。
  • 考虑使用 Docker 自托管镜像构建库。
  • 配置辅助持续集成任务,定期(如每日或每周)构建 kmpkg 库。

问题未列出?

若你的问题未在本文中列出,请访问 我们的仓库 创建新问题。