vcpkg安装与使用教程

一、什么是vcpkg

vcpkg是用于C++的一种命令行包管理器。它极大地简化了 Windows、Linux 和 MacOS 上第三方库的购置与安装。如果项目要使用第三方库,建议通过vcpkg来安装它们。 vcpkg 同时支持开源和专有库。

二、为什么要用vcpkg

  • 传统使用开源库的方法
    Windows下开发C/C++程序,少不了编译开源的第三方库。比如用于网络连接的高性能库libcurl、用于压缩解压的zlib等等。使用这些库开发极大的方便了程序员,使得我们不必重复造轮子。但是使用这些库必须要处理以下问题。
  • 编译工具
    由于这些开源库绝大部分都来源于Linux系统,导致其工程文件、编译系统都使用gnu系列工具,使得将其移植到Windows的VC开发环境下一直是难点。尽管最近几年很多开源库都支持了跨平台的cmake,但是编译过程仍然复杂和多样化。
  • 常见的编译方式有:
编译方式特点举例
configure、make需要msys这样的unix环境才可以编译ffmpeg
自定义编译工具需要学习特定的编译命令和工具openssl、boost
cmake相对简单轻松libcurl
VC工程文件这种最简单,直接拿来即可编译 
  • 编译类型
    当了解了这些还不够,我们还需要考虑预先编译出哪种类型的开源库程序。比如:Debug还是Release、动态库还是静态库、MD还是MT、32位还是64位。光是这三种组合就有16种可能性。如果像libcurl这种还要考虑是否引用其他开源库的功能,那么编译类型的组合会更多。管理起来很麻烦。
  • 工程目录设定
    由于多样的编译类型,工程目录也必须仔细设定才能保证自己的软件项目能够正常编译。
  • Vcpkg的优点
    自动下载开源库源代码
    源码包的缓存管理和版本管理,可以升级版本
    轻松编译
    依赖关系检查(比如编译libcurl,会自动下载zlib、openssl进行编译)
    无缝集成Visual Studio,不需要设置库文件、头文件的所在目录,自动集成。
    Visual Studio全平台支持,不仅支持Debug/Release、x86/x64编译,还支持UWP、ARM平台的编译。

三、获取

Vcpkg的官方源码站点为:https://github.com/microsoft/vcpkg

帮助文档:https://learn.microsoft.com/zh-cn/vcpkg/get_started/overview

四、编译

Vcpkg大量使用的psl脚本,所以官方强烈推荐使用PowerShell而不时CMD命令行来执行各种操作。尽管在使用的时候兼容CMD,但是在编译这一步,请使用PowerShell。本文的操作都使用PowerShell 7

编译很简单,执行Vcpkg工程目录下的“bootstrap-vcpkg.bat”文件,即可编译。编译好以后会在同级目录下生成vcpkg.exe文件。编译期间,脚本会自动下载vswhere组件。

五、使用

5.1 搜索vcpkg支持的开源库

例如不确定vcpkg是否存在jsoncpp库,可以通过下面命令搜索,它将返回所有包含jsoncpp字样的库。

vcpkg search jsoncpp

5.2 安装一个开源库

这里的“安装”其实是指下载源码和编译。
比如安装jsoncpp库,那么执行命令

vcpkg install jsoncpp
  1. 环境初始化
  2. 下载源代码(如果已经在vcpkg\downloads文件夹中,则不重复下载)
  3. 校验文件有效性
  4. 解压缩源代码
  5. 利用配套工具配置源码工程,在这里是使用的是cmake(如果是ffmpeg,则用msys2)
  6. 编译源码。一般会同时编译Release和Debug版本。
  7. 把编译好的文件拷贝到相关文件夹中去(一般是vcpkg\installed文件夹)

5.3 指定编译架构

如果不指定安装的架构,vcpkg默认把开源库编译成当前操作系统架构的库。那vcpkg总共支持多少种架构呢?我们可以使用如下命令便知:

vcpkg help triplet

这个清单以后随着版本的迭代还会再增加。vcpkg不仅支持x86架构,还支持arm架构。注意:这里的arm架构特指类似于surface这种运行在arm处理器上的Win10平台,而并非我们传统意义上的Linux或android的ARM平台。

那如果要安装编译某一个架构的开源库,我们只需要在需要安装的包后面指定相应的triplet即可。例如我们需要编译64位版本的jsoncpp,那么执行如下命令:

vcpkg install jsoncpp:x64-windows-release

5.4 移除一个已经安装(编译)的开源库

如果移除一个已经安装的开源库,那么执行remove指令即可。比如我们要移除jsoncpp,那么执行命令:

vcpkg remove jsoncpp

5.5 列出已经安装的开源库

vcpkg list

5.6 更新已经安装的开源库

一般有两种更新方式。一个是update指令,可以显示可以升级的开源库的列表。另一个是upgrade的指令,会编译所有需要更新的包。

由于vcpkg是使用本地缓存列表的方式,而不是实时去获取最新列表,因此建议每间隔一个月在vcpkg安装目录下执行一次git pull,然后再使用下面的命令更新:

vcpkg upgrade --no-dry-run

只更新指定的某个包,例如:opencv4:x64-windows

vcpkg upgrade opencv4:x64-windows --no-dry-run

5.7 获取指定版本的开源库

当我们需要某个旧版本的库时,一种方式是通过git将vcpkg整个回滚到指定的旧版本,这会导致所有库都回滚。另外一种是通过vcpkg的清单模式(Manifest Mode),将指定版本的库下载到指定文件夹中。这里着重介绍这种方式,例如我们需要grpc的1.68.2和protobuf的5.29.2版本,在项目根目录中创建vcpkg.json文件:

{
  "dependencies": [
    {
      "name": "grpc"
    },
    {
       "name": "protobuf"
    }
  ],
  "overrides": [
    { "name": "grpc", "version": "1.68.2" },
    { "name": "protobuf", "version": "5.29.2" }
  ]
}

然后在项目根目录中执行vcpkg命令:

vcpkg x-update-baseline --add-initial-baseline
vcpkg install --feature-flags=versions

指定版本的开源库将被安装到项目根目录的vcpkg_installed文件夹中。

六、集成

上面我们已经安装了一些第三方库,那如何使用呢?常规情况下,我们需要设置include目录、lib目录等,会有很多工作量。而vcpkg提供了一套机制,可以全自动的适配目录,而开发者不需要关心已安装的库的目录在哪里,也不需要设置。这是vcpkg的一大优势。

6.1 与 Visual Studio 集成

执行命令:

vcpkg integrate install

当出现“Applied user-wide integration for this vcpkg root.”字样的时候,说明已经集成成功。这时候可以在任意的工程中使用安装好的第三方库,通过<库名\头文件>的方式即可引入需要的头文件,并会自动在项目输出目录中创建所需的dll等。

移除全局集成只要执行命令:vcpkg integrate remove

6.2 与 CMake(GUI)集成

在CMake的配置参数中,增加vcpkg工具链的路径:”-DCMAKE_TOOLCHAIN_FILE=${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake”。

CMakeLists.txt中添加:SET(CMAKE_TOOLCHAIN_FILE $ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake)

如果使用CMake的GUI,则在点击Configure按钮之前先点击Add Entry按钮,然后输入以下信息:

  • Name:CMAKE_TOOLCHAIN_FILE
  • Type:FILEPATH
  • Value:指向vcpkg的 scripts/buildsystems/vcpkg.cmake 文件的完整路径。

6.3 pkg-config集成

vcpkg在安装完成开源库后生成相应的pkg-config文件,我们可以在CMakeLists.txt中引入它。例如引入protobuf库:

# 设置pkg-config文件所在目录
set(ENV{PKG_CONFIG_PATH} "C:/vcpkg/installed/x64-windows/lib/pkgconfig;$ENV{PKG_CONFIG_PATH}")

# 引入 FindPkgConfig 模块
find_package(PkgConfig REQUIRED)

# 使用 pkg-config 查找 protobuf
pkg_check_modules(PROTOBUF REQUIRED protobuf)

# 使用 pkg-config 获取的信息
target_include_directories(my_app PRIVATE ${PROTOBUF_INCLUDE_DIRS})
target_link_directories(my_app PRIVATE ${PROTOBUF_LIBRARY_DIRS})
target_link_libraries(my_app PRIVATE ${PROTOBUF_LIBRARIES})

其中PROTOBUF是可以修改的自定义前缀。

七、设置网络代理

条件允许的话尽量使用代理吧,这样就不会出现下载慢或下载失败的情况了。

在Windos平台的PowerShell中依据你的代理服务器配置执行下面命令,例如:

$env:HTTP_PROXY="127.0.0.1:10809" 
$env:HTTPS_PROXY="127.0.0.1:10809"

在Linux平台的终端中,例如:

export http_proxy=http://127.0.0.1:10809
export https_proxy=http://127.0.0.1:10809

八、可能遇到的问题

8.1 下载慢

设置Powershell使用网络代理,参考上一章节。

8.2 Failed to do post-extract rename-in-place.

例如:

Failed to do post-extract rename-in-place.
fs.rename(D:\SoftwareDevelopment\vcpkg\downloads\tools\git-2.25.1-1-windows.partial.34372, D:\SoftwareDevelopment\vcpkg\downloads\tools\git-2.25.1-1-windows, operation not permitted)

字面意思是权限不足,重命名失败,但我明明是用管理员权限运行的PowerShell。

手动重命名提示的文件(夹)即可。这里是将git-2.25.1-1-windows.partial.34372文件夹重命名为git-2.25.1-1-windows

8.3 Building package boost-compatibility:x86-windows failed with: BUILD_FAILED

遇到这种问题,需要通过日志查看具体出错原因,寻找FailedError关键字。

例如:Downloading https://raw.githubusercontent.com/boostorg/boost/boost-1.72.0/boostcpp.jamFailed.

vcpkg\downloads\temp文件里有一个大小为0的boost-1.72.0-boostcpp.jam文件。注意文件名不完全相同,说明它需要下载后重命名。

下载时出错,重试多次都不行,网络也没问题。那就复制地址,用浏览器下载这个文件,然后保存在vcpkg\downloads文件夹里并重命名boost-1.72.0-boostcpp.jam就行了。

8.4 CMake Error: Problem with archive_write_header(): Can’t create ”

PowerShell中报类似如下的错误:

Building package expat[core]:x86-windows…
— Downloading https://github.com/libexpat/libexpat/archive/R_2_2_7.tar.gz…
— Extracting source D:/CDH/vcpkg/downloads/libexpat-libexpat-R_2_2_7.tar.gz
CMake Error at scripts/cmake/vcpkg_execute_required_process.cmake:72 (message):
Command failed: D:/CDH/vcpkg/downloads/tools/cmake-3.14.0-windows/cmake-3.14.0-win32-x86/bin/cmake.exe -E tar xjf D:/CDH/vcpkg/downloads/libexpat-libexpat-R_2_2_7.tar.gz
Working Directory: D:/CDH/vcpkg/buildtrees/expat/src/TEMP
Error code: 1
See logs for more information:
D:\CDH\vcpkg\buildtrees\expat\extract-err.log

Call Stack (most recent call first):
scripts/cmake/vcpkg_extract_source_archive.cmake:43 (vcpkg_execute_required_process)
scripts/cmake/vcpkg_extract_source_archive_ex.cmake:108 (vcpkg_extract_source_archive)
scripts/cmake/vcpkg_from_github.cmake:139 (vcpkg_extract_source_archive_ex)
ports/expat/portfile.cmake:6 (vcpkg_from_github)
scripts/ports.cmake:90 (include)

在其中的extract-err.log里,是:

CMake Error: Problem with archive_write_header(): Can’t create ”
CMake Error: Current file: libexpat-R_2_2_7/README.md
CMake Error: Problem extracting tar: D:/CDH/vcpkg/downloads/libexpat-libexpat-R_2_2_7.tar.gz

解决方案是打开“控制面板->区域->管理->更改系统区域设置”,取消勾选“Beta版:使用Unicode UTF-8提供全球语言支持”。

8.5 Please install the English language pack

打开Visual Studio Installer,在“语言包”里勾选“英语”进行安装。

九、参考文档

留下评论

您的邮箱地址不会被公开。 必填项已用 * 标注