VCPKG详细使用教程

这是一份 vcpkg 的详细使用教程,内容涵盖从安装、核心命令到与 CMake 和 Visual Studio 集成的完整流程,重点推荐使用清单模式 (Manifest Mode) 进行项目开发。

一、安装与初始配置

1.1 获取 vcpkg

首先,从 GitHub 克隆 vcpkg 仓库到本地。建议选择一个简单路径,如 C:\dev\vcpkg 或 ~/tools/vcpkg

bash 复制代码
git clone https://github.com/microsoft/vcpkg.git

1.2 运行引导脚本

进入 vcpkg 目录,执行引导脚本以生成 vcpkg 可执行文件。

操作系统 命令
Windows .\bootstrap-vcpkg.bat
Linux/macOS ./bootstrap-vcpkg.sh

1.3 (可选)设置环境变量

为方便使用,建议将 vcpkg 目录添加到系统 PATH,并设置 VCPKG_ROOT 环境变量。

Windows (命令提示符):

复制代码
setx VCPKG_ROOT "C:\path\to\vcpkg"
setx PATH "%VCPKG_ROOT%;%PATH%"

Visual Studio Code 终端 (临时设置):

复制代码
$env:VCPKG_ROOT="C:\path\to\vcpkg"
$env:PATH="$env:VCPKG_ROOT;$env:PATH"

1.4 与 Visual Studio 集成(可选)

如果使用 Visual Studio,执行以下命令可使 vcpkg 安装的库对所有项目全局可见,无需额外配置即可 #include。

bash 复制代码
vcpkg integrate install

注意:此命令适用于"经典模式"。如果使用"清单模式"(推荐),则无需执行此步骤。

二、两种工作模式

vcpkg 提供两种工作模式,强烈建议新项目使用清单模式。

特性 经典模式 (Classic Mode) 清单模式 (Manifest Mode)
依赖声明 手动执行 vcpkg install 命令 在项目根目录的 vcpkg.json 文件中声明
依赖安装 手动安装,全局共享 自动安装,配置项目时自动下载安装
版本控制 难以锁定版本,项目间可能冲突 通过 builtin-baseline 锁定统一版本基线
项目隔离 全局安装在 <vcpkg-root>/installed 安装在项目构建目录 vcpkg_installed 下,实现项目隔离
推荐场景 个人学习、小型或临时性项目 团队协作、持续集成、需要精确控制版本的项目

三、核心命令

命令 作用 示例
search 搜索可用的库 vcpkg search json
install 安装一个库 vcpkg install fmt
list 列出已安装的库 vcpkg list
remove 卸载一个库 vcpkg remove fmt
update 更新 vcpkg 自身和包目录 vcpkg update
upgrade 重新构建所有过时的库 vcpkg upgrade

指定架构(三元组 Triplet):默认安装 x86 版本,如需 x64 可在包名后指定 :x64-windows,例如 vcpkg install fmt:x64-windows。使用 vcpkg help triplet 查看所有支持的架构。

四、清单模式详细使用教程

这是现代 C++ 项目推荐的使用方式,通过声明式文件管理依赖。

4.1 初始化清单文件

在项目根目录下打开终端,执行以下命令创建必要的配置文件:

bash 复制代码
vcpkg new --application

该命令会生成两个文件:

  • vcpkg.json:项目清单,用于声明依赖项。
  • vcpkg-configuration.json:配置文件,用于配置注册表、覆盖端口等。

4.2 添加依赖项

使用 add port 命令添加所需的库,例如添加 fmt 库:

bash 复制代码
vcpkg add port fmt

此时,vcpkg.json 文件的内容将更新为:

json 复制代码
{
    "dependencies": [
        "fmt"
    ]
}

你也可以手动编辑 vcpkg.json 文件,添加更复杂的配置,例如版本锁定和依赖特性:

json 复制代码
{
    "dependencies": [
        "fmt",
        {
            "name": "curl",
            "features": ["openssl"]
        }
    ],
    "builtin-baseline": "3426db05b996481ca31e95fff3734cf23e0f51bc"
}

4.3 与 CMake 项目集成

4.3.1 创建 CMakeLists.txt

在项目根目录创建 CMakeLists.txt 文件,内容如下:

cmake 复制代码
cmake_minimum_required(VERSION 3.10)

project(HelloWorld)

find_package(fmt CONFIG REQUIRED)

add_executable(HelloWorld helloworld.cpp)

target_link_libraries(HelloWorld PRIVATE fmt::fmt)

4.3.2 配置 CMake 工具链

为了能让 CMake 找到 vcpkg 安装的库,需要指定 vcpkg 提供的工具链文件。推荐使用 CMakePresets.json 来配置。

在项目根目录创建 CMakePresets.json:

json 复制代码
{
  "version": 2,
  "configurePresets": [
    {
      "name": "vcpkg",
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build",
      "cacheVariables": {
        "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
      }
    }
  ]
}

为了方便团队协作,再创建一个用户级别的 CMakeUserPresets.json(此文件不应提交到版本控制):

json 复制代码
{
  "version": 2,
  "configurePresets": [
    {
      "name": "default",
      "inherits": "vcpkg",
      "environment": {
        "VCPKG_ROOT": "C:/path/to/your/vcpkg"
      }
    }
  ]
}

4.3.3 配置和构建

  • 在 Visual Studio Code 中:安装 "C++" 和 "CMake Tools" 扩展后,打开项目,CMake 工具会自动检测预设并开始配置,期间 vcpkg 会自动安装 vcpkg.json 中声明的依赖。
  • 在命令行中:
bash 复制代码
cmake --preset=default
cmake --build build

4.4 与 Visual Studio 项目集成

如果你使用的是 Visual Studio 并采用清单模式,可以按以下步骤配置:

  1. 确保已执行 vcpkg integrate install
  2. 在项目根目录创建 vcpkg.jsonvcpkg-configuration.json 文件。
  3. 打开 Visual Studio,右键点击项目 → 属性。
  4. 在左侧导航栏找到 vcpkg 选项。
  5. 将 Use Vcpkg 设置为 是。
  6. 将 Use Vcpkg Manifest 设置为 是。

完成配置后,Visual Studio 在构建项目时会自动读取清单文件并安装/更新依赖项。安装的库会位于项目目录下的 vcpkg_installed 文件夹中。

五、进阶功能

5.1 版本控制

  • builtin-baseline:在 vcpkg.json 中通过指定 vcpkg 官方仓库的一个 Git Commit ID,来锁定所有依赖的统一版本基线。
  • overrides:强制覆盖特定包的版本,用于精确控制。

5.2 自定义功能 (Features)

你可以为项目定义可选的功能模块,每个模块可以有自己的依赖。

json 复制代码
{
  "name": "my-game",
  "dependencies": ["grpc"],
  "features": {
    "client": {
      "description": "Client Game Executable",
      "dependencies": ["sdl2", "bullet3"]
    },
    "server": {
      "description": "Multiplayer Server Executable",
      "dependencies": ["proxygen"]
    }
  }
}

安装时,可以通过 --x-feature 选项指定要启用的功能:

bash 复制代码
vcpkg install --x-feature=client

5.3 覆盖端口 (Overlay Ports)

如果你需要修改某个官方库的构建方式(例如为 curl 添加自定义编译选项),可以使用覆盖端口功能。首先创建一个本地目录存放自定义端口,然后通过 vcpkg-configuration.json 或命令行指定该目录。

vcpkg-configuration.json 配置示例:

json 复制代码
{
  "overlay-ports": [
    "./my-overlay"
  ]
}

5.4 清理空间

vcpkg 会下载源码包并编译,占用较多磁盘空间。你可以安全地删除以下文件夹来释放空间,vcpkg 在需要时会重新下载或生成它们:

  • buildtrees/
  • packages/
  • downloads/

六、vcpkg库查找逻辑

vcpkg 查找库的逻辑,本质上是根据名称在多个配置好的"端口"源中按优先级顺序搜索的过程。这个查找发生在执行 vcpkg install 或 CMake 配置(清单模式)时。

为了更清晰地理解,我先把这个查找过程的核心流程图展示出来:
找到
未找到
有配置文件
在某个 registry 找到
所有 registry 未找到
配置了 default-registry
未配置 default-registry
无配置文件
未找到
开始:需要安装库名 "xxx"
在当前上下文环境中查找

(环境变量 / CMake 变量)
检查 覆盖层
✅ 使用覆盖层中的端口
检查 vcpkg-configuration.json
遍历配置中的 registries

(按声明顺序)
✅ 使用该 registry 的端口
检查 default-registry
✅ 使用默认 registry 的端口
❌ 查找失败,报错
使用内置的官方 GitHub registry
✅ 在官方仓库中查找
❌ 查找失败,报错

下面将按优先级从高到低,详细解释每一步的具体规则。

优先级 1:覆盖层 (Overlay Ports) ------ 最高优先级

这是查找的第一站,优先级最高。只要在这里找到库,就会立即使用,不会再往下查找。

  • 本质:一个你指定的本地文件夹路径,里面存放着自定义的端口(每个端口是一个子文件夹,包含 vcpkg.jsonportfile.cmake)。

  • 作用:

    • 覆盖:如果你想修改官方某个库的构建方式(比如改编译选项、打补丁),可以把官方端口复制到覆盖层里修改,vcpkg 就会优先用它。
    • 补充:添加官方没有收录的私有库。
  • 如何指定(三选一即可):

    • CMake 变量(推荐):配置时加 -DVCPKG_OVERLAY_PORTS=你的端口文件夹路径
    • 环境变量:设置 VCPKG_OVERLAY_PORTS
    • 配置文件:在 vcpkg-configuration.json 中写 "overlay-ports" 数组。

优先级 2:配置文件中的注册表 (Registries)

如果覆盖层没找到,vcpkg 就会检查项目根目录下的 vcpkg-configuration.json 文件。这个文件定义了自定义的库搜索源。

查找规则如下:

按 "registries" 数组的声明顺序:vcpkg 会挨个检查你列出的每个注册表(比如公司的私有 Git 仓库、某个团队的注册表)。

找到即停:一旦在某个注册表中找到这个库名,就立即使用,不再往后查。

最后查 "default-registry":如果所有 registries 里都没有,最后才会去 default-registry(通常是官方 GitHub 仓库)里找。

都不存在则失败:如果 default-registry 里也没有,查找就失败了。

你可以把 vcpkg-configuration.json 理解为 Maven 的 settings.xml 或 npm 的 .npmrc,用于精细控制依赖的来源。

优先级 3:默认官方注册表 (Default Registry)

如果没有 vcpkg-configuration.json 文件,或者配置文件里没匹配到任何注册表,vcpkg 就会使用内置的默认源:微软官方 GitHub 仓库 (https://github.com/Microsoft/vcpkg)。

  • 这是最常用的路径:绝大多数情况下,你安装的库都是从这里来的。
  • 版本由 builtin-baseline 锁定:在清单模式(有 vcpkg.json)下,官方仓库的版本由 vcpkg.json 中的 "builtin-baseline" 字段(一个 Git commit ID)锁定,确保版本一致。

一个完整的查找流程示例

假设你的项目要安装 fmt 库,vcpkg 的查找过程是这样的:

  1. 检查覆盖层:你有设置 VCPKG_OVERLAY_PORTS 指向 ./my-ports 吗?或者 CMake 传了 -DVCPKG_OVERLAY_PORTS=... 吗?

    • 如果有:去 ./my-ports 文件夹里找有没有 fmt 子文件夹。

      • 找到:✅ 就用这个 fmt(可能是你修改过的版本)。
      • 没找到:➡️ 进入下一步。
    • 如果没有设置覆盖层:➡️ 直接进入下一步。

  2. 检查 vcpkg-configuration.json:项目根目录下有这个文件吗?

    • 有:读取文件。

      • 假设 registries 数组里第一个是公司私有 Git 仓库 https://git.mycompany.com/vcpkg-registry.git

      • vcpkg 会去这个仓库里找有没有 fmt 这个端口。

        • 找到:✅ 从公司仓库安装。
        • 没找到:继续检查 registries 里的下一个。
      • 如果所有 registries 都没找到,最后去 default-registry(假设配置为官方仓库)。

        • 找到:✅ 从官方仓库安装。
        • 没找到:❌ 报错 error: 'fmt' does not exist in the default registry
    • 没有:➡️ 直接使用默认官方仓库。

      • 去官方 GitHub 仓库找 fmt
      • 找到:✅ 安装。
      • 没找到:❌ 报错(这种情况极少见,因为 fmt 是官方收录的)。

总结与最佳实践

场景 推荐方案
使用官方标准库 什么都不用做,vcpkg 会自动从官方仓库查找。
临时修改某个官方库的构建方式 使用 覆盖层 (Overlay Ports)。把官方端口复制出来修改,通过环境变量或 CMake 变量指定覆盖层路径。
团队内使用私有库,或固定某个特定版本的库 使用 vcpkg-configuration.json 配置私有 Git 注册表,并在 vcpkg.json 中用 overrides 锁定版本。
需要完全控制所有依赖的来源 同时使用覆盖层 + 配置文件,并把 default-registry 设为 null,强制所有库都必须从你指定的源找到。

理解了这个查找逻辑,你就能灵活地控制 vcpkg 从哪里获取依赖,无论是使用公共库、修改官方库,还是管理私有库,都能得心应手。

七、临时修改某个官方库的构建方式

临时修改某个官方库的构建方式,最核心的方法就是使用 vcpkg 的 覆盖端口 (Overlay Ports) 功能。这个功能可以让你在本地创建一个"定制版"的库,vcpkg 在安装时会优先使用你定制的版本,而不是官方仓库中的版本。

整个过程大致分为三步:
第三步:使用
通过命令行

--overlay-ports 指定目录
安装时,vcpkg 会

优先使用你的定制版本
第二步:定制
复制官方库的

vcpkg.json 和 portfile.cmake
按需修改

构建脚本和配置
第一步:准备
创建覆盖目录

例如:./my-overlay/
在目录下创建

以库名命名的子文件夹

例如:./my-overlay/zlib/

下面我们详细看看每一步具体怎么做。

第一步:准备覆盖目录

首先,在你的项目或任意位置创建一个文件夹,用来存放所有自定义的库。通常建议放在项目根目录下,方便管理。

例如,创建一个名为 my-overlay 的文件夹。然后,在这个文件夹里,为你要修改的库再创建一个子文件夹,名字必须和官方库的名字完全一致。

bash 复制代码
# 假设你要修改的是 zlib 库
mkdir -p my-overlay/zlib

这样,目录结构就是:

复制代码
your-project/
├── my-overlay/
│   └── zlib/          # 名字必须和官方库名一致
│       └── ...
├── CMakeLists.txt
└── vcpkg.json

第二步:复制并修改官方端口文件

接下来,你需要从 vcpkg 的官方安装目录中找到这个库的"端口 (port)",把它复制到你刚刚创建的 my-overlay/zlib/ 文件夹下。

一个标准的端口通常包含两个核心文件:

  1. vcpkg.json: 声明库的元数据,如名称、版本、依赖项等。
  2. portfile.cmake: 核心构建脚本,定义了如何下载源码、配置、编译和安装。

官方端口的位置通常在 <vcpkg的安装根目录>/ports/<库名>/ 下。

找到后,将这两个文件复制到你的 my-overlay/zlib/ 目录中。现在,你可以开始自由修改了:

  • 修改 portfile.cmake:这是最常用的方式。你可以在这里调整 CMake 配置参数、给源码打补丁、替换下载地址等。例如,如果你想在编译 zlib 时开启某个特定的编译选项(如 ZLIB_COMPAT),可以在 vcpkg_cmake_configure() 调用前添加相应的 -D 参数。
  • 修改 vcpkg.json:通常不需要改动,但如果你的修改引入了新的依赖,或者改变了库的版本,可以在这里更新。

进阶技巧:使用 Overlay Triplets 调整编译参数

如果你的修改只是想改变一些全局的编译选项(例如,为某个特定的库开启一个特殊的宏),但又不想完整复制一个 portfile.cmake,可以使用 覆盖三元组 (Overlay Triplets)。

这需要你创建一个 my-triplets 文件夹,并在其中放置修改过的三元组文件(如 x64-windows.cmake),然后在脚本中根据 PORT 变量来判断是否为特定库添加参数:

cmake 复制代码
# 在 my-triplets/x64-windows.cmake 文件中
if (PORT STREQUAL "zlib-ng")
    set(ZLIB_COMPAT ON)
endif()

使用时,通过 --overlay-triplets=./my-triplets 来指定。

第三步:让 vcpkg 使用你的定制版本

现在,需要告诉 vcpkg 优先去你的 my-overlay 目录里找库。有三种方式,选择最适合你的一种即可:

  1. 命令行指定 (最直接)
    在每次执行 vcpkg install 时,通过 --overlay-ports 参数指定路径。
bash 复制代码
vcpkg install zlib --overlay-ports=./my-overlay
  1. 项目配置文件指定 (推荐,适合团队协作) 在项目根目录的 vcpkg-configuration.json 文件中,添加 "overlay-ports" 数组。这样,团队成员无需额外操作就能自动使用相同的覆盖配置。
json 复制代码
{
  "default-registry": { ... },
  "overlay-ports": [ "./my-overlay" ]
}
  1. 环境变量指定 (全局生效)
    设置 VCPKG_OVERLAY_PORTS 环境变量,将其指向你的 my-overlay 目录。这种方法会影响所有使用该环境变量的 vcpkg 操作。

完成以上设置后,当你的项目(无论是通过 vcpkg install 命令还是 CMake 的 manifest 模式)尝试安装 zlib 时,vcpkg 会按照"覆盖端口 -> 自定义注册表 -> 官方注册表"的顺序查找。由于你的 my-overlay 优先级最高,它会直接使用你定好的版本进行构建。

总结与最佳实践

  1. 为每个库单独创建文件夹:在 my-overlay 下,确保每个要修改的库都有一个独立的子文件夹,并且名字与官方库名完全一致。
  2. 仅修改必要的文件:通常只需复制并修改 portfile.cmake,这能满足大部分构建定制的需求。
  3. 妥善维护:你的定制版本是独立于 vcpkg 官方更新的。当官方端口有重要更新(如安全补丁)时,你需要手动将更新合并到你的覆盖端口文件中。
  4. 团队协作首选 vcpkg-configuration.json:将 overlay-ports 配置在项目文件中,可以确保所有开发者使用一致的、项目指定的依赖构建方式,实现"配置即代码"。

一个简单的路径示例:

假设你正在使用 manifest 模式,那么你的项目目录结构最终可能会是这样:

复制代码
 your-project/
├── my-overlay/
│   └── zlib/                 # 你定制过的 zlib 端口
│       ├── portfile.cmake    # 修改过的构建脚本
│       └── vcpkg.json        # 可选的元数据文件
├── vcpkg.json                # 项目清单,声明依赖 zlib
├── vcpkg-configuration.json  # 项目配置,声明 overlay-ports 路径
└── CMakeLists.txt

以curl库示例

以修改 curl 为例,来完整走一遍流程。先创建目录,复制官方端口文件,然后根据需求修改 portfile.cmake。

第一步:创建覆盖目录并复制官方端口

bash 复制代码
# 在项目根目录下创建覆盖目录
mkdir -p my-overlay/curl

# 复制官方 curl 端口文件
cp -r <vcpkg安装路径>/ports/curl/* my-overlay/curl/

官方端口文件通常包含这些关键文件:

文件 作用
vcpkg.json 端口元数据:名称、版本、依赖、特性声明
portfile.cmake 核心构建脚本:下载源码、配置编译选项
其他辅助文件 如 usage 文件、wrapper 等

第二步:修改 portfile.cmake 实现定制

curl 的 portfile.cmake 中大量使用 vcpkg_check_features() 来将特性映射到构建选项:

cmake 复制代码
# curl portfile.cmake 中的典型特性映射
vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
    FEATURES
        http2       USE_NGHTTP2
        openssl     CURL_USE_OPENSSL
        schannel    CURL_USE_SCHANNEL
        sspi        CURL_USE_SSPI
        winssl      CURL_USE_WINSSL  # 旧版
    INVERTED_FEATURES
        ldap        CURL_DISABLE_LDAP
)

常见的定制需求及修改方式:

  1. 切换 TLS 后端(如从 Schannel 改为 OpenSSL)
cmake 复制代码
# 在 vcpkg_check_features 调用之前添加
# 强制使用 OpenSSL 而非 Schannel
set(CURL_USE_OPENSSL ON)
set(CURL_USE_SCHANNEL OFF)
  1. 添加自定义编译宏
cmake 复制代码
# 在 vcpkg_cmake_configure 调用之前
set(EXTRA_OPTIONS
    -DCURL_ENABLE_CURL_OPTION=ON
    -DENABLE_CUSTOM_FEATURE=1
)

# 然后在 vcpkg_cmake_configure 的 OPTIONS 参数中添加
vcpkg_cmake_configure(
    SOURCE_PATH "${SOURCE_PATH}"
    OPTIONS 
        ${FEATURE_OPTIONS}
        ${EXTRA_OPTIONS}   # 添加自定义选项
        # ... 其他选项
)
  1. 静态库的额外处理

curl 在静态链接时可能需要特殊的处理。在 portfile.cmake 中通常会看到类似这样的逻辑:

cmake 复制代码
# 静态库时修改头文件中的默认宏
if(VCPKG_LIBRARY_LINKAGE STREQUAL "static")
    # 在 Windows 上静态链接时需要定义 CURL_STATICLIB
    if(VCPKG_TARGET_IS_WINDOWS)
        vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/include/curl/curl.h"
            "#ifdef CURL_STATICLIB"
            "#if 1")
    endif()
endif()
  1. 禁用不需要的协议或特性
cmake 复制代码
# 在调用 vcpkg_check_features 之后,可以覆盖某些选项
set(EXTRA_OPTIONS
    -DCURL_DISABLE_FTP=ON      # 禁用 FTP
    -DCURL_DISABLE_POP3=ON     # 禁用 POP3
    -DCURL_DISABLE_SMTP=ON     # 禁用 SMTP
    -DCURL_DISABLE_TELNET=ON   # 禁用 Telnet
    -DCURL_DISABLE_TFTP=ON     # 禁用 TFTP
)

第三步:使用覆盖端口

有两种方式让你的项目使用修改后的 curl:

方式一:通过 vcpkg-configuration.json(推荐团队协作)

在项目根目录创建 vcpkg-configuration.json:

json 复制代码
{
    "default-registry": {
        "kind": "git",
        "repository": "https://github.com/Microsoft/vcpkg",
        "baseline": "3426db05b996481ca31e95fff3734cf23e0f51bc"
    },
    "overlay-ports": [
        "./my-overlay"
    ]
}

方式二:命令行临时指定

bash 复制代码
vcpkg install curl --overlay-ports=./my-overlay

或在 CMake 配置时:

bash 复制代码
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=<vcpkg>/scripts/buildsystems/vcpkg.cmake \
    -DVCPKG_OVERLAY_PORTS=./my-overlay

如果只是想切换 curl 的 TLS 后端(更简单的方案)

如果你不是要修改构建逻辑,而只是想更换 curl 使用的 TLS 库(比如从默认的 Windows Schannel 换成 OpenSSL),其实不需要使用覆盖端口,直接在 vcpkg.json 中声明即可:

json 复制代码
{
    "name": "my-project",
    "version": "1.0.0",
    "dependencies": [
        {
            "name": "curl",
            "default-features": false,    // 关闭默认特性(包括 schannel)
            "features": ["openssl"]       // 只开启 openssl 后端
        }
    ]
}

为什么这样可以? 因为 curl 端口在设计时就考虑到了 TLS 后端的可选择性,OpenSSL 和 Schannel 被定义为不同的 feature(特性)。用户可以通过选择不同的 feature 来切换后端,而不需要覆盖整个端口。

完整示例:修改 curl 添加自定义 CA 路径

假设你希望 curl 使用自定义的 CA 证书包:

cmake 复制代码
# 在 portfile.cmake 中找到 vcpkg_cmake_configure 调用处
# 添加以下选项:

vcpkg_cmake_configure(
    SOURCE_PATH "${SOURCE_PATH}"
    OPTIONS
        ${FEATURE_OPTIONS}
        -DCURL_CA_BUNDLE="C:/custom/ca-bundle.crt"  # 自定义 CA 路径
        # ... 其他现有选项
)

建议先用 vcpkg edit curl 命令查看官方端口文件的完整内容,再决定需要修改哪些部分。

总结

定制需求 推荐方案 是否需要覆盖端口
切换 TLS 后端(OpenSSL/Schannel) 在 vcpkg.json 中用 features 选择 ❌ 不需要
禁用/启用某些协议(FTP、SMTP 等) 修改 portfile.cmake 中的 CMake 选项 ✅ 需要
添加自定义编译宏 修改 portfile.cmake ✅ 需要
修改静态库的头文件行为 修改 portfile.cmake 中的后处理逻辑 ✅ 需要
替换源码下载地址或打补丁 修改 portfile.cmake 中的 vcpkg_from_github ✅ 需要

八、vcpkg查找自定义库

要让 vcpkg 找到你私有的或修改过的自定义库,核心方法是使用覆盖端口 (Overlay Ports)。它本质上是一个本地文件夹,拥有最高查找优先级,让你可以轻松地覆盖官方库或添加全新的库。

整个过程分为两步:1) 编写自定义库的端口文件;2) 配置 vcpkg 使用这个覆盖端口。下面我会用mylib这个库来演示具体怎么做。

第一步:编写自定义端口 (Port)

端口是一个文件夹,里面必须包含两个文件,定义了如何获取和构建你的库。

  1. 创建目录:在项目里新建一个文件夹,比如 my-overlay,然后在里面为你的库 mylib 创建一个子目录。
bash 复制代码
mkdir -p my-overlay/mylib
  1. 创建 vcpkg.json (元数据):在 my-overlay/mylib 文件夹下创建此文件,声明库的基本信息。对于私有库,"version" 字段可以用日期等自定义。
json 复制代码
{
  "name": "mylib",
  "version": "1.0.0",
  "description": "My custom library",
  "license": "MIT"
}
  1. 创建 portfile.cmake (构建脚本):在相同目录下创建此文件,它是告诉 vcpkg 如何下载和编译库的核心脚本。这里分几种情况:

情况A:库在本地源码目录

cmake 复制代码
# 假设你的库源码在项目根目录下的 libsrc/mylib 文件夹中
vcpkg_check_linkage(ONLY_STATIC_LIBRARY) # 可选:限制为静态库

# 直接将源码路径赋值给 SOURCE_PATH
set(SOURCE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../libsrc/mylib")

# 如果你的库是用 CMake 构建的
vcpkg_cmake_configure(
    SOURCE_PATH "${SOURCE_PATH}"
)
vcpkg_cmake_install()
vcpkg_cmake_config_fixup()

情况B:库托管在 Git 仓库 (如 GitHub)

cmake 复制代码
vcpkg_check_linkage(ONLY_STATIC_LIBRARY)

# 从 GitHub 下载源码
vcpkg_from_github(
    OUT_SOURCE_PATH SOURCE_PATH
    REPO <你的GitHub用户名>/mylib   # 仓库地址
    REF v1.0.0                      # 标签或提交ID
    SHA512 0                        # 首次设为0,运行后会提示正确哈希值
)

vcpkg_cmake_configure(
    SOURCE_PATH "${SOURCE_PATH}"
)
vcpkg_cmake_install()
vcpkg_cmake_config_fixup()

获取 SHA512 哈希值:在 SHA512 处先填 0,然后运行 vcpkg install --overlay-ports=... 命令,安装会失败,但控制台会打印出正确的哈希值,复制并替换掉文件中的 0 即可。

第二步:配置 vcpkg 使用覆盖端口

告诉 vcpkg 去你的 my-overlay 文件夹查找,有以下三种方式。推荐使用第一种,它对团队协作最友好。

  1. 项目级配置 (最佳实践):在项目根目录的 vcpkg-configuration.json 文件中添加 "overlay-ports" 数组。此文件通常与 vcpkg.json 并列。
json 复制代码
{
  "overlay-ports": [
    "./my-overlay"   # 指向你第一步创建的文件夹
  ]
}

配置好后,在项目的 vcpkg.json 中像使用普通库一样声明 "mylib" 即可。团队成员拉取代码后,无需额外配置就能自动识别。

  1. 命令行指定 (快速测试):在每次执行 vcpkg 命令时通过参数指定。
cmake 复制代码
vcpkg install mylib --overlay-ports=./my-overlay

或者在 CMake 配置时:

bash 复制代码
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=<vcpkg路径>/scripts/buildsystems/vcpkg.cmake \
      -DVCPKG_OVERLAY_PORTS=./my-overlay
  1. 全局环境变量 (永久生效):设置 VCPKG_OVERLAY_PORTS 环境变量。这会作用于你电脑上所有使用 vcpkg 的地方,可能会造成干扰,一般不太推荐。

一个更巧妙的用法:用覆盖端口"替换"官方库

这个功能非常强大。如果你想用 zlib-ng 来完全替代官方的 zlib,可以利用覆盖端口的优先级来"偷梁换柱"。

原理:vcpkg 查找库时,my-overlay 的优先级高于官方仓库。你只需在 my-overlay 里创建一个名为 zlib 的端口,并在其 vcpkg.json 中写上 "dependencies": ["zlib-ng"]。

这样,当任何项目依赖 zlib 时,vcpkg 会先找到你的覆盖端口,然后自动去安装 zlib-ng。对项目来说,它毫不知情,依然在请求 zlib,但实际获得的却是 zlib-ng。

九、官方文档与资源

vcpkg 的官方文档已迁移至 Microsoft Learn 平台,你可以通过以下链接获取最新、最全面的信息:

相关推荐
爱莉希雅&&&2 小时前
MySQL MGR + MySQL Router 高可用集群完整笔记(含手动配置 + Shell 接管双路线)
linux·数据库·笔记·mysql·mysqlrouter·mysqlshell
楼田莉子2 小时前
仿Muduo的高并发服务器:LoopThread模块及其ThreadPool模块
linux·服务器·c++·后端·学习
盐焗鹌鹑蛋2 小时前
【C++】模板进阶
c++
繁星蓝雨2 小时前
Qt多界面创建的优化问题(main函数或主界面中创建?)—————附带详细方法
c++·qt·架构·多界面管理
Cx330❀3 小时前
Qt 入门指南:从零搭建开发环境到第一个图形界面程序
xml·大数据·开发语言·网络·c++·人工智能·qt
蜡笔小马3 小时前
02.C++设计模式—建造者模式详解
c++
诙_3 小时前
深入理解C++设计模式
c++·设计模式
南境十里·墨染春水3 小时前
linux 学习进展 网络编程 ——TCP 协议 TIME_WAIT 状态详解
linux·网络·学习
昵称小白3 小时前
C++ 刷题语法速查
c++·算法