常见问题解答
什么是经典模式(classic mode)和清单模式(manifest mode)?
kmpkg 提供两种依赖管理方式:
- 清单模式:通过
kmpkg.json文件(详见文档)声明直接依赖、版本约束和使用的注册表。该文件应纳入代码仓库,并可提交到版本控制系统。依赖项会安装在名为kmpkg_installed的子文件夹中,每个项目可拥有独立依赖集,无需系统级安装。运行kmpkg install(无其他参数)即可启用清单模式,也可借助与 MSBuild 的自动集成 和 CMake 项目的自动集成。大多数情况下,建议优先使用清单模式,因其能更精准地控制依赖。更多细节请参阅 清单模式文档。 - 经典模式:传统的依赖管理方式,需通过 kmpkg 命令指定要安装、修改或移除的每个直接依赖项。依赖项存储在 kmpkg 安装目录中,多个项目可共享同一套依赖。更多细节请参阅 经典模式文档。
我可以贡献新的库吗?
可以!首先阅读 贡献指南,再查看 维护者指南 了解更多细节。我们还提供了 向 kmpkg 添加端口的教程 帮助你快速上手。
如果想贡献但暂无具体目标库,可查看 新端口请求列表。
kmpkg 能否创建预编译二进制包?kmpkg 使用的二进制格式是什么?
可以!若需生成二进制包用于其他环境,可参阅 export 命令文档。
若需保留 kmpkg install 命令生成的二进制文件供后续复用,可使用 二进制缓存功能。
如何更新库?
- 若使用清单文件(kmpkg.json)管理依赖,需直接修改该文件。详情请参阅 版本控制参考文档。
- 若使用经典模式(无清单文件,通过命令管理包),请参阅
kmpkg update命令文档。该命令会列出所有与当前端口文件不同步的包,之后需运行kmpkg upgrade命令 确认更新。
如何获取更多库?
库列表源自 ports\ 目录。你可根据自身或公司需求,自由添加/移除该目录中的库——详见打包 压缩文件 和 GitHub 仓库 的示例。
建议直接从 GitHub 克隆仓库,通过 git pull 更新端口文件列表。
能否用该工具构建私有库?
可以。遵循 打包示例 创建自定义端口,再参阅 覆盖端口 和 注册表 文档,学习如何管理私有端口。
你还可将私有库发布到自定义注册表中,详见 自定义注册表文档。注册表是端口的集合,类似 kmpkg 内置的开源库注册表。
能否用该工具使用预编译的私有库?
可以。库的 portfile.cmake 本质是一个脚本,用于将头文件和二进制文件放置到 ${CURRENT_PACKAGES_DIR} 的指定位置。因此,若要引入预编译二进制文件,只需编写端口文件直接下载并整理这些文件即可。
示例可参考 ports\opengl\portfile.cmake,该文件仅从 Windows SDK 中复制所需文件。
kmpkg 支持哪些目标平台?
我们通过持续集成测试的内置三元组(triplet)包括:
- Windows 桌面(x86、x64、x64-static、arm64)
- 通用 Windows 平台(x64、arm64)
- Mac OS X(x64-static)
- Linux(x64-static)
- Android(x64、arm64、arm-neon)
这些目标平台在每个 kmpkg 版本中都会经过严格的兼容性测试。此外,社区还提供了更多三元组,支持 iOS、MinGW、WebAssembly、FreeBSD、OpenBSD 等更多平台和架构。
你也可根据需求自定义三元组,kmpkg 具有高度可定制性。
运行 kmpkg help triplet 可查看当前支持的三元组列表,更多细节请参阅 三元组文档。
kmpkg 能否在 Linux/OS X 上运行?
可以!我们持续在 OS X 和 Ubuntu 22.04 上进行测试,同时已知用户已成功在 Arch、Fedora 和 FreeBSD 上使用。若在你常用的 Linux 发行版中遇到问题,可提交 issue 反馈,我们会尽力提供帮助!
如何更新 kmpkg?
执行 git pull 获取最新源代码,然后运行 bootstrap-kmpkg.bat(Windows)或 ./bootstrap-kmpkg.sh(Unix)更新 kmpkg。若你使用的是 Visual Studio 自带的 kmpkg,只需通过 Visual Studio 安装程序更新 Visual Studio 版本即可。
如何在一台机器上使用同一库的不同版本?
- 建议使用 清单文件 管理单个项目的依赖,即使多个项目在同一台机器上,也能轻松管理包版本和库的来源注册表。
- 若使用经典模式,在单个 kmpkg 实例中(例如一套
installed\、packages\、ports\等目录),同一库只能安装一个版本(否则头文件会冲突!)。对于有系统级包管理器使用经验的用户,kmpkg 中的包类似X-dev或X-devel包。若需为不同项目使用同一库的不同版本,建议创建多个 kmpkg 实例,并使用项目级集成机制。每个库的版本由ports\目录中的文件指定,可通过标准git命令轻松操作(例如回滚到整套库的历史兼容版本)。若需单独固定某个库的版本,只需检出ports\<package>\的对应版本即可。若你的应用对库版本高度敏感,建议将所需的端口文件与项目源代码一起提交到版本控制系统,并使用--kmpkg-root选项指定kmpkg.exe的工作目录。
kmpkg 如何保护我的隐私?
有关隐私的所有信息,请参阅 隐私文档。
能否将自定义 CMake 工具链文件与 kmpkg 的工具链文件结合使用?
可以。若你已有自定义 CMake 工具链文件,只需在文件末尾包含 kmpkg 的工具链文件,例如添加 include(<kmpkg_root>\scripts\buildsystems\kmpkg.cmake) 指令。或者,也可将 scripts\buildsystems\kmpkg.cmake 的内容复制到现有工具链文件的末尾。
能否为重建库指定自定义编译标志?
可以。通过 自定义三元组,可借助 KMPKG_C_FLAGS 和 KMPKG_CXX_FLAGS 变量修改编译标志。
也可 为单个端口自定义标志,示例如下:
if (PORT MATCHES "my-port")
set(KMPKG_CXX_FLAGS "-D_CRT_SECURE_NO_WARNINGS")
set(KMPKG_C_FLAGS "-D_CRT_SECURE_NO_WARNINGS")
endif()
kmpkg 是否支持自定义配置的集成?
支持。kmpkg 构建库时仅生成标准的 "Release" 和 "Debug" 配置,但你可为项目的自定义配置(以及标准配置)添加集成支持:
- 对于以 "Release"(或 "Debug")开头的自定义配置,kmpkg 会自动将其视为与标准 "Release"(或 "Debug")配置兼容,并相应地运行。
- 对于其他自定义配置,只需在项目文件(.vcxproj)中覆盖 MSBuild 的
$(KmpkgConfiguration)宏,声明自定义配置与目标标准配置的兼容性。由于 MSBuild 的执行顺序限制,需在加载 kmpkg 集成之前添加该设置,建议将$(KmpkgConfiguration)宏添加到 "Globals" 属性组中。
示例:为 "MyRelease" 配置添加支持,需在项目文件中添加:
<PropertyGroup Label="Globals">
...
<KmpkgConfiguration Condition="'$(Configuration)' == 'MyRelease'">Release</KmpkgConfiguration>
</PropertyGroup>
注意:仅当自定义配置与目标标准配置兼容(例如链接相同的运行时库)时,才能生成可用的二进制文件。
无法使用全局用户级集成,能否使用项目级集成?
可以。可通过以下两种方式生成适用于项目级使用的 NuGet 包:
kmpkg integrate project命令(轻量级链接)kmpkg export --nuget命令(打包所有依赖)
另一种底层实现方式(与 kmpkg integrate project 生成的 NuGet 包效果一致)是导入 <kmpkg_root>\scripts\buildsystems\msbuild\kmpkg.targets 文件。只需在 .vcxproj 文件中添加以下内容(将 <kmpkg_root> 替换为 kmpkg 的安装路径):
<Import Project="<kmpkg_root>\scripts\buildsystems\msbuild\kmpkg.targets" />
如何删除临时文件?
若仅需保留已安装的包,可安全删除 kmpkg 根目录下的以下目录:
packagesbuildtreesdownloads
也可在运行 kmpkg install 命令 时,添加 --clean-after-build 标志,让 kmpkg 在构建完成后自动删除临时文件。
kmpkg 还会在根目录外使用其他临时位置,具体路径如下:
- Windows:
%LocalAppData%/kmpkg(存储 Visual Studio 集成文件、默认二进制缓存和注册表缓存) - Linux/macOS:
$XDG_CACHE_HOME/kmpkg或~/.cache/kmpkg(仅当XDG_CACHE_HOME未定义时)
若你配置了本地二进制缓存或资源缓存,也可根据需要定期清理。
kmpkg 内部如何使用 CMake?
kmpkg 将 CMake 用作内部构建脚本语言,原因如下:
- CMake 是跨平台开源库中极为常用的构建系统,在 C++ 项目中普及度高。
- 在 Windows 上易于获取,无需系统级安装。
- 语法清晰,便于不熟悉的用户理解。
kmpkg 是否支持从公共或私有服务器下载预编译二进制文件?
建议使用首选构建配置构建一次库,然后通过 二进制缓存功能 复用二进制文件,避免重复构建。这在团队协作、本地构建与持续集成环境(多机器、容器、虚拟机等)中尤为实用。
支持哪些 MSVC 工具集?
支持 Visual Studio 2015 Update 3 及以上版本。
启用全局用户级集成后,Visual Studio 为何无法使用我的库?
启用全局用户级集成(kmpkg integrate install)会修改部分项目属性的默认值:
- 未启用集成时,“C/C++/常规/附加包含目录”和“链接器/常规/附加库目录”通常为空。
- 启用集成后,空值会覆盖 kmpkg 提供的增强默认值,导致无法找到头文件/库。
如需恢复默认行为,需将这些属性设置为“从父级或项目默认值继承”。
为何不使用 NuGet?
NuGet 是 .NET 库的包管理器,严重依赖 MSBuild,在以下三个方面无法满足原生 C++ 用户的特定需求:
- 编译配置多样性:C++ 编译选项组合繁多,提供完整的预编译二进制包几乎不可能;且完整二进制包的下载体积庞大,需拆分为多个包,导致搜索困难。
- 二进制 vs 源代码:NuGet 设计初衷是提供小型预编译二进制文件,但原生代码开发中,开发者需要访问源代码以确保 ABI 兼容性、性能、完整性和可调试性。
- 按 DLL 版本控制 vs 按应用版本控制:NuGet 以项目为中心,适用于 ABI 稳定的托管语言(基础库升级不会影响上层依赖)。但原生语言 ABI 脆弱,稳健的策略是每个库都针对最终应用的精确依赖进行显式构建——这在 NuGet 中难以保证,导致生态系统高度分散且版本独立。
为何不使用 Conan?
Conan.io 是基于 Python 开发的跨平台 C++ 包管理器,采用公共联邦制、项目中心架构。我们的核心差异如下:
- 公共联邦制 vs 私有联邦制:Conan 依赖个人发布独立的包副本,易导致大量包存在不同问题;用户需在 20+ 个 Boost 1.56 公共包中筛选可用版本,效率低下。我们主张“单一协作维护版本”,确保绝大多数场景可用,同时允许用户自由修改私有版本——这能形成高质量、经过充分互测的包集合,为私有修改提供坚实基础。
- 按库版本控制 vs 按应用版本控制:库级独立版本控制会导致每个构建环境独一无二,无法利用或贡献稳定的生态系统。我们通过“平台级版本控制”(类似系统包管理器),将所有库作为整体版本管理,集中测试常见库版本组合,最大化生态系统的质量和稳定性;同时避免库依赖版本与应用需求冲突(例如“库需 OpenSSL Z 但应用依赖 Boost X,而 X 仅支持 OpenSSL Y”)。
- 跨平台 vs 单平台:虽然跨平台是理想目标,但 apt-get、yum、homebrew 等系统包管理器的系统集成度和稳定性极高——在自动化脚本中用
kmpkg install boost替代apt-get install libboost-all-dev或brew install boost仅需一行代码,无需在这些成熟工具的优势场景中替代它们。 - Python 实现 vs C++/CMake 实现:Python 是优秀的语言,但包管理器对工作流至关重要,透明度和熟悉度是关键。因此,我们选择 C++/CMake 作为实现语言(C++ 包管理器应为 C++ 开发者设计)——无需学习其他编程语言即可理解包管理器的工作原理。
为何不使用 Chocolatey?
Chocolatey 是优秀的应用管理工具,但目前并非为获取可再发行的开发资源和调试支持而设计。相比之下,kmpkg 专注于提供构建应用所需的库,并支持通过任何平台(包括 Chocolatey)交付最终产品。