几天前,在 CppCon C++ 大会期间,微软发布了 Vcpkg。它可以帮助您在 Windows 上为 Microsoft Visual Studio 获取和从源代码构建 C 和 C++ 开源库。这是一个很好的举措,得到了社区的广泛认可,并且已经有许多用户通过提交拉取请求贡献了新的“端口”(vcpkg 使用此术语来称呼配方或公式)。

Vcpkg 基于 CMake 脚本执行所有获取和构建任务,并委托给名为“vcpkg.exe”的可执行文件来调用 cmake 和其他一些功能。

Conan 已经实现了 system_requirements() 来处理系统包(如 apt-get 或 brew)的安装,这些包在需要系统依赖项的 conan 配方中使用。因此,我们开始分析 vcpkg 和 conan 之间是否存在任何类似的协同作用,以及 conan 是否可以避免为那些已经在 vcpkg 中存在的库创建或重写包。

从 conan 使用 vcpkg 库

“端口 conan 配方”名称类似于“portname/libversion@lasote/vcpkg”,例如 boost/1.61.0@lasote/vcpkg

您可以在 conan.io 中搜索 vcpkg 包

像使用常规 conan 配方一样使用它们,在 conanfile.txtconanfile.py 中使用。 查看入门指南

这是一个使用 boost 库的示例,在一个文件夹中创建以下源代码文件

Conanfile.txt

[requires]
boost/1.61.0@lasote/vcpkg

[generators]
cmake

[imports]
bin, *.dll -> ./bin
lib, *.dylib* -> ./bin

regex.cpp

#include <boost/regex.hpp>
#include <iostream>
#include <string>

int main(){
    std::string line = "Subject: Regex working!";
    boost::regex pat( "^Subject: (Re: |Aw: )*(.*)" );

    boost::smatch matches;
    if (boost::regex_match(line, matches, pat))
        std::cout << matches[2] << std::endl;
}

CMakeLists.txt

project(MyHello)
cmake_minimum_required(VERSION 3.0)

include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)

conan_basic_setup()
add_executable(regex regex.cpp)
target_link_libraries(regex ${CONAN_LIBS})

在您的项目中创建一个新的构建文件夹并运行 conan install。它将从 conan.io 获取 boost 配方和预构建的二进制包。如果您的设置没有二进制包,它将调用 conan 配方中嵌入的 vcpkg cmake 脚本并生成一个新的 conan 包二进制文件

$ mkdir build && cd build
$ conan install .. --build missing

这假设您的默认设置是 Visual Studio 14,如果您有其他版本,可以在安装参数中指定它

$ conan install .. --build missing -s compiler="Visual Studio" -s compiler.version=12

并使用适合您 Visual Studio 版本的生成器调用 cmake

$ cmake ..  -G "Visual Studio 14 Win64"
$ cmake --build . --config Release

转到“bin”文件夹并运行可执行文件

$ cd bin
$ regex.exe

我们是如何做到的?自动为 vcpkg 库创建 conan 包

“lasote” Vckpg 分支 中有一个“conanizer”文件夹。它包含一个 run.py python 脚本,该脚本读取所有可用的端口。对于每个端口,它都会从基本模板生成一个新的 conanfile.py conan 包配方,该配方将调用 CMake 脚本并为不同的配置(VS10、12、14、调试和发布版本)构建包二进制文件。

Vcpkg CMake 脚本只需要两个参数

  • 端口:要编译的端口名称
  • 目标三元组:基本上它定义了体系结构,在 conan 中是一个设置,因此我们可以从 conan arch 设置生成三元组名称。

Vcpkg 打包库的方式与 conan(标准)相同,因此在“package”方法中,我们只需复制文件夹即可

  • bin => dll
  • lib => 要链接的库
  • include => 库头文件
  • tools => 可执行文件

最后,我们创建了一个 appveyor.yml 来帮助每次我们推送我们的分支或进行任何标记的发布时自动生成并上传到 conan.io 所有包配方和预构建的二进制文件。

Conan 的优势

对于 vcpkg 包,使用 conan 比仅使用 vpckg 有一些优势

  • 库版本控制Vcpkg 每个端口/vcpkg 实例仅保留一个版本,如果发布了库的新版本,它将覆盖您以前的依赖项。对于 C/C++ 项目来说,这是一个大问题,因为依赖项通常应该保持稳定。用户很少希望他们的 Boost 或 OpenSSL 版本自动替换为最新版本。我们读取声明库版本的 CONTROL 文件,并使用该版本为不同库版本生成不同的 conan 配方,例如 boost/1.61.0@lasote/vcpkg

待办事项conanizer 尚未正确管理端口的递归依赖项。我们可以通过为另一个“端口”包定义 conan 需求来改进它。这样,我们可以处理库 A 依赖于 B(A -> B)并且 B 版本在 vcpkg 存储库中更新为 B’ 的情况。然后,conan.io 中将有两个二进制包可用,(A -> B)和(A -> B’)。用户可以通过请求 A 正常使用(A -> B)版本,甚至可以通过使用旧的二进制包在他们的项目中将 B’ 覆盖为 B。

  • 不同的 Visual Studio 版本:Vcpkg 目前仅支持 Visual Studio 14 编译。我们进行了一些调整,可以使用任何其他 Visual Studio 版本编译任何端口(只要库源代码可以使用以前的 Visual Studio 版本进行编译,如果它们仅使用 VS 2015 提供的最新 C++ 功能,则可能无法编译)。
  • 不同的调试/发布包:我们将构建类型调试和发布分离到两个不同的二进制包中,因此您可以使用设置“build_type”仅安装所需的二进制文件。
  • 将端口与常规 conan 包结合使用:将这些端口包用作普通的 conan 包,链接到其他包等。
  • 自动链接:Conan 检测并声明构建的库,因此您可以例如使用 CMake 生成器并自动链接 ${CONAN_LIBS}。
  • 二进制缓存:Conan 可以本地或在任何 conan 服务器上缓存构建的包。我们知道编译大型 C/C++ 项目的成本有多高,因此您无需每次更改环境时都重新构建依赖项。分布式服务器架构(如 git 远程)提供了多种可能性,例如带有可选读取访问权限的私有内部服务器到公共存储库等。
  • 使用您自己的内部 conan 服务器,使用 MIT 许可证,易于运行和维护,以托管包配方和二进制文件并与您的开发团队共享。
  • 从源代码构建:与 Vcpkg 一样,如果您不想使用 conan.io 的预构建二进制文件,您可以继续从源代码构建包。使用 –build 选项调用 conan install。它将调用库 CMake 端口脚本以重新构建库。
  • 使用任何 conan 生成器:使用任何 conan 生成器来重用 vcpkg 端口,CMake、CLion、Xcode、Autotools、YCM、Premake…
  • 许多其他 conan 优势:Conan 提供了许多其他高级包管理器功能,如冲突解决、依赖项覆盖等。