CMake 快速入门 您所在的位置:网站首页 qt构建设置中添加脚本 CMake 快速入门

CMake 快速入门

2024-04-26 08:27| 来源: 网络整理| 查看: 265

CMake 快速入门

CMake 是一组允许构建、测试及打包应用程序的工具。就像 Qt,它可用于所有主流开发平台。它还被各种 IDE 所支持,包括 Qt Creator .

此章节将展示在 CMake 工程中,使用 Qt 的最基本方式。首先,创建基本控制台应用程序。然后,将工程扩展成 GUI 应用程序使用 Qt Widgets .

If you want to know how to build an existing CMake project with Qt, see the documentation on how to build projects with CMake on the command line .

构建 C++ 控制台应用程序

A CMake 工程由以 CMake 语言编写的文件定义。main 文件称为 CMakeLists.txt ,通常放在实际程序源代码的相同目录下。

这里是典型 CMakeLists.txt 文件使用 Qt 以 C++ 编写的控制台应用程序:

cmake_minimum_required(VERSION 3.16) project(helloworld VERSION 1.0.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(Qt6 REQUIRED COMPONENTS Core) qt_standard_project_setup() add_executable(helloworld main.cpp ) target_link_libraries(helloworld PRIVATE Qt6::Core)

让我们浏览一下内容。

cmake_minimum_required(VERSION 3.16)

cmake_minimum_required() 指定应用程序要求的最低 CMake 版本。Qt 本身要求 CMake 至少 3.16 版。若使用的是静态构建的 Qt - 默认在 Qt for iOS and Qt for WebAssembly - 需要 CMake 3.21.1 或更高版本。

project(helloworld VERSION 1.0.0 LANGUAGES CXX)

project() 设置工程名称和默认工程版本。 LANGUAGES 自变量告诉 CMake 程序是以 C++ 编写的。

set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON)

Qt 6 要求编译器支持 C++ 第 2017 或更高版本。实施这是通过设置 CMAKE_CXX_STANDARD , CMAKE_CXX_STANDARD_REQUIRED 变量将使 CMake 打印错误,若编译器太旧。

find_package(Qt6 REQUIRED COMPONENTS Core)

这告诉 CMake 去查找 Qt 6,并导入 核心 模块。继续没有意义若 CMake 无法定位模块,因此,设置 REQUIRED 标志以使 CMake 中止 (在这种情况下)。

若成功,模块将设置一些 CMake 文档化变量在 模块变量 。此外,它还导入 Qt6::Core 目标 (使用于下文)。

For find_package 要取得成功, CMake 必须找到 Qt 安装。有不同方式可以告诉 CMake 关于 Qt,但最常见且推荐的方式是设置 CMake 缓存变量 CMAKE_PREFIX_PATH 以包括 Qt 6 安装前缀。注意 Qt Creator 会透明地处理这种情况。

qt_standard_project_setup()

qt_standard_project_setup 命令设置典型 Qt 应用程序的工程范围默认值。

除其它事情外,此命令设置 CMAKE_AUTOMOC 变量到 ON ,指导 CMake 自动设置规则,以便 Qt 的 MOC (元对象编译器) 被透明调用当要求时。

见 qt_standard_project_setup 参考了解细节。

add_executable(helloworld main.cpp )

add_executable() 告诉 CMake 想要构建的可执行文件 (因此不是库) 称为 helloworld 作为目标。应构建目标从 C++ 源文件 main.cpp .

注意,通常不会在此列出头文件。这异于 qmake ,需要明确列出头文件,以便处理它们通过 MOC (元对象编译器) .

对于不那么琐碎的工程,可能想要调用 qt_add_executable() 取而代之。它是包裹器围绕内置 add_executable() 命令,提供额外逻辑以自动处理像静态 Qt 构建中的 Qt 插件链接、特定平台的库名称定制、等。

For creating libraries, see qt_add_library .

target_link_libraries(helloworld PRIVATE Qt6::Core)

最后, target_link_libraries 告诉 CMake helloworld 可执行文件利用 Qt Core 通过引用 Qt6::Core 目标,导入通过 find_package() 调用 (见上文)。这不仅将正确自变量添加到链接器,且还确保将正确包括目录、编译器定义传递给 C++ 编译器。 PRIVATE 关键字对于可执行目标不是严格必要的,但指定它是良好实践。若 helloworld 是库而不是可执行文件,那么 PRIVATE or PUBLIC 应该指定 ( PUBLIC 若库提到的任何东西来自 Qt6::Core 在其头中, PRIVATE 否则)。

构建 C++ GUI 应用程序

在 上一章节 展示简单控制台应用程序的 CMakeLists.txt 文件。现在将扩展它以创建 GUI 应用程序使用 Qt Widgets 模块。

这是完整工程文件:

cmake_minimum_required(VERSION 3.16) project(helloworld VERSION 1.0.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(Qt6 REQUIRED COMPONENTS Widgets) qt_standard_project_setup() add_executable(helloworld mainwindow.ui mainwindow.cpp main.cpp ) target_link_libraries(helloworld PRIVATE Qt6::Widgets) set_target_properties(helloworld PROPERTIES WIN32_EXECUTABLE ON MACOSX_BUNDLE ON )

让我们回顾一下所做的改变。

find_package(Qt6 REQUIRED COMPONENTS Widgets)

在 find_package 调用,我们替换 核心 with Widgets 。这会定位 Qt6Widgets 模块和提供 Qt6::Widgets 目标,我们稍后链接它。

注意,应用程序仍会链接 Qt6::Core ,因为 Qt6::Widgets 从属它。

qt_standard_project_setup()

除了 CMAKE_AUTOMOC , qt_standard_project_setup 设置 CMAKE_AUTOUIC 变量到 ON 。这会自动创建规则以援引 Qt 的 uic (用户界面编译器) on .ui 源文件。

add_executable(helloworld mainwindow.ui mainwindow.cpp main.cpp )

我们添加 Qt Designer 文件 ( mainwindow.ui ) 及其相应 C++ 源文件 ( mainwindow.cpp ) 到应用程序目标的源。

target_link_libraries(helloworld PRIVATE Qt6::Widgets)

在 target_link_libraries 命令,我们链接到 Qt6::Widgets 而不是 Qt6::Core .

set_target_properties(helloworld PROPERTIES WIN32_EXECUTABLE ON MACOSX_BUNDLE ON )

最后,设置应用程序目标特性,效果如下:

阻止 Windows 创建控制台窗口。 在 macOS 创建应用程序捆绑。

见 CMake 文档编制 了解有关这些目标特性的更多信息。

结构化工程

包含多个目标的工程将受益于清晰的工程文件结构。我们将使用 CMake 的 子目录特征 .

由于我们计划采用更多目标扩展工程,所以将应用程序源文件移到子目录并创建新的 CMakeLists.txt 在那里。

├── CMakeLists.txt └── src └── app ├── CMakeLists.txt ├── main.cpp ├── mainwindow.cpp ├── mainwindow.h └── mainwindow.ui

顶层 CMakeLists.txt 包含整体工程设置, find_package and add_subdirectory 调用:

cmake_minimum_required(VERSION 3.16) project(helloworld VERSION 1.0.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(Qt6 REQUIRED COMPONENTS Widgets) qt_standard_project_setup() add_subdirectory(src/app)

在此文件中设置的变量,在子目录工程文件中可见。

应用程序的工程文件 src/app/CMakeLists.txt 包含可执行目标:

add_executable(helloworld mainwindow.ui mainwindow.cpp main.cpp ) target_link_libraries(helloworld PRIVATE Qt6::Widgets) set_target_properties(helloworld PROPERTIES WIN32_EXECUTABLE ON MACOSX_BUNDLE ON )

这样的结构使之易于向工程添加更多目标,譬如:库或单元测试。

构建库

随着工程增长,可能想要将部分应用程序代码转换成用于应用程序且可能单元测试的库。此章节展示如何创建这种库。

我们的应用程序目前将业务逻辑直接包含在 main.cpp 。我们将代码提取到的新静态库称为 businesslogic 在子目录 "src/businesslogic" 如解释在 上一章节 .

为简单起见,库仅仅包含一个 C++ 源文件及其相应头文件,头文件包括在应用程序的 main.cpp :

├── CMakeLists.txt └── src ├── app │ ├── ... │ └── main.cpp └── businesslogic ├── CMakeLists.txt ├── businesslogic.cpp └── businesslogic.h

让我们查看一下库工程文件 ( src/businesslogic/CMakeLists.txt ).

add_library(businesslogic STATIC businesslogic.cpp ) target_link_libraries(businesslogic PRIVATE Qt6::Core) target_include_directories(businesslogic INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

让我们浏览一下内容。

add_library(businesslogic STATIC businesslogic.cpp )

add_library 命令创建库 businesslogic 。稍后,将让应用程序链接到此目标。

STATIC 关键字表示静态库。若想创建共享或动态库,将使用 SHARED 关键词。

target_link_libraries(businesslogic PRIVATE Qt6::Core)

有了静态库,实际不必链接其它库。但由于库使用的类来自 QtCore ,添加依赖链接到 Qt6::Core 。这会压入必要 QtCore 包括路径和预处理器定义。

target_include_directories(businesslogic INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

库 API 的定义在头文件 businesslogic/businesslogic.h 。通过调用 target_include_directories ,确保绝对路径 businesslogic 目录被自动添加作为使用我们的库的所有目标的包括路径。

这解放了我们的 main.cpp 从使用相对路径到定位 businesslogic.h 。相反,可以仅仅编写

#include

最后,必须将库的子目录添加到顶层工程文件中:

add_subdirectory(src/app) add_subdirectory(src/businesslogic) 使用库

要使用我们创建的库在 上一章节 ,我们指导 CMake 链接到它:

target_link_libraries(helloworld PRIVATE businesslogic Qt6::Widgets)

这确保 businesslogic.h 被找到当编译 main.cpp 时。此外,businesslogic 静态库将变为属于 helloworld 可执行文件。

在 CMake 术语中,库 businesslogic 指定 用法要求 (include 路径) 库 (应用程序) 的每个消费者都必须满足。 target_link_libraries 命令负责处理这。

添加资源

想在应用程序中显示一些图像,添加它们使用 Qt 资源系统 .

qt_add_resources(helloworld imageresources PREFIX "/images" FILES logo.png splashscreen.png )

qt_add_resources 命令自动创建包含引用图像的 Qt 资源。从 C++ 源代码,可以通过前置指定资源前缀访问图像:

logoLabel->setPixmap(QPixmap(":/images/logo.png"));

qt_add_resources 命令将自变量名称 (或目标名称) 作为第一个自变量。推荐使用此命令基于目标的变体,如以上范例所示。

添加翻译

Qt 工程中字符串的翻译被编码在 .ts 文件。见 Qt 国际化 了解细节。

要添加 .ts 文件到您的工程,使用 qt_add_translations 命令。

以下范例将德语和法语翻译文件添加到 helloworld 目标:

qt_add_translations(helloworld TS_FILES helloworld_de.ts helloworld_fr.ts)

这创建构建系统规则以自动生成 .qm 文件从 .ts 文件。默认情况下, .qm 文件嵌入在资源中且可访问透过 "/i18n" 资源前缀。

要更新条目在 .ts 文件,构建 update_translations 目标:

$ cmake --build . --target update_translations

要触发生成的 .qm 文件手动,构建 release_translations 目标:

$ cmake --build . --target release_translations

对于更多信息有关如何影响处理 .ts 文件和嵌入资源,见 qt_add_translations 文档编制 .

qt_add_translations 命令是方便包裹器。对于如何更细粒度控制 .ts 文件和 .qm 文件的处理,使用底层命令 qt_add_lupdate and qt_add_lrelease .

延伸阅读

官方 CMake 文档编制 是使用 CMake 的宝贵资源。

官方 CMake 教程 涵盖常见构建系统任务。

书籍 专业 CMake:实践指南 提供 CMake 最相关特征的很好介绍。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有