因为某些没法解决的问题,主力开发系统又从 ArcoLinux 变回了 Windows 。失去了 Arch 系优秀的包管理工具和方便好用的 Unix 环境,面对 Windows 下的 CPP 开发,一切都太难了(

用 Windows 摸爬滚打了近三个月,也算把 Windows 下 CPP 的开发方式也大致摸了一遍。

在这要吐个槽,为什么所有在 Windows 下的 CPP 开发工具或者环境,都想在我的电脑上再装一套 Python CMake 还有 Ninja 。

麻了麻了,明天就折腾回 Linux 。

先总结一下,众所周知,在 Windows 上使用第三方库很麻烦,没法做到像 Linux 一样直接使用包管理器进行安装,又因为 Windows 并不支持 POSIX 标准(虽然可以使用 msys 和 mingw 做兼容),还有其他种种不利因素,使得在 Windows 环境下进行跨平台,调用第三方库的情况下, CMake + vcpkg/conan 几乎是唯一选择,如果你还有跨移动端的需求,那么 conan 我认为也应该排除在外。

先从包管理开始谈起吧

包管理

脱离 CSDN 的错误指导

第三方库的大一统

CMake

先来讲讲 CMake 最最原生的方法, CMake 本身为调用第三方库提供了三种方法,分别是 find_package FetchContent ExternalProject

先对三种进行一个简单介绍:

find_package

find_package 是 CMake 引入第三方库最基本的方法,如果你使用 *nix 系统,那么直接使用包管理器安装相应的库,然后在你的 CMakeLists.txt 内添加一行 find_package(SomeLib) 即可,通常来说都是 OK 的,也有一些其他技巧,就用 Qt 来举个例子。

# ...
find_package(Qt5) # 最基本用法

if(NOT Qt5_FOUND) # 如果上面成功会定义此变量
  # do something
endif()

find_package(Qt5 REQUIRE) # 找不到直接报错

find_package(Qt5 MODULE)
find_package(Qt5 NO_MODULE) # 是否在 ${CMAKE_MODULE_PATH} 寻找 FindQt5.cmake 

find_package(Qt5 COMPONENTS Core) # 顺便找上他的组件
# ...

上面都是 *nix 的操作,如果你使用 Windows ,安装了相应的库(指官网上提供的预编译库),你直接调用上面的命令是肯定不行的, CMake 并不知道去哪找,你需要在配置 CMake 的时候指定相应的搜索路径:

cmake . -DQt5_ROOT:PATH=C:\path\to\qt

这是最最基础的方法,在 Windows 下你需要提前下载好预编译库,典型如 Qt , OpenCV 。 其他第三方库的调用方法也通常离不开 find_package 。

FetchContent and ExternalProject

这两种方法我觉得应该放在一起来讲,甚至我觉得应该出个表格来对比,但是我懒。

简单对这两种方法进行一个概括:FetchContent 在配置项目时从网络上下载相应的内容,在编译时一起编译, ExternalProject 在编译时下载第三方库,这意味着你在写你自己的内容之前应该有你需要使用的第三方库的头文件,没错很反人类。

这两种方法都不适用于大项目,如 OpenCV 等等,这种级别的第三方库通常一次编译就需要近两三个小时的时间,不过还好有构建缓存,但是如果你不小心手贱 clean 掉了,那就必须再等三四个小时去编译相关内容。

简单的介绍一下使用方法:

# FetchContent
include(FetchContent)
FetchContent_Declare(
  some_lib
  GIT_REPOSITORY git_to_some_lib
  GIT_TAG v1.0.0
)
FetchContent_MakeAvaliable(some_lib)

# ExternalProject
include(ExternalProject)
ExternalProject_Add(some_lib
  PREFIX ${CMAKE_BINARY_DIR}/extern/some_lib
  GIT_REPOSITORY git_to_some_lib
  GIT_TAG v1.0.0
  # 麻烦的编译指令
  CONFIGURE_COMMAND "cmake ."
  BUILD_COMMAND "make"
  INSTALL_COMMAND "make install"
)

Git submodule + Cmake

该种方法与 FetchContent 类似,同样仅仅适用于小型依赖。

vcpkg

终于讲到了正题,不得不说 vcpkg 真是 Windows 上 Cpp 包管理唯一的神,它不仅进能在 Windows 上使用,同样支持其他系统和交叉编译,不过它的优势仅仅在 Windows 上是优势。

vcpkg 同样需要从源码编译你所需要的的库,可以指定不同的 target 与编译类型(静态库或者动态库)。它的使用方法简单,支持多种编译系统(不过我没见过有其他人用 Meson 之类的),不过目前仍有部分 bug ,而且修复很慢(指3月提出,至今未修复)

具体详见 vcpkg

Conan

Conan 同样是一个包管理器,使用 python 编写,能与各种编译系统结合,与 vcpkg 相比它提供一个预编译的二进制发行中心,但是都是静态库,所以小依赖库用不着提前编译,大一点的依赖库也不用它的编译(因为有各种选项),conan 的依赖管理相比 vcpkg 好了很多,我们可以自行选择版本,也可以用 python 脚本去介入编译过程,配置过程。不过它对交叉编译的支持略弱。

编译系统

在这个方面,其实除了 CMake 外几乎没有可选了,但我也试了试,最让人惊喜的就是 xmake ,感觉以后会火。

xmake

xmake 是我发现的一个新编译系统,使用 lua 脚本控制编译过程与选项,不得不说这是我见过最好的编译系统了,对交叉编译的支持近乎完美,可同时使用 conan 与 vcpkg 的库,同时也有一个自己的蛮大的依赖库,编译速度也说的过去, lua 的通用性和易学度也远超 cmake dsl 。可惜目前来看流行度不高,相关的文档内容也不够充实。

想做一些大一点的东西没有文档支持属实有点累,网络上也没有相关的资料或者可以参考的项目。

番外 craft

craft 一个由 KDE 开发的编译系统 + 包管理工具,不支持 CMake 。 KDE 自己都不用的东西。

最后修改日期: 2021年9月25日

作者

留言

撰写回覆或留言

发布留言必须填写的电子邮件地址不会公开。