Qt5 CMake 使用指南

CMAKE_PREFIX_PATH的使用说明

CMAKE_PREFIX_PATH是CMake中一个重要的环境变量,它用于帮助CMake在配置项目时找到各种依赖项的位置。这个变量尤其在处理那些不在标准位置安装的库时显得非常有用。

作用

CMAKE_PREFIX_PATH指定了一系列的路径,CMake会在这些路径中搜索需要的包、库、工具等。当使用find_package、find_library、find_file等命令时,CMake会优先在CMAKE_PREFIX_PATH指定的路径中查找。

设置方法

CMAKE_PREFIX_PATH可以通过多种方式设置,包括在命令行中直接设置,或者在CMakeLists.txt文件中设置。

在命令行中设置

在命令行中设置CMAKE_PREFIX_PATH,可以在调用cmake命令时使用-D选项:

这种方法适用于临时指定某个依赖项的路径。

在CMakeLists.txt中设置

也可以在CMakeLists.txt文件中通过set命令设置CMAKE_PREFIX_PATH:

这种方法适用于项目中有固定依赖路径的情况,可以确保所有人在构建项目时使用相同的路径。

注意事项

CMAKE_PREFIX_PATH可以包含多个路径,路径之间使用分号(;)分隔。

CMake中使用find_package查找Qt5

find_package命令在CMake中用于查找并加载指定的包(在这里是Qt5)。这个命令会检查系统中是否安装了指定的包,并提供必要的变量和目标,以便在项目中使用这些包。

使用find_package查找Qt5

当你需要在你的CMake项目中使用Qt5时,可以通过find_package命令来查找Qt5及其组件。以下是一个示例,展示了如何查找Qt5的核心组件,包括Core、Gui、Widgets和Multimedia:

find_package(Qt5 REQUIRED COMPONENTS
Core
Gui
Widgets
Multimedia
)

参数解释

REQUIRED:这个参数指示如果找不到Qt5或指定的组件,CMake应该终止配置过程。

COMPONENTS:后面跟随的是你希望在项目中使用的Qt5组件列表。在这个例子中,我们指定了Core、Gui、Widgets和Multimedia。

配置项目使用Qt5

在使用find_package成功找到Qt5之后,你可以通过链接目标库的方式,将Qt5组件添加到你的目标(例如可执行文件或库)中:

# 假设你的项目是一个可执行文件
add_executable(my_app
main.cpp
# 其他源文件
) # 链接Qt5库
target_link_libraries(my_app
Qt5::Core
Qt5::Gui
Qt5::Widgets
Qt5::Multimedia
)

注意事项

确保在调用find_package之前,你的系统已经正确安装了Qt5,并且CMAKE_PREFIX_PATH环境变量已经设置为Qt5的安装路径。这样CMake才能正确找到Qt5。

如果你的项目中使用了Qt特有的代码(如MOC、UI文件等),还需要在CMakeLists.txt中相应配置,例如启用AUTOMOC或使用qt5_wrap_ui处理UI文件。

在CMake中设置WIN32_EXECUTABLE选项构建非控制台程序

在使用CMake构建Windows应用程序时,WIN32_EXECUTABLE选项用于指定生成的是一个Windows应用程序,而不是控制台应用程序。这个选项通常在调用add_executable函数时使用,以确保应用程序在没有控制台窗口的情况下运行。

使用WIN32_EXECUTABLE选项

当你希望你的应用程序作为一个GUI应用程序运行,而不是在命令行窗口中运行时,可以在add_executable命令中使用WIN32标志。对于CMake版本3.14及以上,可以使用WIN32_EXECUTABLE目标属性来更明确地控制这一行为。

cmake_minimum_required(VERSION 3.14)

project(MyApp)

# 设置源文件
set(SOURCE_FILES main.cpp) # 添加一个可执行文件
add_executable(${PROJECT_NAME} WIN32 ${SOURCE_FILES}) # 对于CMake 3.14及以上版本,可以使用WIN32_EXECUTABLE目标属性
set_target_properties(${PROJECT_NAME} PROPERTIES
WIN32_EXECUTABLE ON
)

qt5 设置Windows应用程序图标

在CMake项目中,你可以通过指定资源文件来设置Windows应用程序的图标。这通常通过在项目的CMakeLists.txt文件中设置一个变量来实现,该变量指向包含图标资源的.rc文件。

以下是如何在CMake项目中设置Windows应用程序图标的示例:

set(APP_ICON_RESOURCE_WINDOWS "${CMAKE_CURRENT_SOURCE_DIR}/icon.rc")

参数解释

  • APP_ICON_RESOURCE_WINDOWS:这是一个自定义变量名,用于存储图标资源文件的路径。
  • ${CMAKE_CURRENT_SOURCE_DIR}:这是一个CMake变量,指向当前处理的CMakeLists.txt文件所在的目录。
  • /icon.rc:这是图标资源文件的相对路径和文件名。假设这个文件位于与当前CMakeLists.txt文件同一目录下。

使用资源文件

在设置了包含图标资源的.rc文件路径后,你需要将这个资源文件包含到你的应用程序中。这通常在添加可执行文件的命令中完成:

add_executable(${PROJECT_NAME}
${SOURCE_FILES}
${APP_ICON_RESOURCE_WINDOWS} # 包含图标资源文件
)

在这个示例中,${APP_ICON_RESOURCE_WINDOWS}变量被用于add_executable命令中,这样就将图标资源文件包含到了最终的应用程序中。

注意事项

  • 确保.rc文件正确指向了你的应用程序图标文件。.rc文件是一个资源脚本文件,通常包含了图标、菜单、对话框定义等资源的引用。

CMake中生成Qt UI头文件的两种方式

在使用CMake进行Qt项目的构建时,有两种主要方式来处理.ui文件,从而生成相应的UI头文件。这些方法分别是启用CMAKE_AUTOUIC选项和使用qt5_wrap_ui()命令。

  • 方法一:启用CMAKE_AUTOUIC选项

    通过设置CMAKE_AUTOUIC变量为ON,CMake会自动处理.ui文件,生成对应的UI头文件。这种方法简单且自动化,适用于大多数情况。

    set(CMAKE_AUTOUIC ON)

    CMAKE_AUTOUIC设置为ON时,CMake会自动寻找与当前项目中的.cpp文件同名的.ui文件,并将它们转换为UI头文件。这意味着不需要手动指定.ui文件,CMake会自动处理。

  • 方法二:使用qt5_wrap_ui()命令

    如果出于某种原因需要禁用CMAKE_AUTOUIC变量,还可以手动处理.ui文件。这可以通过使用qt5_wrap_ui()命令来实现,该命令将.ui文件转换为UI头文件,并将输出文件列表存储在指定的变量中。

    # 禁用CMAKE_AUTOUIC
    set(CMAKE_AUTOUIC OFF) # 手动处理.ui文件
    qt5_wrap_ui(UI_HEADERS ${FORM_FILES}) # 在add_executable或add_library中包含生成的UI头文件
    add_executable(${PROJECT_NAME}
    ${SOURCE_FILES}
    ${HEADER_FILES}
    ${UI_HEADERS} # 包含生成的UI头文件
    ${QT_RESOURCES}
    ${APP_ICON_RESOURCE_WINDOWS}
    ) # 添加 target_include_directories() 命令,生成的UI头文件所在的目录通常是当前构建目录
    # 即CMAKE_CURRENT_BINARY_DIR,因此需要将该目录添加到包含目录中。
    target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})

    在这种方法中,需要明确指定.ui文件,并通过qt5_wrap_ui()命令生成UI头文件。然后,在add_executableadd_library命令中包含这些生成的头文件。

Qt5 UI 生成的头文件找不到自定义类所在的头文件的处理方法

在使用 Qt5 进行项目开发时,有时会遇到一个问题:通过 uic 工具自动生成的 UI 头文件无法找到项目中自定义类的头文件。这种情况通常发生在项目结构比较复杂,或者自定义类与 UI 类不在同一个目录下时。以下是解决这个问题的两种方法:

  • 方法一:使用 target_include_directories

    这种方法是通过在 CMakeLists.txt 文件中为目标项目添加包含目录来解决的。具体操作如下:

    在 CMakeLists.txt 文件中找到 target_include_directories 命令。

    在该命令中添加包含自定义类头文件的目录路径。确保路径是相对于项目根目录的相对路径或者是一个绝对路径。

    例如,如果自定义类的头文件位于项目的 include 目录下,可以这样写:

    这样,当 uic 工具生成 UI 头文件时,编译器就能够找到自定义类的头文件了。

  • 方法二:取消勾选全局包含

    在某些情况下,如果项目设置中勾选了全局包含(在 Qt Creator 中),可能会导致编译器在整个项目范围内搜索头文件,这可能会引起一些不必要的编译问题。取消这个选项可以让我们更精确地控制包含目录,避免潜在的冲突。

    打开 Qt Creator,导航到项目设置。

    在构建设置中找到“全局包含”选项,并取消勾选。

    明确指定需要包含的目录,如方法一所述。

qt5 部署 Windows 程序

在 Windows 平台上部署 Qt5 程序时,需要将 Qt5 运行时库(DLL 文件)一同打包到程序目录中,以确保程序能够在没有安装 Qt5 的计算机上正常运行。以下是部署 Qt5 程序到 Windows 的一般步骤:

自动部署依赖项

如果系统中安装了Qt,并且windeployqt.exe工具可用,脚本会利用这个工具自动部署应用程序的依赖项。

检查windeployqt.exe

脚本首先检查windeployqt.exe是否存在:

if (EXISTS "${CMAKE_PREFIX_PATH}/bin/windeployqt.exe")
message("windeployqt exists")

如果存在,使用windeployqt.exe自动处理依赖项:

add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND "${CMAKE_PREFIX_PATH}/bin/windeployqt.exe" "--compiler-runtime"
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.exe"
)

手动部署依赖项

如果windeployqt.exe不存在,手动部署依赖项:

  1. 设置调试后缀:根据构建类型(Debug/Release),设置相应的后缀。
  2. 确定Qt安装路径:尝试定位Qt的安装路径。
  3. 复制Qt插件:将必要的Qt插件复制到构建目录。
  4. 复制Qt库:将需要的Qt库(如Qt5Core.dllQt5Gui.dll等)复制到构建目录。
  5. 处理MinGW依赖(如果使用MinGW):复制MinGW运行时库到构建目录。

MinGW部署

对于使用MinGW的项目,从指定路径复制MinGW运行时库:

if (MINGW)
set(MINGW_PATH "D:/Scoop/apps/msys2/current/ucrt64")
message("MINGW ENV: ${MINGW_PATH}")
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy "${MINGW_PATH}/bin/libgcc_s_seh-1.dll" "$<TARGET_FILE_DIR:${PROJECT_NAME}>"
COMMAND ${CMAKE_COMMAND} -E copy "${MINGW_PATH}/bin/libstdc++-6.dll" "$<TARGET_FILE_DIR:${PROJECT_NAME}>"
COMMAND ${CMAKE_COMMAND} -E copy "${MINGW_PATH}/bin/libwinpthread-1.dll" "$<TARGET_FILE_DIR:${PROJECT_NAME}>"
COMMENT "Deploying mingw runtime libraries from ${MINGW_PATH}/bin"
)
endif ()

附:完整 CMakeLists.txt 示例

cmake_minimum_required(VERSION 3.24)

project(Qt5CMakeDemo)
message("PROJECT_NAME: ${PROJECT_NAME}") find_package(Qt5 REQUIRED COMPONENTS
Core
Gui
Widgets
Multimedia
) # ==================== set build options ====================
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON) if (WIN32)
if (MINGW)
message("GNU")
set(CMAKE_PREFIX_PATH "C:/Qt/5.15.2/mingw81_64")
elseif (MSVC)
message("MSVC")
set(CMAKE_PREFIX_PATH "C:/Qt/5.15.2/msvc2019_64")
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
endif ()
elseif (APPLE)
# Add Apple specific settings here
else ()
endif () if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message("Build Type not set, defaulting to Release...")
set(CMAKE_BUILD_TYPE Release)
endif () message(${PROJECT_NAME} " build type: " ${CMAKE_BUILD_TYPE})
message("CMAKE_PREFIX_PATH: " ${CMAKE_PREFIX_PATH})
message("CXX Compiler: " ${CMAKE_CXX_COMPILER})
message("CXX Standard: " ${CMAKE_CXX_STANDARD}) # ==================== set Project Source Files ====================
set(SOURCE_FILES
main.cpp
mainwidget.cpp
)
set(HEADER_FILES
mainwidget.h
)
set(APP_ICON_RESOURCE_WINDOWS "${CMAKE_CURRENT_SOURCE_DIR}/icon.rc") # 如果禁用 CMAKE_AUTOUIC 变量,还可以使用 qt_wrap_ui() 该命令手动处理 .ui 文件。
# qt5_wrap_ui(UI_HEADERS mainwidget.ui)
# 如果禁用 CMAKE_AUTORCC 变量,还可以使用 qt5_add_resources() 命令手动处理 .qrc 文件。
# 同时可以 使用 AUTORCC_EXECUTABLE 变量指定 rcc 可执行文件的路径。
# qt5_add_resources(QT_RESOURCES pic.qrc) # ==================== set Project Target ====================
add_executable(${PROJECT_NAME}
${SOURCE_FILES}
${HEADER_FILES}
${APP_ICON_RESOURCE_WINDOWS}
# ${UI_HEADERS}
# ${QT_RESOURCES}
)
# target_include_directories(${PROJECT_NAME} PRIVATE
# ${CMAKE_CURRENT_SOURCE_DIR}
# # ${CMAKE_CURRENT_BINARY_DIR}
# )
target_link_libraries(${PROJECT_NAME}
Qt5::Core
Qt5::Gui
Qt5::Multimedia
Qt5::Widgets
) # create a GUI application
if (CMAKE_BUILD_TYPE MATCHES "Release" OR CMAKE_CONFIGURATION_TYPES MATCHES "Release")
set_target_properties(${PROJECT_NAME} PROPERTIES
WIN32_EXECUTABLE ON
MACOSX_BUNDLE ON
)
endif () # ==================== Deployment ====================
# Handle Windows deployment
if (WIN32 AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
message("WIN32 DEPLOYMENT")
# 如果存在 windeployqt.exe 工具,则自动部署依赖项
if (EXISTS "${CMAKE_PREFIX_PATH}/bin/windeployqt.exe")
message("windeployqt exists")
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND "${CMAKE_PREFIX_PATH}/bin/windeployqt.exe" "--compiler-runtime"
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.exe"
)
else ()
message(FATAL_ERROR "windeployqt.exe not found!")
# Set the debug suffix to copy the correct Qt libraries
set(DEBUG_SUFFIX)
if (CMAKE_BUILD_TYPE MATCHES "Debug" OR CMAKE_CONFIGURATION_TYPES MATCHES "Debug")
set(DEBUG_SUFFIX "d")
endif () # Set the path to the Qt installation
set(QT_INSTALL_PATH "${CMAKE_PREFIX_PATH}")
if (NOT EXISTS "${QT_INSTALL_PATH}/bin")
set(QT_INSTALL_PATH "${QT_INSTALL_PATH}/..")
if (NOT EXISTS "${QT_INSTALL_PATH}/bin")
set(QT_INSTALL_PATH "${QT_INSTALL_PATH}/..")
endif ()
endif ()
message("QT_INSTALL_PATH: ${QT_INSTALL_PATH}") # Copy the required Qt plugins to the build directory
if (EXISTS "${QT_INSTALL_PATH}/plugins/platforms/qwindows${DEBUG_SUFFIX}.dll")
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory
"$<TARGET_FILE_DIR:${PROJECT_NAME}>/plugins/platforms/")
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
"${QT_INSTALL_PATH}/plugins/platforms/qwindows${DEBUG_SUFFIX}.dll"
"$<TARGET_FILE_DIR:${PROJECT_NAME}>/plugins/platforms/")
endif () # Copy the required Qt libraries to the build directory
foreach (QT_LIB Core Gui Widgets Multimedia Network Svg)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
"${QT_INSTALL_PATH}/bin/Qt5${QT_LIB}${DEBUG_SUFFIX}.dll"
"$<TARGET_FILE_DIR:${PROJECT_NAME}>")
endforeach () # MINGW deployment, copy the required MinGW libraries
if (MINGW)
if (NOT DEFINED ENV{UCRT64})
# message(FATAL_ERROR "UCRT64 environment variable not set!")
set(MINGW_PATH "D:/Scoop/apps/msys2/current/ucrt64")
message("MINGW ENV: ${MINGW_PATH}")
else ()
set(MINGW_PATH "$ENV{UCRT64}")
message("MINGW UCRT64 ENV: ${MINGW_PATH}")
endif ()
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy "${MINGW_PATH}/bin/libgcc_s_seh-1.dll" "$<TARGET_FILE_DIR:${PROJECT_NAME}>"
COMMAND ${CMAKE_COMMAND} -E copy "${MINGW_PATH}/bin/libstdc++-6.dll" "$<TARGET_FILE_DIR:${PROJECT_NAME}>"
COMMAND ${CMAKE_COMMAND} -E copy "${MINGW_PATH}/bin/libwinpthread-1.dll" "$<TARGET_FILE_DIR:${PROJECT_NAME}>"
COMMENT "Deploying mingw runtime libraries from ${MINGW_PATH}/bin"
)
endif ()
endif () # End of windeployqt.exe check
endif ()

Qt5 CMake 使用指南的更多相关文章

  1. ROS1 Qt5 CMake基本配置

    ############################################################################## # CMake ############# ...

  2. CMake入门指南-编译教程

    CMake是一个比make更高级的编译配置工具,它可以根据不同平台.不同的编译器,生成相应的Makefile或者vcproj项目.通过编写CMakeLists.txt,可以控制生成的Makefile, ...

  3. CMake入门指南

    原文地址:http://www.cnblogs.com/sinojelly/archive/2010/05/22/1741337.html CMake是一个比make更高级的编译配置工具,它可以根据不 ...

  4. Qt5 Cmake

    project(my) cmake_minimum_required(VERSION ) set (CMAKE_PREFIX_PATH "C:\\Qt\\Qt5.3.0\\5.3\\msvc ...

  5. Qt5 CMake cross compile

    cmake_minimum_required(VERSION 2.8) if (${ARM}) set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCES ...

  6. 使用Qt5+CMake实现图片的区域选择(附源码)

    近期研发涉及到了图片的区域选择,找来一些资料一直不能很满意,所以自己实现了一个. 实现步骤如下.源码可以点击ImageAOI获取. 如下资料来自源码的README. ImageAOI (XLabel) ...

  7. Android:cmake开发指南

    一.静态库与动态库构建 (.so)共享库,shared object:节省空间,在运行时去连接,如果执行机器上没有这些库文件就不能执行. (.a)静态库,archive:静态库和程序化为一体,不会分开 ...

  8. Qt5 CMake项目简单模板

    cmake_minimum_required(VERSION 3.5) project(test VERSION 0.1 LANGUAGES CXX) set(CMAKE_INCLUDE_CURREN ...

  9. CMake安装(linux)

    环境:CentOS6.5 1.下载网址: http://www.cmake.org/download/ (选择linux版本,编译安装) 2.安装 # tar zxvf cmake-.tar.gz # ...

  10. [C] c99int(让VC等编译器自动兼容C99的整数类型)V1.02。源码托管到github、添加CMake编译配置文件、使用doxygen规范注释

    新版本—— http://www.cnblogs.com/zyl910/p/zlstdint_v100.html[C] zlstdint(让VC.TC等编译器自动兼容C99的整数类型)V1.0.支持T ...

随机推荐

  1. Gson toJson 忽略 long 为 0的数据

    起因于数据id过大,所以将对应int , Integer都修改为long, 测试过程中发现 Gson toJson时,字段将int为0的数据忽略,但long 没有, 所以 1. 新增适配器 impor ...

  2. ES6中的Set数据结构

    Set是ES6新推出的数据结构,Set结构里面的每个元素都是唯一的: 如何创建一个Set? // Set 构造函数接收一个数组进行初始化;如果什么都不传则创建一个空Set; var set = new ...

  3. 小tips:怎样实现简单的前端hash与history路由方式?

    前端路由实现方式,主要有两种,分别是history和hash模式. hash模式 不同路由对应的hash是不一样的,如何能够监听到URL中关于hash部分发生的变化?浏览器已经暴露给我们一个现成的方法 ...

  4. 【论文解读】transformer小目标检测综述

    一.简要介绍       Transformer在计算机视觉领域迅速普及,特别是在目标识别和检测领域.在检查最先进的目标检测方法的结果时,我们注意到,在几乎每个视频或图像数据集中,transforme ...

  5. 合合信息扫描全能王发布“黑科技”,让AI替人“思考”图像处理问题

    现阶段,手机扫描正越来越多地进入到人们的生活中.随着扫描应用场景的不断拓宽,诸多细节的问题逐渐显露,比如使用者在拍照扫描文档时,手指不小心"入镜"了,只能重拍:拍电脑屏幕时,画面上 ...

  6. SQL Server – 执行计划和各种 join 方式 (Execution plan & Join Pattern)

    前言 我几乎从来没有遇到过性能问题, 毕竟项目真的太小了. 一般上只要用常识去建 index 就可以了. 但是这并不阻碍我对知识的追求. 这篇是关于一些性能优化和原理的内容. 纯属学习, 希望未来有机 ...

  7. 【VMware VCF】使用 VCF Import Tool 将现有 vSphere 环境转换为管理域。

    VMware Cloud Foundation 5.2 发布并引入了一个新的功能,借助 VCF Import Tool 工具可以将现有 vSphere 环境直接转换(Convert)为管理工作负载域或 ...

  8. pimp技法浅析--实现轻量级的面向接口编程

    pimp.hpp: #ifndef pimp_hpp #define pimp_hpp class CMyComponent{ public: CMyComponent(); ~CMyComponen ...

  9. [namespace hdk] 向量 direct_vector

    我忏悔我有罪我心情又不好了不知道干什么所以又不小心封了个东西啊啊啊啊啊啊啊啊 功能 已重载 [] 运算符(左值) 已重载 = 运算符(可使用向量或 std:::vector) 已重载 + += - - ...

  10. .net6 使用gRPC示例

    创建一个gRPC服务项目(grpc服务端)和一个 webapi项目(客户端),测试项目结构如下: 公共模型 测试接口相关类,放在公共类库中,方便服务端和客户端引用相同模型 public class R ...