没事造轮子没事造轮子

没事造轮子

vcpkg 入门指南

  • W_Z_C
  • 阅读约 8 分钟
vcpkg 入门指南

SDL2 入门教程里我介绍过 SDL2 的静态编译相关的内容,其中 SDL2 官方只提供了动态库,静态库需要自己亲手编译,特别是 SDL_image 和 SDL_ttf 对其它库还有依赖的前提下,对新手来说很不友好。这里推荐一个 Windows 平台下的包管理器: vcpkg。官网上 vcpkg 是这样介绍的:

vcpkg 是一个免费的 C/C++ 包管理器,可以用于获取和管理第三方库。目前 支持 1500 多种开源库,从下载到编译一步即可完成。你可以使用它来管理的第三方依赖,并可以简化你程序的构建过程。目前该项目开源并由 Microsoft C++ 团队主导。

虽然 vcpkg 是由微软团队来主导的,但其实很多库都是其它开源贡献者提供的,所以有时候你在安装个别库的时候,会遇见下面的提示信息:

# this is heuristically generated, and may not be correct

不过无需过分担心,一般遇见这种是因为官方不推荐的编译方式,例如 SDL2 的静态编译,你使用 vcpkg 安装的时候就会遇见,如果你在使用过程中发现问题,可以尝试去提交 issue。

vcpkg 本身是支持跨平台的,但是这里我只拿 Windows 下的 SDL2 作为案例简单的介绍一下 vcpkg 的使用。

1. 安装

vcpkg 使用起来非常方便,不过在 Windows 上使用是有一些前提条件的。首先必须是 Windows 7 以上的系统,然后你的计算机必须预先安装 Git 软件,除此之外,如果需要和 Visual Studio 集成的话,必须需要提前安装 Visual Studio 2015 Update3 以上版本。

因为 vcpkg 在使用过程中会依赖两个东西,一个是 PowerShell-core,另一个是 CMake。这里强烈大家先去官网下载最新版安装,虽然 vcpkg 在使用的过程中会自动安装它们,但是国内的下载速度非常感人。

vcpkg 安装的第一步就是使用 Git 克隆其代码库到本地:

git clone https://github.com/Microsoft/vcpkg.git

克隆代码的过程基本等价于其它软件的安装过程,所以你最好将代码直接克隆到最终的安装目录,否则可能还需要额外的移动操作。

克隆成功之后,启动终端,切换到 vcpkg 的根目录,然后运行该目录下的 bootstrap-vcpkg 脚本文件:

.\bootstrap-vcpkg.bat

该脚本会直接在当前目录下生成最终的 vcpkg.exe 程序。目前最新的脚本其实就是从官方网站下载编译好的文件而已,如果大家下载比较慢,也可以直接复制 scripts/bootstrap.ps1 中的最终地址手动下载。

为了以后使用方便,推荐大家将 vcpkg 目录放到 PATH 环境变量中,方便后续使用。

2. 命令行

下面简单的介绍几个 vcpkg 常用的命令:

  • vcpkg help 用来查看 vcpkg 的帮助文档。
C:\dev\vcpkg>vcpkg help
Commands:
  vcpkg search [pat]              Search for packages available to be built
  vcpkg install ...          Install a package
  vcpkg remove ...           Uninstall a package
  vcpkg remove --outdated         Uninstall all out-of-date packages
  vcpkg list                      List installed packages
  vcpkg update                    Display list of packages for updating
  vcpkg upgrade                   Rebuild all outdated packages
  vcpkg x-history            (Experimental) Shows the history of CONTROL versions of a package
  vcpkg hash  [alg]         Hash a file by specific algorithm, default SHA512
  vcpkg help topics               Display the list of help topics
  vcpkg help               Display help for a specific topic

  vcpkg integrate install         Make installed packages available user-wide. Requires admin
                                  privileges on first use
  vcpkg integrate remove          Remove user-wide integration
  vcpkg integrate project         Generate a referencing nuget package for individual VS project use
  vcpkg integrate powershell      Enable PowerShell tab-completion

  vcpkg export ... [opt]...  Exports a package
  vcpkg edit                 Open up a port for editing (uses %EDITOR%, default 'code')
  vcpkg create   [archivename]
                                  Create a new package
  vcpkg x-init-registry     Initializes a registry in the directory 
  vcpkg format-manifest --all     Formats all vcpkg.json files. Run this before committing to vcpkg.
  vcpkg owns                 Search for files in installed packages
  vcpkg depend-info ...      Display a list of dependencies for packages
  vcpkg env                       Creates a clean shell environment for development or compiling
  vcpkg version                   Display version information
  vcpkg contact                   Display contact information to send feedback

Options:
  --triplet=                   Specify the target architecture triplet. See 'vcpkg help triplet'
                                  (default: %VCPKG_DEFAULT_TRIPLET%)
  --host-triplet=              Specify the host architecture triplet. See 'vcpkg help triplet'
                                  (default: %VCPKG_DEFAULT_HOST_TRIPLET%)
  --overlay-ports=          Specify directories to be used when searching for ports
                                  (also: %VCPKG_OVERLAY_PORTS%)
  --overlay-triplets=       Specify directories containing triplets files
                                  (also: %VCPKG_OVERLAY_TRIPLETS%)
  --binarysource=           Add sources for binary caching. See 'vcpkg help binarycaching'
  --x-asset-sources=        Add sources for asset caching. See 'vcpkg help assetcaching'
  --downloads-root=         Specify the downloads root directory
                                  (default: %VCPKG_DOWNLOADS%)
  --vcpkg-root=             Specify the vcpkg root directory
                                  (default: %VCPKG_ROOT%)
  --x-buildtrees-root=      (Experimental) Specify the buildtrees root directory
  --x-install-root=         (Experimental) Specify the install root directory
  --x-packages-root=        (Experimental) Specify the packages root directory
  --x-json                        (Experimental) Request JSON output

  @response_file                  Specify a response file to provide additional parameters

For more help (including examples) see the accompanying README.md and docs folder.
  • vcpkg list 查看当前安装的开源库列表。
C:\dev\vcpkg>vcpkg list
brotli:x64-windows-static                          1.0.9#2          a generic-purpose lossless compression algorithm...
bzip2:x64-windows-static                           1.0.8#2          bzip2 is a freely available, patent free, high-q...
freetype:x64-windows-static                        2.12.1           A library to render fonts.
freetype[brotli]:x64-windows-static                                 Support decompression of WOFF2 streams
freetype[bzip2]:x64-windows-static                                  Support bzip2 compressed fonts.
freetype[png]:x64-windows-static                                    Support PNG compressed OpenType embedded bitmaps.
freetype[zlib]:x64-windows-static                                   Use zlib instead of internal library for DEFLATE
libpng:x64-windows-static                          1.6.37#18        libpng is a library implementing an interface fo...
sdl2-image:x64-windows-static                      2.0.5#6          SDL_image is an image file loading library. It l...
sdl2-mixer:x64-windows-static                      2.0.4#16         Multi-channel audio mixer library for SDL.
sdl2-mixer[nativemidi]:x64-windows-static                           Support for MIDI audio format on Windows and macOS.
sdl2-ttf:x64-windows-static                        2.0.15#5         A library for rendering TrueType fonts with SDL
sdl2:x64-windows-static                            2.0.22#1         Simple DirectMedia Layer is a cross-platform dev...
vcpkg-cmake-config:x64-windows                     2022-02-06#1
vcpkg-cmake:x64-windows                            2022-06-07
zlib:x64-windows-static                            1.2.12#1         A compression library
  • vcpkg search xxx 搜索现有可以安装的第三方库。
C:\dev\vcpkg>vcpkg search SDL2
ffmpeg[sdl2]                              Sdl2 support
imgui[sdl2-binding]                       Make available SDL2 binding
imgui[sdl2-renderer-binding]              Make available SDL2 Renderer binding
magnum[sdl2application]                   Sdl2Application library
sdl2                     2.0.22#1         Simple DirectMedia Layer is a cross-platform development library designed ...
sdl2[vulkan]                              Vulkan functionality for SDL
sdl2[x11]                                 Dynamically load X11 support
sdl2-gfx                 1.0.4#8          Graphics primitives (line, circle, rectangle etc.) with AA support, rotozo...
sdl2-image               2.0.5#6          SDL_image is an image file loading library. It loads images as SDL surface...
sdl2-image[libjpeg-turbo]                 Support for JPEG image format
sdl2-image[libwebp]                       Support for WEBP image format.
sdl2-image[tiff]                          Support for TIFF image format
sdl2-mixer               2.0.4#16         Multi-channel audio mixer library for SDL.
sdl2-mixer[dynamic-load]                  Load plugins with dynamic call.
sdl2-mixer[fluidsynth]                    Support for FluidSynth MIDI/SF2 audio format.
sdl2-mixer[libflac]                       Support for FLAC audio format.
sdl2-mixer[libmodplug]                    Support for MOD audio format.
sdl2-mixer[libvorbis]                     Support for OGG Vorbis audio format.
sdl2-mixer[mpg123]                        Support for MP3 audio format.
sdl2-mixer[nativemidi]                    Support for MIDI audio format on Windows and macOS.
sdl2-mixer[opusfile]                      Support for Opus audio format.
sdl2-net                 2.0.1#9          Networking library for SDL
sdl2-ttf                 2.0.15#5         A library for rendering TrueType fonts with SDL
sdl2pp                   0.16.1#2         C++11 bindings/wrapper for SDL2
tgui[sdl2]                                build the SDL backend
The result may be outdated. Run `git pull` to get the latest results.

If your port is not listed, please open an issue at and/or consider making a pull request:
    https://github.com/Microsoft/vcpkg/issues
  • vcpkg install xxx 安装现有第三方库。
C:\dev\vcpkg>vcpkg.exe install SDL2-mixer:x64-windows-static
Computing installation plan...
The following packages will be built and installed:
    sdl2-mixer[core,nativemidi]:x64-windows-static -> 2.0.4#16
Detecting compiler hash for triplet "x64-windows-static"...
-- Using HTTP(S)_PROXY in environment variables.
Restored 0 packages from C:\Users\wangz\AppData\Local\vcpkg\archives in 222.1 us. Use --debug to see more details.
Installing 1/1 sdl2-mixer:x64-windows-static...
Building sdl2-mixer[core,nativemidi]:x64-windows-static...
-- Downloading https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-2.0.4.zip -> SDL2_mixer-2.0.4.zip...
-- Extracting source C:/dev/vcpkg/downloads/SDL2_mixer-2.0.4.zip
-- Applying patch fix-featurempg123.patch
-- Using source at C:/dev/vcpkg/buildtrees/sdl2-mixer/src/2.0.4-b2dc1eb366.clean
-- Found external ninja('1.10.2').
-- Configuring x64-windows-static
CMake Warning at installed/x64-windows/share/vcpkg-cmake/vcpkg_cmake_configure.cmake:299 (message):
  The following variables are not used in CMakeLists.txt:

      LIBRARY_SUFFIX
      SDL_DYNAMIC_LOAD

  Please recheck them and remove the unnecessary options from the
  `vcpkg_cmake_configure` call.

  If these options should still be passed for whatever reason, please use the
  `MAYBE_UNUSED_VARIABLES` argument.
Call Stack (most recent call first):
  ports/sdl2-mixer/portfile.cmake:44 (vcpkg_cmake_configure)
  scripts/ports.cmake:146 (include)


-- Building x64-windows-static-dbg
-- Building x64-windows-static-rel
-- Fixing pkgconfig file: C:/dev/vcpkg/packages/sdl2-mixer_x64-windows-static/lib/pkgconfig/SDL2_mixer.pc
-- Using cached msys-mingw-w64-i686-pkg-config-0.29.2-3-any.pkg.tar.zst.
-- Using cached msys-mingw-w64-i686-libwinpthread-git-9.0.0.6373.5be8fcd83-1-any.pkg.tar.zst.
-- Using msys root at C:/dev/vcpkg/downloads/tools/msys2/9a1ec3f33446b195
-- Fixing pkgconfig file: C:/dev/vcpkg/packages/sdl2-mixer_x64-windows-static/debug/lib/pkgconfig/SDL2_mixer.pc
-- Installing: C:/dev/vcpkg/packages/sdl2-mixer_x64-windows-static/share/sdl2-mixer/copyright
-- Performing post-build validation
-- Performing post-build validation done
Stored binary cache: C:\Users\wangz\AppData\Local\vcpkg\archives\18\187786e4b64f612fdb9bd6d3a95343d9c4f32740d9470674335a191e65195eef.zip
Elapsed time to handle sdl2-mixer:x64-windows-static: 45.58 s

Total elapsed time: 50.92 s

sdl2-mixer provides CMake targets:
    # this is heuristically generated, and may not be correct
    find_package(sdl2-mixer CONFIG REQUIRED)
    target_link_libraries(main PRIVATE SDL2::SDL2_mixer)

安装命令后面其实可以指定具体的安装库的版本,例如上面安装的就是 SDL2-mixer 在 Windows 平台下的 64 位静态库:vcpkg.exe install SDL2-mixer:x64-windows-static

如果你想查看目前支持的版本参数,可以使用 vcpkg help triplet

C:\dev\vcpkg>vcpkg help triplet
Available architecture triplets
VCPKG built-in triplets:
  arm-uwp
  arm64-windows
  x64-linux
  x64-osx
  x64-uwp
  x64-windows-static
  x64-windows
  x86-windows

VCPKG community triplets:
  arm-android
  arm-ios
  arm-linux
  arm-mingw-dynamic
  arm-mingw-static
  arm-neon-android
  arm-windows-static
  arm-windows
  arm64-android
  arm64-ios
  arm64-linux
  arm64-mingw-dynamic
  arm64-mingw-static
  arm64-osx-dynamic
  arm64-osx
  arm64-uwp
  arm64-windows-static-md
  arm64-windows-static
  armv6-android
  ppc64le-linux
  s390x-linux
  wasm32-emscripten
  x64-android
  x64-freebsd
  x64-ios
  x64-linux-release
  x64-mingw-dynamic
  x64-mingw-static
  x64-openbsd
  x64-osx-dynamic
  x64-osx-release
  x64-windows-release
  x64-windows-static-md
  x86-android
  x86-freebsd
  x86-ios
  x86-mingw-dynamic
  x86-mingw-static
  x86-uwp
  x86-windows-static-md
  x86-windows-static
  x86-windows-v120
  • vcpkg remove xxx 可以移除现有的安装库。
C:\dev\vcpkg>vcpkg remove sqlite3
The following packages will be removed:
    sqlite3:x86-windows
Removing 1/1 sqlite3:x86-windows

3. 使用

vcpkg 安装的第三方库有三种常见的使用方式:

  • 单独使用。
  • 和 Visual Studio 集成。
  • 和 CMake 集成。

3.1 单独使用

单独使用是最简单方式,我们只是单纯的将 vcpkg 当做第三方库的下载工具来使用。每当需要某个第三方库的时候,直接先使用 vcpkg 的 install 命令安装对应的库,然后去根目录的 installed 直接找到编译的库引用即可。例如下面是在 installed 目录下的 x64 位静态库的目录结构:

x64-windows-static

其中 include 就是第三方库的头文件目录,lib 是编译好的 Release 版本库目录,而 debug 则是 Debug 版本库的存储目录。具体如何使用这里就不详细展开了,大家可以去参考常用工程属性简介

3.2 和 Visual Studio 集成

因为 vcpkg 是微软团队主导的,所以显然 vcpkg 对 Visual Studio 有独特的加成。vcpkg 支持对 Visual Studio 的全局集成,用户在写代码的过程中,无需专门引用第三方库,Visual Studio 会检测头文件后自动添加依赖项,整个过程对开发者完全透明。下面我给大家简单的演示一下,为了对比明显,咱们先创建一个简单的 SDL2 普通工程。

普通 SDL2 工程项目

运行 Build,会提示下面的错误:

Build started...
1>------ Build started: Project: ConsoleApplication1, Configuration: Debug x64 ------
1>ConsoleApplication1.cpp
1>C:\Users\wangz\source\repos\ConsoleApplication1\ConsoleApplication1\ConsoleApplication1.cpp(1,10): fatal error C1083: Cannot open include file: 'SDL.h': No such file or directory
1>Done building project "ConsoleApplication1.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

接着咱们尝试将 vcpkg 集成到 Visual Studio,这里要注意,需要使用管理员权限运行命令行然后再安装,否则可能会出现安装失败的情况:

C:\dev\vcpkg>vcpkg integrate install
Applied user-wide integration for this vcpkg root.

All MSBuild C++ projects can now #include any installed libraries.
Linking will be handled automatically.
Installing new libraries will make them instantly available.

CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=C:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake"

安装成功后,命令行中会提示已经安装完成,以后在使用库的时候直接 include 即可自动添加依赖库。为了验证这一点,这里再新建一个项目,方法和前面一样,新建后打开工程属性,可以看到额外的 vcpkg 面板:

vcpkg 属性面板

如果你的工程准备使用静态库,那么面板属性中 Use Static Libraries 需要选为 Yes。据我实测,Visual Studio 中使用的库必须是那些已经安装成功的库,并且需要确定位数(x86/x64)、版本(动态库/静态库) 都需要匹配上才能正常加载。

因为我之前安装的是 x64 位的静态库,所以这里必须配置 Use Static Libraries,并且编译的版本也必须是 x64,否则 Visual Studio 的运行结果和不集成前编译的效果一样。

接着咱们可以在编辑器里引用头文件,如果一切顺利,补全功能会自动提示已安装库的列表:

vs 自动补全 vcpkg 库列表

输入代码后,Visual Studio 就已经不会提示错误了:

vcpkg 自动加载库效果

这里还有个问题需要注意,如果你直接使用 include "SDL.h" 是没有什么用的,那具体应该使用 include "SDL2\SDL.h ,还是其它,需要根据安装第三方库的结构来决定。理论上你可以去 vcpkg 的根目录的 include 目录去查看具体的结构,当然在提示里面选择是最方便的做法。

如果你想移除全局集成,可以使用 vcpkg integrate remove 卸载:

C:\dev\vcpkg>vcpkg integrate remove
User-wide integration was removed

3.3 和 CMake 集成

一般在 Windows 上使用 CMake 需要额外指定工程中依赖的其它第三方库,因为 CMake 默认不配置工具链文件的情况下,无法自动查找的第三方依赖库的位置,如果配置不全或者版本不对,很容易造成最终的编译失败。vcpkg 可以弥补这个潜在的问题,只需要在使用 CMake 的时候配置好编译链的位置:

cmake -B [build directory] -S . "-DCMAKE_TOOLCHAIN_FILE=[path to vcpkg]/scripts/buildsystems/vcpkg.cmake"

这样在 CMake build 的时候,会通过 find_package 自动引用 vcpkg 已安装的库。

4. 问题

在安装的过程中可能会遇见下载过慢的情况,如果你自己有代理的话,可以通过在终端上添加下面的命令减缓这一问题:

set http_proxy=http://127.0.0.1:1080
set https_proxy=http://127.0.0.1:1080

5. 总结

实际上 vcpkg 除了上面的功能之外,还有很多额外的使用方式,具体大家可以查看 官方文档,以后在使用 vcpkg 的时候,我也会将遇见的问题尽量在本篇文章中说明。最后希望大家可以通过使用 vcpkg 减轻第三方库的焦虑😀。