解析QT6自动生成的CMake文件

1 新建基于CMake的QT6项目

打开qt-creator,新建一个基于CMake的QT项目,编辑器将自动生成以下CMake文件。

cmake_minimum_required(VERSION 3.5)

project(HeyPlot VERSION 0.1 LANGUAGES CXX)

set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets PrintSupport)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets PrintSupport)

set(PROJECT_SOURCES
        main.cpp
        widget.cpp
        widget.h
        widget.ui
        qcustomplot.cpp
        qcustomplot.h
        heyplot.cpp
        heyplot.h
)

INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR})

if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
    qt_add_executable(HeyPlot
        MANUAL_FINALIZATION
        ${PROJECT_SOURCES}
    )
else()
    if(ANDROID)
        add_library(HeyPlot SHARED
            ${PROJECT_SOURCES}
        )
    else()
        add_executable(HeyPlot
            ${PROJECT_SOURCES}
        )
    endif()
endif()

target_link_libraries(HeyPlot PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::PrintSupport)

set_target_properties(HeyPlot PROPERTIES
    MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
    MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
    MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
    MACOSX_BUNDLE TRUE
    WIN32_EXECUTABLE TRUE
)

install(TARGETS HeyPlot
    BUNDLE DESTINATION .
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

if(QT_VERSION_MAJOR EQUAL 6)
    qt_finalize_executable(HeyPlot)
endif()

 可以看到QT生成的CMake文件和普通项目还是有所不同的,多了挺多奇怪的函数,这里对QT默认生成的CMake脚本文件做一下解析。

2 解析CMake文件

接下来我们按照先上代码,后上解析的方式对CMake文件进行解析。

2.1 定义CMake以及项目版本号

# 设置所需的最低CMake版本为3.5。
cmake_minimum_required(VERSION 3.5)
# 设置项目名称为"HeyPlot",版本号为0.1,使用的编程语言为C++。
project(HeyPlot VERSION 0.1 LANGUAGES CXX)

首先是一些比较基础的东西。配置文件先设置所需的最低CMake版本为3.5,设置项目名称为"HeyPlot",版本号为0.1,使用的编程语言为C++。

2.2 启用QT资源自动编译选项

# 启用自动UI编译(AUTOUIC)
set(CMAKE_AUTOUIC ON)
# 自动元对象编译(AUTOMOC)
set(CMAKE_AUTOMOC ON)
# 自动资源编译(AUTORCC)
set(CMAKE_AUTORCC ON)

然后,就到了比较奇怪的地方了,配置文件分别设置了CMAKE_AUTOUICCMAKE_AUTOMOCCMAKE_AUTORCC三个参数为ON,这些参数都是QT编译时独有的参数。

2.2.1 CMAKE_AUTOUIC

CMAKE_AUTOUIC参数用于启用自动处理Qt User Interface (UI) 文件的功能。当我们使用Qt进行GUI应用程序开发时,通常会创建UI文件(以.ui扩展名结尾),这些文件描述了用户界面的布局和组件。为了将UI文件与应用程序的代码连接起来,我们需要将它们转换为相应的C++代码。通过将CMAKE_AUTOUIC设置为 ON ,CMake将自动在构建过程中查找并处理项目中的UI文件。 具体而言,当我们启用CMAKE_AUTOUIC后,CMake会在构建过程中自动调用uic工具(UI编译器),将UI文件转换为对应的C++代码,并将生成的C++文件添加到构建系统中,以便编译器将其编译为最终的可执行文件。这样,我们就不需要手动执行uic工具来转换UI文件,CMake会在构建时自动完成这个步骤,简化了项目的配置和构建过程。

2.2.2 CMAKE_AUTOMOC

CMAKE_AUTOMOC参数用于启用自动处理启用自动处理Qt元对象编译(MOC)的功能。Qt的元对象编译器(Meta Object Compiler,MOC)是一个工具,用于处理Qt中的特殊C++扩展,例如信号和槽、动态属性和反射机制。MOC会解析源代码中的这些扩展,并生成额外的C++代码,用于支持这些特性的运行时行为。当我们使用到Qt进行应用程序开发时,一般会使用到信号和槽、Q_OBJECT宏或其他需要MOC处理的Qt特性,我们需要确保这些代码被MOC处理后再进行编译。通过将CMAKE_AUTOMOC设置为ON,我们告诉CMake自动查找需要MOC处理的源文件,并在构建过程中自动调用MOC来生成相应的额外C++代码。具体而言,启用CMAKE_AUTOMOC后,CMake会在构建过程中自动检测源文件中的需要MOC处理的特殊Qt扩展,并为这些源文件生成对应的MOC输出文件。然后,这些生成的MOC输出文件将被添加到构建系统中,以便编译器将其编译为最终的可执行文件。

2.2.3 CMAKE_AUTORCC

CMAKE_AUTORCC参数用于启用自动处理Qt资源文件的功能。Qt资源文件(.qrc)是一种用于将非代码资源(如图像、字体、样式表等)集成到应用程序中的方式。资源文件可以在运行时被动态加载和使用,使应用程序的资源管理更加方便和灵活。通过将CMAKE_AUTORCC设置为ON,我们将告诉CMake自动查找并处理项目中的Qt资源文件。 具体而言,启用CMAKE_AUTORCC后,CMake会在构建过程中自动查找项目中的资源文件(.qrc文件),并调用rcc工具(资源编译器)来将这些资源文件编译为二进制数据。然后,生成的二进制资源数据将被添加到构建系统中,以便在应用程序中使用。这样,我们就无需手动调用rcc工具来处理资源文件,CMake会在构建时自动处理这些步骤,简化了项目的配置和构建过程。当我们在代码中使用Qt的资源管理相关函数(如QResource)时,这些资源数据将被加载和使用。

2.3 定义使用到的C++标准

# 设置C++标准为C++17,并要求编译器支持此标准。
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

这和普通的CMake一致,这里直接跳过。

2.4 查找并加载外部依赖包

find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets PrintSupport)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets PrintSupport)

接下来时两个连续的find_package。这是一个很奇怪的构建方式,起初并不明白为什么使用两个连续的find_package来查找和加载外部依赖包,后面发现这两个find_package其实各有用处。

在第一个find_package函数中,CMake尝试查找并加载Qt6,如果找不到再尝试Qt5,同时CMake将要求同时加载Widgets和PrintSupport这两个模块,REQUIRED关键字确保这些模块是必需的,如果找不到任何一个模块,将会导致CMake错误并停止构建过程。在这个过程中,CMake将对QT_VERSION_MAJOR变量进行赋值告诉我们使用到的QT版本是什么。

在第二个find_package函数中,根据第一个find_package函数中找到的QT版本来引用具体的模块。这样连续的两个find_package,确保了之后的构建过程中使用到的模型能够和先前找到的Qt版本匹配。

2.5 导入项目文件

# 定义项目的源文件列表
set(PROJECT_SOURCES
        main.cpp
        widget.cpp
        widget.h
        widget.ui
        qcustomplot.cpp
        qcustomplot.h
        heyplot.cpp
        heyplot.h
)
# 包含源文件目录
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR})

首先,我们先定义了项目的源文件列表,这个和普通的CMake文件一样没什么好说的。然后我们包含了根目录为头文件搜索路径,在QT默认生成的项目中是没有INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR})这个步骤的,但是我认为这是十分错误的决定。没有INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR})步骤意味着CMake编译UI文件后生成的ui_xxxxx.h文件将无法和上述定义的项目源文件联系在一起。导致如果我们希望在qt-creator中对某个空间进行提升操作时无法找到对应的头文件,因此这里我把这句话加上。

2.6 创建可执行文件

# 如果Qt的主要版本号大于等于6,则使用"qt_add_executable"来创建可执行文件。否则,根据目标平台选择创建动态库(Android)或可执行文件。
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
    qt_add_executable(HeyPlot
        MANUAL_FINALIZATION
        ${PROJECT_SOURCES}
    )
else()
    if(ANDROID)
        add_library(HeyPlot SHARED
            ${PROJECT_SOURCES}
        )
    else()
        add_executable(HeyPlot
            ${PROJECT_SOURCES}
        )
    endif()
endif()

接下来时创建可执行文件,这里的qt_add_executable函数其实不是QT6独有的。从Qt 5.14版本开始,QT推荐使用qt_add_executable命令代替add_executable,以更好地集成Qt的构建系统。其主要区别如下:

  • qt_add_executable命令在内部自动处理了与Qt相关的构建步骤,例如自动生成moc文件(元对象编译),处理Qt资源文件(qrc),并将这些步骤与目标可执行文件的构建过程进行了整合。这样,可以更简化和统一Qt项目的构建过程,减少手动配置的需求。
  • qt_add_executable命令在生成目标可执行文件时使用了更好的默认设置,例如自动添加预定义宏和链接Qt的模块。

2.7 链接动态库并设置可执行文件属性

# 将Qt模块链接到目标可执行文件或动态库。
target_link_libraries(HeyPlot PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::PrintSupport)

# 设置目标可执行文件的属性,如MacOSX的Bundle标识符、版本号和短版本字符串,以及在Windows下作为可执行文件运行。
set_target_properties(HeyPlot PROPERTIES
    MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
    MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
    MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
    MACOSX_BUNDLE TRUE
    WIN32_EXECUTABLE TRUE
)

这个部分负责将Qt模块链接到目标可执行文件或动态库,同时也设置了目标可执行文件的属性,如MacOSX的Bundle标识符、版本号和短版本字符串,以及在Windows下作为可执行文件运行。

2.8 安装目标可执行文件到指定的目录。

install(TARGETS HeyPlot
    BUNDLE DESTINATION .
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

和普通CMake文件一致,这里略过

2.9 进行最后的可执行文件处理

# 如果使用的是Qt 6,则使用"qt_finalize_executable"进行最后的可执行文件处理。
if(QT_VERSION_MAJOR EQUAL 6)
    qt_finalize_executable(HeyPlot)
endif()

qt_finalize_executable是一个CMake宏,用于在构建Qt应用程序时进行最后的可执行文件处理。在使用Qt6的情况下,qt_add_executable命令会生成一个中间目标文件,该文件需要经过最后的处理步骤才能成为可执行文件。这个处理步骤包括添加额外的Qt相关链接项、处理资源文件等。 qt_finalize_executable宏负责执行这些最后的处理步骤,将中间目标文件转换为最终的可执行文件。它会添加必要的链接库、处理资源文件,并进行其他必要的操作,以确保可执行文件包含了所有所需的Qt组件和功能。在CMake脚本中,通常会在qt_add_executable之后紧接着调用qt_finalize_executable来完成构建过程。需要注意的是,qt_finalize_executable宏仅在使用Qt 6时才需要调用。对于旧版本的Qt,不需要调用此宏,因为构建过程会自动完成。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值