C++ 好用的包管理工具--vcpkg

2023-11-03

背景

Windows 下开发 C/C++ 程序,少不了编译开源的第三方库,使用这些库开发极大的方便了程序员,使得我们不必重复造轮子。

由于开源库绝大部分都来源于 Linux 系统、将其移植到 Windows 的 VC 开发环境下编译比较复杂和麻烦;而且我们还需要考虑编译出哪种类型的开源库程序,比如:Debug/Release、动态库/静态库、MD/MT、32位/64位,管理起来也很麻烦。

Vcpkg

概述

Vcpkg 是微软社区开发的一个跨平台的 C++ 包管理工具。它旨在解决 C++ 开发过程中依赖管理的痛点,它支持多个操作系统,包括:Windows、Linux和 macOS,使开发者能够更加便捷地安装、管理和更新 C++ 项目所需的第三方库。

Vcpkg 优势

相对于编译开源库的传统方法,使用 Vcpkg 的优点如下:

  • 跨平台支持:Vcpkg 支持 Windows、Linux 和 macOS 等多个主流操作系统,使得开发者能够在不同的环境下进行一致的依赖管理。
  • 自动解决依赖:Vcpkg 能够自动处理库之间的依赖关系,简化了依赖管理的复杂性,并且能够提供一致的库版本。
  • 简单易用:Vcpkg 的命令行接口使得安装、更新和卸载库都变得简单快捷,节省了开发者的时间。
  • 集成 Visual Studio:不需要设置库文件、头文件的所在目录,自动集成。

Vckpg 下载和安装

概述

Vcpkg 大量使用 psl 脚本,所以官方强烈推荐使用 PowerShell 而不是 CMD 命令行来执行各种操作,建议使用 7 以上版本。

安装 Vcpkg

创建安装目录

先创建一个安装目录,如:C:\vcpkg,然后打开该目录:

cd C:/vcpkg

clone 官方 git 仓库

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

编译 vcpkg

切换目录到 vcpkg 仓库文件夹:

cd vcpkg

执行引导脚本:

./bootstrap-vcpkg.bat

成功执行完成后,在目录中可以看到文件 vcpkg.exe:

添加环境变量

将 vcpkg.exe 的路径添加到环境变量,即可在任意位置执行 vcpkg 命令:

更新 Vcpkg

概述

vcpkg 包管理器在 GitHub 上定期更新。 若要将 vcpkg 的克隆更新到最新版本,执行 git pull 命令即可。

更新下载完成后,再次运行引导程序会重新生成 vcpkg 程序,但保留已安装的库。

git pull

进入 vcpkg目录,然后执行 git pull 命令:

git pull

再次执行引导脚本:

./bootstrap-vcpkg.bat

Vcpkg 使用

安装一个开源库

这里以安装 spdlog 库为例进行演示。安装第三方开源库的命令为 vcpkg install pkgname。

默认安装

如果不指定安装的架构,vcpkg 默认把开源库编译成 x86 的 Windows 版本的库:

vcpkg install spdlog

执行结果如下:

编译完成后可以在目录中看到库的位置:

指定位数安装

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

vcpkg install spdlog:x64-windows

命令执行完成后可以在目录中查看新编译的库:

同样,若要编译安装静态库,只需加上 -static 即可:

vcpkg install spdlog:x64-windows-static

删除一个开源库

要删除一个已安装的开源库的命令为:vcpkg remove pkgname:

vcpkg remove spdlog:x64-windows

执行库删除命令后,其源码包和解压缩的源码并没有删除,若再次安装直接进行编译步骤:

更新一个开源库

列出需要更新的库

可以使用 update 或者 upgrade 命令列出需要更新的库:

vcpkg update

也可以使用 upgrade 命令:

vcpkg upgrade

更新过时的库

不带参数使用 upgrade 命令时将一次升级所有过时的库。但默认情况下 upgrade 命令只列出要升级的库,但不升级它们。

要有效地升级它们,应该使用 -no-dry-run 选项:

vcpkg upgrade --no-dry-run 

更新指定的库

upgrade 可以指定一个或多个库名称作为参数:

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

开源库查询

查询一个开源库

使用 search 命令可以查询 vcpkg 中是否包括指定的库:

vcpkg search spdlog 

查询已安装的开源库

使用 list 命令可以查询当前已经安装的开源库:

vcpkg list

导出一个开源库

通常在项目中使用第三方开源库时会把其拷贝到项目文件夹中使用,使用 export 命令可以导出指定的开源库:

vcpkg export spdlog:x64-windows --zip

导出的压缩包位于根目录中:

如下图所示,导出的压缩包中包含了引用库需要的 include、lib 等目录:

或者直接从根目录的 packages 中拷贝对应的库文件夹也可以。

Vckpg 集成

概述

通常情况下要使用第三方库我们需要设置 include、lib 等目录。

Vcpkg 提供了一套机制,可以全自动的适配目录,而开发者不需要关心已安装的库的目录在哪里。

Vckpg 集成到 Visual Studio

全局集成

全局集成即在任意的 Visual Studio 项目中可直接使用已安装的第三方库,使用 integrate install 命令可集成到全局:

vcpkg integrate install

如下示例:集成后可在任意项目中直接使用 spdlog 库:

移除全局集成

若要移除全局集成,执行integrate remove 命令即可:

vcpkg integrate remove

移除后项目引用的第三库即已不可用:

集成到项目

Visual Studio 也支持把 Vcpkg 集成到指定的某个项目中,是利用 Visual Studio 中的 nuget 插件来实现。

  1. 生成配置文件

执行命令 integrate project 生成 nuget 配置文件:

vcpkg integrate project

  1. 打开程序包管理器控制台

通过菜单 “工具-NuGet 包管理器-程序包管理器控制台” 打开控制台界面:

复制在上一步界面中提示的命令,粘贴到控制台界面中,然后执行:

现在 demo 项目中已经可以直接使用 Vcpkg 中安装的第三方库,如下图所示:

集成到 CMake

概述

在 Vcpkg 中安装每个库的时候都会有提示怎么在 CMake 中引用,以 spdlog 库安装为例:

CMakeList.text 示例

使用 CLion 新建一个项目,在 CMakeList.text 中添加以下内容:

cmake_minimum_required(VERSION 3.25)

set(CMAKE_CXX_STANDARD 11)

set(CMAKE_TOOLCHAIN_FILE "C:/vcpkg/vcpkg/scripts/buildsystems/vcpkg.cmake")

if(DEFINED ENV{VCPKG_DEFAULT_TRIPLET} AND NOT DEFINED VCPKG_TARGET_TRIPLET)
    set(VCPKG_TARGET_TRIPLET "$ENV{VCPKG_DEFAULT_TRIPLET}" CACHE STRING "")
endif()

project(spdlogTest)

add_executable(spdlogTest main.cpp)

find_package(spdlog CONFIG REQUIRED)
target_link_libraries(spdlogTest PRIVATE spdlog::spdlog_header_only)

库引用示例

此时在项目中即可使用 spdlog 库了,如下图所示:

微信搜索“编程猿来如此”关注公众号获取更多内容。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 好用的包管理工具--vcpkg 的相关文章

  • C++ 中本地类中的静态成员变量?

    我知道我们不能宣布static本地类中的成员变量 但其原因尚不清楚 那么请问有人可以解释一下吗 另外 为什么我们不能访问非static函数内部定义的变量 内部已经定义了局部类 直接在局部类成员函数中 在下面给出的代码中 int main i
  • 如何为 C 分配的 numpy 数组注册析构函数?

    我想在 C C 中为 numpy 数组分配数字 并将它们作为 numpy 数组传递给 python 我可以做的PyArray SimpleNewFromData http docs scipy org doc numpy reference
  • 单元测试一起运行时失败,单独运行时通过

    所以我的单元测试遇到了一些问题 我不能只是将它们复制并粘贴到这里 但我会尽力而为 问题似乎是 如果我一项一项地运行测试 一切都会按预期进行 但如果我告诉它一起运行测试 则 1 5 将通过 TestMethod public void Obj
  • 如何从 .resx 文件条目获取注释

    资源文件中的字符串有名称 值和注释 The ResXResourceReader类让我可以访问名称和值 有办法看评论吗 你应该能够得到Comment via ResXDataNode class http msdn microsoft co
  • 如何访问另一个窗体上的ListView控件

    当单击与 ListView 所在表单不同的表单中的按钮时 我试图填充 ListView 我在 Form1 中创建了一个方法以在 Form2 中使用 并将参数传递给 Form1 中的方法 然后填充 ListView 当我调试时 我得到了传递的
  • 生成(非常)大的非重复整数序列而不进行预洗牌

    背景 我编写了一个简单的媒体客户端 服务器 我想生成一个不明显的时间值 随从客户端到服务器的每个命令一起发送 时间戳中将包含相当多的数据 纳秒分辨率 即使它不是真正准确 因为现代操作系统中计时器采样的限制 等 我想做的 在 Linux 上
  • 用于检查项目文件中的项目变量和引用路径的 api

    我正在研究一个 net application VS2010 与 x 没有 解和变量号这些解决方案中的项目数量 我需要检查项目属性 特定于一定数量的项目 是否同质 并且检查 验证构建期间的参考路径 有没有一个API是这样的吗 如果没有 我该
  • 单击 form2 上的按钮触发 form 1 中的方法

    我对 Windows 窗体很陌生 我想知道是否可以通过单击表单 2 中的按钮来触发表单 1 中的方法 我的表格 1 有一个组合框 我的 Form 2 有一个 保存 按钮 我想要实现的是 当用户单击表单 2 中的 保存 时 我需要检查表单 1
  • C++:.bmp 到文件中的字节数组

    是的 我已经解决了与此相关的其他问题 但我发现它们没有太大帮助 他们提供了一些帮助 但我仍然有点困惑 所以这是我需要做的 我们有一个 132x65 的屏幕 我有一个 132x65 的 bmp 我想遍历 bmp 并将其分成小的 1x8 列以获
  • 上下文敏感与歧义

    我对上下文敏感性和歧义如何相互影响感到困惑 我认为正确的是 歧义 歧义语法会导致使用左推导或右推导构建多个解析树 所有可能的语法都是二义性的语言是二义性语言 例如 C 是一种不明确的语言 因为 x y 总是可以表示两个不同的事物 如下所述
  • 如何在 Blackberry Cascades 中显示具有特定号码的电话板

    我正在使用带有 C QT 和 QML 的 Blackberry Cascades 10 Beta 3 SDK 以及 Blackberry 10 Dev Alpha Simulator 和 QNX Momentics IDE 并且我正在尝试实
  • 如何使用 Mongodb C# 驱动程序连接多个集合

    我需要将 3 个集合与多个集合合并在一起 lookup我在 C 驱动程序中尝试过 它允许我 lookup用户采集但无法执行秒 lookup用于设置集合 有人可以帮忙吗 db Transactions aggregate lookup fro
  • 有人可以提供一个使用 Amazon Web Services 的 itemsearch 的 C# 示例吗

    我正在尝试使用 Amazon Web Services 查询艺术家和标题信息并接收回专辑封面 使用 C 我找不到任何与此接近的示例 所有在线示例都已过时 并且不适用于 AWS 的较新版本 有一个开源项目CodePlex http www c
  • 如何从main方法调用业务对象类?

    我已将代码分为业务对象 访问层 如下所示 void Main Business object public class ExpenseBO public void MakeExpense ExpensePayload payload var
  • (de)从 CSV 序列化为对象(或者最好是类型对象的列表)

    我是一名 C 程序员 试图学习 C 似乎有一些内置的对象序列化 但我在这里有点不知所措 我被要求将测试数据从 CSV 文件加载到对象集合中 CSV 比 xml 更受青睐 因为它更简单且更易于人类阅读 我们正在创建测试数据来运行单元测试 该集
  • 为什么在setsid()之前fork()

    Why fork before setsid 守护进程 基本上 如果我想将一个进程与其控制终端分离并使其成为进程组领导者 我使用setsid 之前没有分叉就这样做是行不通的 Why 首先 setsid 将使您的进程成为进程组的领导者 但它也
  • Process.Start() 方法在什么情况下返回 false?

    From MSDN https msdn microsoft com en us library e8zac0ca v vs 110 aspx 返回值 true 表示有新的进程资源 开始了 如果由 FileName 成员指定的进程资源 St
  • 防止在工厂方法之外实例化对象

    假设我有一个带有工厂方法的类 class A public static A newA Some code logging return new A 是否可以使用 a 来阻止此类对象的实例化new 那么工厂方法是创建对象实例的唯一方法吗 当
  • 如何使用 Word Automation 获取页面范围

    如何使用办公自动化找到 Microsoft Word 中第 n 页的范围 似乎没有 getPageRange n 函数 并且不清楚它们是如何划分的 这就是您从 VBA 执行此操作的方法 转换为 Matlab COM 调用应该相当简单 Pub
  • 在客户端系统中安装后桌面应用程序无法打开

    我目前正在使用 Visual Studio 2017 和 4 6 1 net 框架 我为桌面应用程序创建了安装文件 安装程序在我的系统中完美安装并运行 问题是安装程序在其他计算机上成功安装 但应用程序无法打开 edit 在客户端系统中下载了

随机推荐

  • 深入解析C/C++的优缺点以及就业方向

    众所周知C C Java Python都是主流的后端开发语言 并且不同的语言 具备不同的优缺点以及就业方向 解析来小编带你一起看看C C 的优缺点以及就业方向 深入解析C C 的优缺点以及就业方向 C语言是很多语言的鼻祖 所以学会C语言 非
  • Welcome to Level 3 (不容易啊...记下啦^_@)

    Welcome to Level 3 Hey clin003 Congratulations Don t forget to check your Mod X ranking and access the level 3 forum to
  • 结合入栈出栈浅谈前序遍历,中序遍历,后序遍历

    二叉树深度遍历 讨巧应付面试 以前其实也懂什么叫二叉树的前中后序遍历 反正面试的时候 给我一个二叉树 我是知道怎么写出他们的答案的 例如如下二叉树 前序遍历 A B D E C F G 中序遍历 D B E A F C G 后序遍历 D E
  • Infinite Fraction Path【HDU-6223】【BFS+剪枝】

    题目链接 训练赛的时候 想到的做法是倍增维护 因为每个点的后继是唯一的 然后又因为不会桶排 所以的复杂度是一定会TLE的 难受 听说桶排还是会被卡 大雾 然后下来补题的时候听了队友的意见 其实比赛的时候就应该多听听 也许就能想到这个bfs了
  • 某返利网站admin目录index.php文件混淆加密算法分析

    恢复内容开始 文件已经加密 可以在此下载 index php 文件内容打开大概如此 简单字符替换之后 发现字符串用base64 decode仍无法解码 找到一个解码网站 找源码 解码后的文件如下 下载地址 尾部仍然有大量未知编码内容 简单修
  • IP协议的服务类型(翻译RFC 1349)

    目录 1 简介 2 目标和理念 3 服务八位字节类型规范 4 TOS字段的规范 5 Internet协议中TOS字段的使用 5 1 Internet控制消息协议 ICMP 5 2传输协议 5 3应用协议 6 ICMP和TOS字段 6 1无法
  • 圆投影匹配算法描述及实现

    解决模板图和基准图之间存在任意角度旋转的景象匹配问题的关键是找到一个旋转不变量 圆投影匹配算法就是利用 圆 的各向同性和投影特征提出来的 传统的图像匹配算法 如归一化交叉互相关算法 主要利用像素点与像素点之间的相关性计算匹配图像与模板之间的
  • 数据结构day4

    https note youdao com s SwyFfOgRhttps note youdao com s SwyFfOgR 学生管理系统 头文件 ifndef STULIST H define STULIST H include
  • Qt布局的使用

    1 控件的sizePolicy设置了Fixed 再一点击设置布局 控件的大小又自动调整了 解决方法 设置布局后 再手动调整控件大小 2 在要布局的部件上 右键 gt Lay out 如果该部件不支持布局 则右键菜单中不会出现 Lay out
  • Hadoop学习——MapReduce的job机制和job链介绍

    前边写了MapReduce的介绍 以及四大组件 序列化机制和排序 这一篇记录一下MapReduce相关的job机制 对于在代码里 我们总要有一个Driver 比如下边 public static void main String args
  • ORA-01075,ORA-09925 Read-only file system问题一例

    OEL 5 7 ORACLE RAC 11 2 0 2 在运行过程中系统监控台出现journal commit I O error的信息 SQL gt oradebug Message from syslogd at Fri Oct 14
  • java 远程接口_java中如何正确的使用远程接口

    服务器必须包含一个扩展了UnicastRemoteObject的类 并实现远程接口 这个类也可以含有附加的方法 但客户只能使用远程接口中的方法 这是显然的 因为客户得到的只是指向接口的一个句柄 而非实现它的那个类 必须为远程对象明确定义构建
  • JVM 内存模型

    内存划分 java虚拟机按照运行时内存使用区域划分如图 区域 是否线程共享 是否会内存溢出 程序计数器 否 不会 java虚拟机栈 否 会 本地方法栈 否 会 堆 是 会 方法区 是 会 一 程序计数器 Program Counter Re
  • Qt中的 connect 函数

    1 connect 函数实现的是信号与槽的关联 注意 只有QO bject类及其派生的类才能使用信号和槽的机制 2 函数原型 static QMetaObject Connection connect const QObject sende
  • Qt中信号槽的连接方式

    Qt AutoConnection 如果信号发送者和接收者在同一线程 Qt DirectConnection被使用 否则Qt QueuedConnection被使用 Qt DirectConnection 信号发送 信号槽立刻执行 Qt Q
  • scheduler Unhealthy Get “http://127.0.0.1:10251/healthz“: dial tcp 127.0.0.1:10251: con

    解决方法 cd etc kubernetes manifest 然后将你的scheduler以及controll manager yaml中把port 0注释掉 containers command kube scheduler authe
  • gitlab如何创建用户并登录

    为了大家后期能方便创建用户和使用gitlab 先给大家设置为中文 设置为中文后保存然后刷新页面即可设置为中文 接下来教大家怎么创建git用户并进行登录 创建完用户后需要配置一次密码 配置完密码后退出用户测试进行新用户登录 这里用刚创建的新用
  • SpringBoot项目jar、war包启动解析

    一 jar包和war包的区别 1 1 war包 war包是Java Web应用程序的一种打包方式符合Servlet标准 它是Web Archive的缩写 主要用于存储Web应用程序相关的文件 包括Java类文件 JSP HTML CSS J
  • 动手实现Linux内核编译与安装

    Linux内核是一个用C语言写成的 符合POSIX标准的类Unix操作系统 内核是操作系统中最基本的一部分 提供了众多应用程序访问计算机硬件的机制 Linux内核的一大特点就是采用了整体式结构 有很多过程组成 每个过程都可以独立编译 其模块
  • C++ 好用的包管理工具--vcpkg

    背景 Windows 下开发 C C 程序 少不了编译开源的第三方库 使用这些库开发极大的方便了程序员 使得我们不必重复造轮子 由于开源库绝大部分都来源于 Linux 系统 将其移植到 Windows 的 VC 开发环境下编译比较复杂和麻烦