什么是经典模式和清单模式?
可使用两种方法通过 vcpkg 管理依赖项:
-
清单模式允许你在名为
vcpkg.json
的文件中声明直接依赖项、版本约束和所用注册表。 此文件应包含在代码存储库中,并且可以签入到源代码管理系统。 依赖项安装在名为vcpkg_installed
的子文件夹中。 这样,每个代码项目都可以有自己的依赖项集;系统范围内未安装任何内容。 通过运行vcpkg install
(无其他参数)或利用与 MSBuild 和 CMake 项目的自动集成,可以在清单模式下运行 vcpkg。 大多数情况下,建议在经典模式下对项目使用清单,因为您可以更好地控制依赖项。 有关更多详细信息,请参阅我们的清单模式文章。 - 经典模式是管理依赖项的更传统方式,它涉及运行 vcpkg 命令来指定要安装、修改或删除的每个直接依赖项。 依赖项存储在 vcpkg 安装目录中,因此多个所用项目可以引用同一组依赖项。 有关更多详细信息,请参阅我们的经典模式文章。
是否可以为新库贡献代码?
是! 首先阅读我们的参与指南。 另请查看我们的维护人员指南,了解更多详细信息。 我们还提供了一个介绍如何将端口添加到 vcpkg 的教程,以帮助你入门。
如果想要贡献代码,但又没决定贡献哪个库,请查看新端口请求列表。
vcpkg 是否可以创建预生成的二进制包? vcpkg 使用哪种二进制格式?
是! 如果要生成用于导出到其他环境的二进制文件,请参阅 export
命令。
或者,如果你的目标是保留 vcpkg install
操作生成的二进制文件以供以后重复使用,请参阅二进制缓存功能
如何更新库?
如果你使用清单(vcpkg.json 文件)来管理依赖项,则需要更新该文件。 有关详细信息,请参阅版本控制参考文档。
如果要在经典模式下使用 vcpkg(运行命令来管理包,无清单文件),请参阅 vcpkg update
命令文档。 此命令将列出与当前端口文件不同步的所有包。 然后,将需要运行 vcpkg upgrade
命令来确认更改。
如何获取更多库?
库列表从 ports\
目录中枚举。 根据设计,你可以根据自己或公司的需要从此目录中添加和移除库 -- 请参阅有关打包 zip 文件和 GitHub 存储库的示例。
建议直接从 GitHub 克隆,然后使用 git pull
更新端口文件列表。
是否可以使用此工具构建专用库?
是的。 按照打包示例创建自己的端口,并查看覆盖端口和注册表文档,了解如何管理专用端口。
可以通过将专用库发布到注册表来进一步执行此操作。 请参阅有关 自定义注册表的文章。 注册表是端口的集合,类似于包含开放源代码库的 vcpkg 提供的端口目录。
是否可以将预生成的专用库与此工具配合使用?
是的。 库的 portfile.cmake
本质上是一个脚本,用于将标头和二进制文件放入 ${CURRENT_PACKAGES_DIR}
的正确排列中,因此要拉取预生成的二进制文件,可以编写直接下载和排列文件的端口文件。
要查看此项的示例,请查看仅从 Windows SDK 中复制文件的 ports\opengl\portfile.cmake
。
可以使用 vcpkg 定位哪些平台?
我们的内置持续集成测试三元组包括:
- Windows 桌面(x86、x64、x64-static、arm64)
- 通用 Windows 平台(x64 和 arm64)
- Mac OS X(x64 静态)
- Linux (x64-static)
- Android(x64、arm64、arm-neon)
这些目标经过了更严格的测试,以便与每个 vcpkg 版本兼容。 然而,我们有更多的社区三元组,可用于更多平台和体系结构,包括 iOS、MinGW、WebAssembly、freeBSD 和 openBSD 的平台和体系结构。
还可以根据你的需求定义自己的三元组。 vcpkg 的可定制性很强。
请参阅 vcpkg help triplet
以获取当前列表,并查看我们的三元组文档以了解更多详细信息。
vcpkg 是否在 Linux/OS X 上运行?
是! 虽然我们知道用户已成功使用 Arch、Fedora 和 FreeBSD,但我们仍在 OS X 和 Ubuntu 22.04 上不断进行测试。 如果在使用自己喜欢的 Linux 分发版时遇到问题,请在问题中告知我们,我们很乐意提供帮助!
如何更新 vcpkg?
执行 git pull
获取最新的源,然后运行 bootstrap-vcpkg.bat
(Windows) 或 ./bootstrap-vcpkg.sh
(Unix) 更新 vcpkg。 或者,如果要使用 Visual Studio 附带的 vcpkg 副本,只需从 Visual Studio 安装程序更新 Visual Studio 版本即可。
如何在一台计算机上使用不同版本的库?
我们建议使用清单文件来管理单个项目的依赖项,即使多个项目位于同一台计算机上,这么做也很很用,并且允许你轻松管理包版本以及库来自的具体注册表。
但是,如果改用经典模式,则在 vcpkg 的单个实例(例如一组 installed\
、packages\
、ports\
等)中,只能安装一个版本的库(否则,标头将相互冲突!)。 对有系统范围的包管理器经验的用户来说,vcpkg 中的包对应于 X-dev
或 X-devel
包。 在这种情况下,若要对不同项目使用不同版本的库,建议创建单独的 vcpkg 实例,并使用每项目集成机制。 每个库的版本由 ports\
中的文件指定,因此可以使用标准 git
命令轻松地对其进行操作。 这样,可以轻松地将整组库回滚到一组一致的旧版本,而这些旧版本可以相互协作。 如果随后需要向前固定特定的库,则签出相应版本的 ports\<package>\
即可。 如果应用程序对库版本非常敏感,我们建议将所需的一组特定端口文件以及项目源代码一起签入源代码管理,并使用 --vcpkg-root
选项重定向 vcpkg.exe
的工作目录。
vcpkg 如何保护我的隐私?
有关隐私的所有信息,请参阅隐私文档。
是否可以将我自己的 CMake 工具链文件与 vcpkg 的工具链文件一起使用?
是的。 如果已有 CMake 工具链文件,则需要在你的工具链文件末尾包含我们的工具链文件。 这应该像 include(<vcpkg_root>\scripts\buildsystems\vcpkg.cmake)
指令一样简单。 或者,你可以将我们 scripts\buildsystems\vcpkg.cmake
的内容复制到现有工具链文件的末尾。
我可以使用自己的/特定标志重建库吗?
是的。 您可以使用 自定义 triplet 通过 VCPKG_C_FLAGS
和 VCPKG_CXX_FLAGS
变量修改编译标志。
您还可以 单独自定义每个端口的标志。 例如:
if (PORT MATCHES "my-port")
set(VCPKG_CXX_FLAGS "-D_CRT_SECURE_NO_WARNINGS")
set(VCPKG_C_FLAGS "-D_CRT_SECURE_NO_WARNINGS")
endif()
是否可以获取自定义配置的 vcpkg 集成?
是的。 虽然 vcpkg 构建库时仅构建标准“发布”和“调试”配置,但除了项目的标准配置之外,还可以获得对项目自定义配置的集成支持。
首先,vcpkg 将以 "Release"(或 "Debug")开头的任何自定义配置自动假定为与标准“发布”(或“调试”)配置兼容的配置,并相应地采取行动。
对于其他配置,只需覆盖项目文件 (.vcxproj) 中的 MSBuild $(VcpkgConfiguration)
宏即可声明你的配置与目标标准配置之间的兼容性。
遗憾的是,由于 MSBuild 的顺序性,需要在 vcxproj 中更高的位置添加这些设置,以便在加载 vcpkg 集成之前声明该设置。 建议将 $(VcpkgConfiguration)
宏添加到 "Globals" PropertyGroup。
例如,可以通过在项目文件中添加对 "MyRelease" 配置的支持:
<PropertyGroup Label="Globals">
...
<VcpkgConfiguration Condition="'$(Configuration)' == 'MyRelease'">Release</VcpkgConfiguration>
</PropertyGroup>
当然,仅当自定义配置与目标配置兼容(例如,它们应同时链接到同一运行时库)时,此操作才会生成可行的二进制文件。
我无法使用用户范围的集成。 是否可以使用每个项目集成?
是的。 通过 vcpkg integrate project
命令(轻型链接)或 vcpkg export --nuget
命令(收缩包装)可以生成适合每个项目使用的 NuGet 包。
通过 vcpkg integrate project
文件可实现与 <vcpkg_root>\scripts\buildsystems\msbuild\vcpkg.targets
NuGet 包相同的较低级别机制。 只需将该文件导入 .vcxproj 文件中,并将 <vcpkg_root>
替换为安装 vcpkg 的路径:
<Import Project="<vcpkg_root>\scripts\buildsystems\msbuild\vcpkg.targets" />
如何删除临时文件?
如果只关心已安装的包,则可安全地删除 vcpkg 根文件夹中的以下目录:
-
packages
? -
buildtrees
? - 和
downloads
可使用 --clean-after-build
命令中的 vcpkg install
标志以让 vcpkg 在生成完成后自动删除临时文件。
vcpkg 还使用 vcpkg 根文件夹之外的其他临时位置。 Visual Studio 集成文件、默认二进制缓存和注册表缓存;它们均位于以下路径,具体取决于你的操作系统:
在 Windows 上:
%LocalAppData%/vcpkg
在 Linux/macOS 上:
$XDG_CACHE_HOME/vcpkg
-
~/.cache/vcpkg
(仅当未定义XDG_CACHE_HOME
时)
如果已配置本地二进制或资产缓存,则可能需要按需定期清理这些缓存。
vcpkg 如何在内部使用 CMake?
vcpkg 在内部使用 CMake 作为构建脚本语言。 这是因为 CMake 已经是极其常见的跨平台开放源代码库构建系统,并且在 C++ 项目中也越来越受欢迎。 它在 Windows 上很容易获得,不需要系统范围的安装,而且不熟悉的用户也能看懂。
Vcpkg 是否支持从公共服务器或专用服务器中下载编译的二进制文件?
我们建议使用首选的构建配置构建一次库,并使用二进制缓存功能来重复使用二进制文件,而无需每次都重新构建。 在处理团队项目时,或在本地以及在跨多台计算机、容器、虚拟机等的持续集成环境中构建时,这非常有用。
哪些 MSVC 工具集受支持?
我们支持 Visual Studio 2015 Update 3 及更高版本。
为什么 Visual Studio 在启用了用户范围集成后没有使用我的库?
启用用户范围的集成 (vcpkg integrate install
) 会更改某些项目属性的默认值。 具体而言,"C/C++/General/Additional Include Directories" 和 "Linker/General/Additional Library Directories" 在没有用户范围集成时通常为空白。 如果有集成,空白值表示将覆盖 vcpkg 提供的增强默认值,并且找不到标头/库。 要恢复默认值,请将属性设置为从父级继承。
为什么不使用 NuGet?
NuGet 是 .NET 库的包管理器,对 MSBuild 有很强的依赖性。 它至少在三个方面不能满足本机 C++ 客户的特定需求。
编译风格。 由于编译选项可能的组合非常多,因此根本不可能提供一组真正完整的选项。 此外,相对完整的二进制包的下载大小将变得非常大。 这就需要将结果拆分为多个包,但随后搜索会变得非常困难。
二进制文件与源代码。 与第一点密切相关的是,NuGet 从一开始就旨在提供相对较小的预生成二进制文件。 由于本机代码的性质,开发人员需要有权访问源代码,以确保 ABI 兼容性、性能、完整性和可调试性。
每个 dll 与每个应用程序。 NuGet 高度以项目为中心。 这在具有天然稳定 ABI 的托管语言中效果很好,因为基础库可以在不破坏更高级别库的情况下继续发展。 但是,在 ABI 脆弱得多的本机语言中,唯一可靠的策略是根据最终应用程序中包含的确切依赖项显式构建每个库。 在 NuGet 中很难确保这一点,并将产生一个高度分离和独立版本控制的生态系统。
为什么不使用 Conan?
Conan.io 是一个公开联合的、以项目为中心的、跨平台的、以 Python 编写的 C++ 包管理器。 我们的主要区别在于:
公开联合与私人联合。 Conan 依赖于个人发布每个包的独立副本。 我们认为这种方法会鼓励大量有不同缺陷的包。 我们认为,让用户在 Boost 1.56 的 20 多个公共包中挑选以确定少数适合其特定情况的包是浪费时间。 相比之下,我们认为应该有一个单一的、协作维护的版本,该版本适用于绝大多数情况,并允许用户自由地在他们的私人版本上进行修改。。 我们相信,这将产生一组高质量的包,这些包已经过大量相互测试,并为你需要的任何私人修改奠定了良好的基础。
每个 dll 与每个应用程序。 当依赖项在库级别独立进行版本控制时,它鼓励每个构建环境成为完全唯一的环境,因此法利用或为一个稳定、经过充分测试的生态系统做出贡献。 相比之下,通过将所有库作为一个平台(类似于系统包管理器)进行版本控制,我们希望将测试和工作集中在一组非常常见的库版本,从而最大限度地提高生态系统的质量和稳定性。 这也完全排除了库要求提供的版本与应用程序选择版本相冲突的可能性(我想要 openssl Z 和 boost X,但 X 仅声明与 openssl Y 兼容)。
跨平台与单平台。 虽然在许多平台上托管是一个不错的目标,但我们认为 apt-get、yum 和 homebrew 提供的系统集成和稳定性水平非常值得在自动化脚本中将
apt-get install libboost-all-dev
替换为brew install boost
。 我们选择让我们的系统尽可能简单地集成到这些非常成功的系统管理器中(多一行vcpkg install boost
),而不是试图在它们已经如此成功且深受喜爱的领域取而代之。C++/CMake 与 python。 虽然 Python 是一种深受多人喜爱的优秀语言,但我们认为,在选择像包管理器这样对工作流程非常重要的工具时,透明度和熟悉程度才是最重要的因素。 因此,我们选择最可能普遍接受的实现语言:应在 C++ 包管理器中供 C++ 程序员使用的 C++。 你不需要仅仅为了了解包管理器而学习另一种编程语言。
为什么不使用 Chocolatey?
Chocolatey 是一个出色的应用程序管理系统。 然而,它目前并不具备获取可再分发的开发者资源并帮助你进行调试的功能。 相比之下,vcpkg 旨在获取构建应用程序所需的库,并帮助你通过希望的任何平台(包括 Chocolatey!)交付。