CMake+QT使用教程

一、CMake入门

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

1.构建一个控制台应用程序

# 指定应用程序所需的CMake最低版本(Qt本身至少需要CMake版本3.16)
cmake_minimum_required(VERSION 3.16)

# 设置项目名称和默认项目版本,同时告诉CMake该程序是用C++编写的
project(helloworld VERSION 1.0.0 LANGUAGES CXX)

# 设置变量CMAKE_CXX_STANDARD,指定C++版本(QT6需要支持c++ 17或更新版本的编译器)
# 设置变量CMAKE_CXX_STANDARD_REQUIRED,如果编译器太旧,让CMake打印一个错误
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 设置CMake查找Qt6,并导入模块Core
# 如果CMake找不到模块,设置标志REQUIRED让CMake终止
# 如果成功,CMake将设置一些变量,这些变量记录在模块变量中(见变量参考Module variables)
# 为了能找到依赖包,CMake可以设置变量CMAKE_PREFIX_PATH包含Qt6安装前缀
find_package(Qt6 REQUIRED COMPONENTS Core)

# qt_standard_project_setup命令为一般的QT应用程序设置项目范围的默认值
# 除此之外,该命令将CMAKE_AUTOMOC变量设置为ON,指示CMake自动设置规则,以便在需要时透明地调用Qt的元对象编译器(moc)。
qt_standard_project_setup()

# add_executable命令告诉CMake从指定源文件构建一个可执行文件(而不是库)
# 注意,这里通常不列出头文件。这与qmake不同,qmake需要显式列出头文件,以便元对象编译器(moc)处理它们。
# 对于比较复杂的项目需要改为调用qt_add_executable(),它是内置add_executable()命令的包装器,提供了额外的逻辑来自动处理诸如在静态Qt构建中链接Qt插件、特定于平台的库名定制等。
# 要创建库,使用qt_add_library。
add_executable(helloworld
    main.cpp
)

# 最后告诉CMake, helloworld可执行文件通过引用由上面的find_package()调用导入的Qt6::Core目标来使用Qt的Core模块。这不仅可以为链接器添加正确的参数,还可以确保将正确的include目录、编译器定义传递给c++编译器。PRIVATE关键字对于可执行目标并不是严格必要的,但是指定它是一种良好的实践。
# 如果helloworld是一个库而不是可执行文件,则应该指定PRIVATE或PUBLIC(如果库在头文件中提到了来自Qt6::Core的内容,则为PUBLIC,否则为PRIVATE)
target_link_libraries(helloworld PRIVATE Qt6::Core)

2.构建一个界面应用程序

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)

# 最后,我们在应用程序目标上设置属性,效果如下:
# 防止在Windows上创建控制台窗口。
# 在macOS上创建应用程序包。
set_target_properties(helloworld PROPERTIES
    WIN32_EXECUTABLE ON
    MACOSX_BUNDLE ON
)

3.构建子目录项目

  • 项目目录结构
<project root>
├── CMakeLists.txt
└── src
    └── app
        ├── CMakeLists.txt
        ├── main.cpp
        ├── mainwindow.cpp
        ├── mainwindow.h
        └── mainwindow.ui
  • 顶层CMakeLists.txt,包含整个项目的设置并调用add_subdirectory,顶层CMakeLists.txt设置的变量在子目录项目中可见
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)
  • 子目录项目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
)

4.构建库和使用库

  • 项目目录结构
<project root>
├── CMakeLists.txt
└── src
    ├── app
    │   ├── ...
    │   └── main.cpp
    └── businesslogic
        ├── CMakeLists.txt
        ├── businesslogic.cpp
        └── businesslogic.h
  • 库项目文件(src/businesslogic/CMakeLists.txt)
# add_library命令创建businesslogic库,STATIC表示静态库,SHARED表示动态库
add_library(businesslogic STATIC
    businesslogic.cpp
)

target_link_libraries(businesslogic PRIVATE Qt6::Core)

# 通过调用target_include_directories,确保businesslogic目录的绝对路径被自动添加为使用我们的库的所有目标的包含路径。
# 这使我们在main.cpp中不用使用相对路径来定位businesslogic.h。相反,我们可以直接写#include <businesslogic.h>
target_include_directories(businesslogic INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

最后,我们必须将库的子目录添加到顶级项目文件中:

add_subdirectory(src/app)
add_subdirectory(src/businesslogic)
  • 使用库
target_link_libraries(helloworld PRIVATE
    businesslogic
    Qt6::Widgets)

5.添加资源

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

用法:

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

6.添加翻译

qt_add_translations(helloworld
    TS_FILES helloworld_de.ts helloworld_fr.ts)

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

$ cmake --build . --target update_translations

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

$ cmake --build . --target release_translations

二、CMake命令参考(CMake Command Reference)

  • Qt6::Core

    CMake命令 描述
    qt_add_big_resources 将大型二进制资源编译为目标代码
    qt_add_binary_resources 从 Qt 资源文件列表创建 RCC 文件
    qt_add_executable 创建并最终确定指定平台类型的应用程序目标
    qt_add_library 创建并完成库
    qt_add_plugin 创建 Qt 插件目标
    qt_add_resources 将二进制资源编译为源代码
    qt_allow_non_utf8_sources 防止强制将源文件视为适用于 Windows 的 UTF-8
    qt_android_add_apk_target 定义运行安卓部署qt以生成APK的构建目标
    qt_android_apply_arch_suffix 将目标二进制文件的名称配置为包含特定于体系结构的后缀
    qt_android_generate_deployment_settings 生成 androiddeployqt 所需的部署设置文件
    qt_deploy_qt_conf 在部署时编写 qt.conf 文件
    qt_deploy_runtime_dependencies 部署可执行文件所需的Qt插件,Qt和非Qt库
    qt_disable_unicode_defines 防止在目标上自动设置某些与 Unicode 相关的编译器定义
    qt_extract_metatypes 防止在目标上自动设置某些与 Unicode 相关的编译器定义
    qt_finalize_project 处理与Qt项目相关的各种常见平台特定任务
    qt_finalize_target 处理与Qt目标相关的各种常见平台特定任务
    qt_generate_deploy_app_script 为应用程序生成部署脚本
    qt_generate_moc 对输入文件调用 moc
    qt_import_plugins 指定要为静态Qt构建导入的自定义插件集
    qt_set_finalizer_mode 自定义目标最终确定的各个方面
    qt_standard_project_setup 将项目范围的默认设置设置为标准排列
    qt_wrap_cpp 从源文件创建.moc文件
  • Qt6::DBus

    CMake命令 描述
    qt_add_dbus_adaptor 将项目范围的默认设置设置为标准排列
    qt_add_dbus_interface 生成实现 D-Bus 接口描述文件接口的C++源
    qt_add_dbus_interfaces 生成实现 D-Bus 接口描述文件接口的C++源
    qt_generate_dbus_interface 从头文件生成 D-Bus 接口
  • Qt6::InterfaceFramework

    CMake命令 描述
    qt_ifcodegen_extend_target 使用从 qface IDL 文件生成的文件扩展目标
    qt_ifcodegen_generate 从 qface IDL 文件生成文件
    qt_ifcodegen_import_variables 从 qface IDL 文件生成文件,并提供变量以在 CMake 中使用
    qt_set_ifcodegen_variable 将变量设置为 ifcodegen 模板中的给定 c 值
  • Qt6::LinguistTools

    CMake命令 描述
    qt_add_lrelease 添加目标以将Qt语言学家.ts文件转换为.qm文件
    qt_add_lupdate 添加目标以生成或更新Qt语言学家.ts文件
    qt_add_translation 添加目标以生成或更新Qt语言学家.ts文件
    qt_add_translations 添加目标以更新Qt Linguist .ts文件并将其转换为.qm文件
    qt_create_translation 设置Qt语言学家翻译工具链
  • Qt6::Qml

    CMake命令 描述
    qt_add_qml_module 设置Qt语言学家翻译工具链
    qt_add_qml_plugin 定义与 QML 模块关联的插件
    qt_deploy_qml_imports 部署可执行文件所需的 QML 模块的运行时组件
    qt_generate_deploy_qml_app_script 为 QML 应用程序生成部署脚本
    qt_generate_foreign_qml_types 在 QML 模块中注册来自一个目标的类型
    qt_import_qml_plugins 确保为静态构建导入目标所需的 QML 插件
    qt_query_qml_module 检索有关 QML 模块的信息
    qt_target_compile_qml_to_cpp
    qt_target_qml_sources 检索有关 QML 模块的信息
  • Qt6::RemoteObjects

    CMake命令 描述
    qt_add_repc_merged 从 Qt 远程对象 .rep 文件为源和副本类型创建C++头文件
    qt_add_repc_replicas 从 Qt 远程对象 .rep 文件为副本类型创建C++头文件
    qt_add_repc_sources 从 Qt 远程对象 .rep 文件为源类型创建C++头文件
    qt_reps_from_headers 从 QObject 头文件创建 .rep 文件
  • Qt6::Scxml

    CMake命令 描述
    qt_add_statecharts
  • Qt6::ShaderTools

    CMake命令 描述
    Qt Shader Tools Build System Integration 编译着色器并将其添加到Qt资源
  • Qt6::Widgets

    CMake命令 描述
    qt_wrap_ui 编译着色器并将其添加到Qt资源
  • Qt6::WebEngineCore

    CMake命令 描述
    qt_add_webengine_dictionary 将 hunspell 字典格式转换为 bdict 二进制格式

三、CMake变量参考(CMake Variable Reference)

1.模块变量(Module variables)

变量 描述
Qt6Widgets_COMPILE_DEFINITIONS 针对库构建时使用的编译定义列表。
Qt6Widgets_DEFINITIONS 针对库进行构建时使用的定义列表。
Qt6Widgets_EXECUTABLE_COMPILE_FLAGS 针对库构建可执行文件时使用的标志字符串。
Qt6Widgets_FOUND 描述是否成功找到模块的布尔值。
Qt6Widgets_INCLUDE_DIRS 针对库构建时使用的包含目录列表。
Qt6Widgets_LIBRARIES 模块导入的目标的名称:Qt5::Widgets
Qt6Widgets_PRIVATE_INCLUDE_DIRS 在构建库和使用私有Qt API时使用的私有包含目录列表。
Qt6Widgets_VERSION_STRING 包含模块版本的字符串。

2.安装变量(Installation variables)

变量 描述
QT_DEFAULT_MAJOR_VERSION 在混合Qt 5和Qt 6项目的情况下,在调用相应的find_package()之前,需要将其设置为5或6。如果未设置,第一次find_package调用将定义默认版本。
QT_LIBINFIX 当Qt配置了-libinfix时,保存库名称中使用的中缀的字符串。
QT_NO_CREATE_VERSIONLESS_FUNCTIONS 隐藏以qt_开头的命令,只保留以qt6_开头的版本化命令。
QT_NO_CREATE_VERSIONLESS_TARGETS 隐藏导入的以Qt::开头的目标。相反,您需要使用以Qt6::开头的目标。
QT_VISIBILITY_AVAILABLE 在Unix上,一个布尔值,用于描述Qt库和插件是否使用-fvisibility=hidden进行编译。这意味着只导出选定的符号。

3.项目变量(Project variables)

  • Qt6::Core

变量 描述
ANDROID_NDK_HOST_SYSTEM_NAME 特定于android的主机系统架构
ANDROID_SDK_ROOT Android SDK的位置
QT_ANDROID_ABIS 为其构建项目包的abi列表
QT_ANDROID_APPLICATION_ARGUMENTS 要传递给Android应用程序的参数列表
QT_ANDROID_BUILD_ALL_ABIS 允许使用自动检测的Qt for Android SDK列表构建多abi包
QT_ANDROID_MULTI_ABI_FORWARD_VARS 允许在多个abi构建中共享CMake变量
QT_ANDROID_SIGN_AAB 使用指定的密钥库、别名和存储密码对.aab包进行签名
QT_ANDROID_SIGN_APK 使用指定的密钥库、别名和存储密码对包进行签名
QT_DEPLOY_BIN_DIR 前缀-相对子目录,用于在某些目标平台上部署运行时二进制文件
QT_DEPLOY_LIB_DIR 前缀相对子目录,用于在某些目标平台上部署库
QT_DEPLOY_PLUGINS_DIR 前缀-相对子目录,用于在一些目标平台上部署Qt插件
QT_DEPLOY_PREFIX 部署的基本位置
QT_DEPLOY_QML_DIR 前缀-相对子目录,用于在一些目标平台上部署QML插件
QT_DEPLOY_SUPPORT 要包括用于设置部署支持的文件的名称
QT_ENABLE_VERBOSE_DEPLOYMENT 启用部署工具的详细模式
QT_HOST_PATH 交叉编译时主机Qt安装的位置
QT_IOS_LAUNCH_SCREEN 所有目标使用的iOS启动屏幕故事板的路径
QT_NO_COLLECT_BUILD_TREE_APK_DEPS 防止在Android部署期间收集项目构建的共享库目标
QT_NO_SET_XCODE_BUNDLE_IDENTIFIER 在iOS上禁用在目标终结期间提供备用应用程序包ID
QT_NO_SET_XCODE_DEVELOPMENT_TEAM_ID 在iOS上禁用在目标完成过程中提供备用团队ID
QT_NO_STANDARD_PROJECT_SETUP 防止后续对qt_standard_project_setup()的调用进行任何更改
QT_PATH_ANDROID_ABI_ 为相应的ABI指定Qt for Android路径的变量集
  • Qt6::Qml

变量 描述
QT_QML_OUTPUT_DIRECTORY 默认情况下将在其下面创建QML模块的基本输出目录
  • Qt6::InterfaceFramework

变量 描述
IFCODEGEN_VERBOSE 为所有ifcodegen函数启用详细日志记录
QT_IFCODEGEN_TEMPLATE_SEARCH_PATH ifcodegen模板的搜索路径

四、CMake属性参考(CMake Property Reference)

  • Qt6::Core

    目标属性

属性 描述
QT_ANDROID_ABIS 为单个目标的包构建的abi列表
QT_ANDROID_DEPLOYMENT_DEPENDENCIES 覆盖添加到目标部署中的Qt依赖项
QT_ANDROID_DEPLOYMENT_SETTINGS_FILE 指定目标生成的部署设置文件的位置
QT_ANDROID_EXTRA_LIBS 要与目标一起部署的额外库
QT_ANDROID_EXTRA_PLUGINS 额外的Qt插件与目标一起部署
QT_ANDROID_MIN_SDK_VERSION Android SDK最低版本
QT_ANDROID_NO_DEPLOY_QT_LIBS Qt共享库是否打包在Android的APK中
QT_ANDROID_PACKAGE_SOURCE_DIR 自定义Android包模板的路径
QT_ANDROID_SDK_BUILD_TOOLS_REVISION Android构建工具的修订使用
QT_ANDROID_SYSTEM_LIBS_PREFIX 指定Qt库在目标设备上的位置
QT_ANDROID_TARGET_SDK_VERSION Android目标SDK版本
QT_ANDROID_VERSION_CODE Android内部应用版本
QT_ANDROID_VERSION_NAME 可读的安卓应用版本
QT_IOS_LAUNCH_SCREEN iOS启动屏幕故事板的路径
QT_QML_IMPORT_PATH 指定要搜索QML导入的目录列表
QT_QML_ROOT_PATH 覆盖应用程序qml目录的位置
QT_RESOURCE_PREFIX 指定默认的Qt资源前缀
QT_WASM_INITIAL_MEMORY 内部WebAssembly初始内存
QT_WASM_PTHREAD_POOL_SIZE 内部WebAssembly线程池大小
qt_no_entrypoint 指定禁止链接到Qt的入口点库

源文件属性

属性 描述
QT_RESOURCE_ALIAS 为资源中的文件指定Qt资源别名
  • Qt6::DBus

源文件属性

属性 描述
CLASSNAME 覆盖默认的接口类名
INCLUDE 添加一个包含路径
NO_NAMESPACE 禁止生成名称空间名称
  • Qt6::Qml

源文件属性

属性 描述
QT_QMLTC_FILE_BASENAME 指定非默认的.h和.cpp文件名
QT_QML_INTERNAL_TYPE 将QML文件标记为提供内部类型
QT_QML_SINGLETON_TYPE 将QML文件标记为提供单例类型
QT_QML_SKIP_CACHEGEN 不允许将文件编译为字节代码
QT_QML_SKIP_QMLDIR_ENTRY 排除一个文件作为类型添加到QML模块的typeinfo文件
QT_QML_SKIP_QMLLINT 防止一个文件被自动qmllint处理
QT_QML_SKIP_TYPE_COMPILER 不允许使用qmltc将文件编译为c++
QT_QML_SOURCE_TYPENAME 重写文件提供的类型名称
QT_QML_SOURCE_VERSIONS 指定类型的自定义版本集

猜你喜欢

转载自blog.csdn.net/pointerz_zyz/article/details/129781963