从QMake到CMake:CMake为什么在2020年相当不错的故事

2020-09-23 18:21:00

ScreScript是一款适用于Windows(即将在Linux和MacOSX上)使用现代C++/Qt/QML编写的开源Live墙纸和小工具应用程序,从2017年初开始在GitLab上积极开发。

在开发稍微复杂一些的应用程序时,最好的解决方案通常是尝试将它们拆分成更易于管理的部分。例如,如果您希望将应用程序作为单独的可执行文件进行测试,则子目录项目(项目树)是此处唯一的选择。

子目录项目只是一个简单的MyApp.pro,它只包含一个模板和子目录:

我们现在有多个子项目需要在彼此之间共享代码。要告诉编译器在哪里可以找到来自另一个项目的头文件和源文件,我们需要告诉链接器要链接哪个库以及在哪里可以找到编译后的文件。进入qmake的方法是制作仅用于包含文件的大型.pri文件。这类似于c++中的常规#include<;xyz.h>;。这些MyProjectName.pri现在包含在其他MyProjectName.pro中。要解决相对路径问题,您必须将当前绝对路径添加到每行:

在多个操作系统上处理外部依赖项主要包括将平台特定路径的块复制粘贴到.pro文件中。这确实是一项乏味的工作,因为每个操作系统处理路径的方式都略有不同。例如,我们在Linux上没有单独的DEBUG/RELEASE子文件夹。

Qmake的另一个大问题是看似随机的编译器竞争。当您有许多子项目作为其他子项目的库时,它会随机失败,因为库Liba依赖于库libB和libC。但当时libc还没有建成。大多数情况下,简单的第二次重新编译就可以解决这个问题。但这清楚地表明了一些严重的缺陷。这个问题从未真正用libA.desives=libB解决过。也许(相当肯定的)我犯了一些错误,但我和我的同事们从未解决过这个问题。确保构建顺序固定的唯一方法是设置“config+=ordered”,这将终止所有构建并行性。

当QtCompany宣布不再积极支持QBS时,确实令人震惊。我甚至是推动进行第二次社区投票的人之一。对于编写过QML的每个人来说,QBS语法看起来都很好,很熟悉。CMake没有。在与CMake合作了几个月之后,

我可以自信地说,从Qt6开始,使用CMake而不是QBS作为默认构建系统是正确的决定。

CMake(WITH主要有语法缺陷)工作可靠。QBS问题更多的是政治问题,而不是技术问题:

对于许多不喜欢Qt大小(包括代码行和库大小)的程序员来说,这是主要的禁忌之一。另外,很多人讨厌MOC。这是将Qt C++编译成常规C++的预编译器。这是为了编写漂亮的代码,比如emit mySignal();

我们已经有了build2,cmake,meson,scons,它们有很多项目在Qt生态系统之外使用。

还记得我在第1.1段中关于外部依赖的咆哮吗?对我来说,vcpkg是每个C++开发人员的圣杯。使用一个命令安装依赖项!

如果你点击前10个谷歌搜索结果,你会发现CMake真的很难看。这是因为Google向您展示了2008年的旧CMake堆栈溢出答案,并且经常将您重定向到2.8版的旧文档。CMake语法可能相当不错,因为大多数情况下您只需要使用以下命令:

#设置最低要求cmake_MINIMUM_REQUIRED(版本3.16.0)#设置项目名称。这在以后用于可执行文件名称和#非常有用的${PROJECT_NAME}项目(剧本)#一些资源的QT设置和MOC设置(CMAKE_AUTORCC ON)设置(CMAKE_AUTOMOC ON)#这实际上只是synatx糖。这只会使用这些字符串作为数组元素创建变量src#。稍后在add_ecutable set(src main.cpp app.cpp#let跳过此处src/util.cpp src/create.cpp)set(headers app.h src/globalvariable.h#让我们跳过此处src/util.h src/create.h)#大资源(如我们的字体qt5_add_Big_resources(resources resources ces.qrc)#告诉CMake在发布模式下将QML编译成C++以加快速度!If(CMAKE_BUILD_TYPE STREQUAL";Debug";)set(QML qml.qrc)Else()qtQUICH_COMPILER_ADD_RESOURCES(QML qml.qrc)endif()#告诉CMake搜索这些库。因为我们更早地设置了CMAKE_TOOLCHAIN_FILE#,所以我们不再需要手动管理难看的相对路径!Find_package(需要Qt5组件Quick QuickCompiler小部件GUI WebEngine)#外部vcpkg库find_package(需要ZLIB)find_package(需要OpenSSL)find_package(需要libzippp配置)find_package(需要nlohmann_json配置)#CMake有两个主要命令:#add_executable用于创建可执行文件#add_library用于创建库add_executable(${project_name}${src}${headers}${resources}${qml})#用于禁用控制台的自定义属性。Window上的窗口#https://stackoverflow.com/questions/8249028/how-do-i-keep-my-qt-c-program-from-opening-a-console-in-windows SET_PROPERTY(目标${PROJECT_NAME}PROPERTY WIN32_EXECUTABLE TRUE)#告诉链接器搜索这些依赖项。大多数情况下,vcpkg会#告诉您图书馆的名称。如果没有,请查看#the dll/lib/so/dynlib#的vcpkg/install路径。如果您需要在项目结构中有依赖项,只需#将项目(MyLib)添加到target_link_library。没有嵌入的路径,#没有额外的东西,它简单地工作!Target_link_library(${PROJECT_NAME}私有Qt5::Quick Qt5::GUI Qt5::widgets Qt5::core Qt5::WebEngine nlohmann_json::nlohmann_json libzippp::libzippp ScreenPlaySDK QTBreakpadplugin)#告诉CMake在更改后将此文件复制到您的构建目录#${CMAKE_BINARY_DIR}是您的构建目录!FILE(MAKE_DIRECTORY${CMAKE_BINARY_DIR}/bin/Assets/Fonts)CONFIGURE_FILE(ASSES/Fonts/NotoSansCJKkr-Regular.otf${CMAKE_BINARY_DIR}/bin/Assets/Fonts COPYONLY)。

CMake只为您选择的构建系统生成指令。在与更喜欢VisualStudio而不是QtCreator的人一起工作时,这可能是一个很大的优势。当使用CMake时,可以(应该)选择忍者作为默认的构建系统。用CMake+忍者编译项目很有趣。忍者和CMake附带了工具类别中的Qt维护。随着[13/424]的进展,迭代更改看起来是令人难以置信的快速和干净的。

它是如此之快,以至于与Godots Scons合作让我非常想要将Godot转换为CMake。

在C++中管理依赖项是单调乏味的,许多项目甚至将DLL与它们的git存储库一起提供。这很糟糕,因为它夸大了git回购大小(我们现在忽略git-lfs)。缺点是vcpkg只支持包的一个全局版本(您需要手动安装不同版本的vcpkg,但这更像是黑客攻击,而且很少需要)。这是他们路线图上的一项功能。在剧本中,我们只需使用install_ependency_windows.bat或install_ependency_linux_mac.sh来克隆vcpkg、构建vcpkg并安装我们所有的依赖项,在使用QtCreator时,我们必须将CMAKE_TOOLCHAIN_FILE设置为vcpkg的相对路径。我们还必须告诉vcpkg我们使用的是什么操作系统和ARCH。

#QtCreator安装程序。Extras->;Tools->;Kits->;->;C进行配置->;追加此内容:CMAKE_TOOLCHAIN_FILE:STRING=%{CurrentProject:Path}/Common/vcpkg/scripts/buildsystems/vcpkg.CMake vcpkg_target_triplet:STRING=x64-WINDOWS。

需要安装另一个库吗?只需再次调用vcpkg install myLibToInstall就可以了!

随波逐流有其优势,但也有代价。构建系统,比如QBS,有很大的潜力被扔到公交车下面。使用什么取决于开发人员,这就是为什么我的项目从现在开始将使用CMake。

下一篇博客文章将讨论如何在“Hello World”之外设置Qt项目。敬请关注!