712 Star 4.6K Fork 2.1K

飞扬青云 / QWidgetDemo

 / 详情

关于 cmake 构建工作以及与原有 qmake 构建的相关内容

待办的
创建于  
2022-08-16 12:26
  1. 有关 cmake 的构建工作

    • 基本的 cmake 构建骨架
      此骨架具有打破传统cmake使用方式,其类似于makefile项目(在每个目录都有一个 CMakeLists.txt)。
    • 该骨架可被直接应用到其它 cmake 与 qt 构建项目(适合通用移植)
    • 使用宏(macro)进行了抽象构建模式,减少了大量重复脚本与cmake指令
  2. 有关 qmake 的构建,

    • 在此项目中目前保留了原有的qmake构建脚本
    • 完全移除 qmake 构建部分
  3. 一些构建补充

    • 处理 cmake 构建下的 windows/linux/macos 等适配工作,由 cmake 构建扩展进行
  4. 有关当前相关内容模板(来自 社区维护的星火应用商店 项目)

    cmake_minimum_required(VERSION 3.5.1)
    
    project(spark-store LANGUAGES CXX VERSION 0.0.1)
    
    # 构建 qwidgetdemo 的配置流程
    include(cmake/SparkEnvConfig.cmake)           # 设置一些有关QT构建的开关
    include(cmake/SparkMacrosConfig.cmake)        # 声明了一些 spark_ 开头的 macro 宏
    include(cmake/SparkFindQt5Config.cmake)       # 提供了 target_link_qt5 用于目标链接 qt5 的库
    
    # 1.传统构建
    # spark_add_executable(control-battery        # 与 add_executable 相同
    #     control/battery/battery.cpp             # 传统构建方式需要添加指定的源代码文件
    #     control/battery/battery.h
    #     control/battery/main.cpp
    #     ...
    # )
    # 2. 传统链接目标
    # target_link_libraries(control-battery 
    #     Qt5::Core Qt5::Widgets Qt5::Gui         # 传统构建方式需要链接指定的库
    # )
    
    # 3. 使用 Spark 骨架构建与链接目标
    # _path 表示将指定的目录作为构建,自动将目录中源代码构建为一个目标(只支持一个目录)
    # spark_add_executable_path(control-battery
    #     control/battery
    # )
    # target_link_qt5(control-battery)            # 构建的目标需要使用 qt5 库
    
    # 4. 分层构建: 在下层目录中创建 CMakeLists.txt,并继续使用 Spark 骨架构建与链接目标
    # add_subdirectory(control)                   # 传统子构建方式,但已经可使用 spark_ 宏用于构建目标
    
    # 5. 下层目录中的 CMakeLists.txt
    # cmake_minimum_required(VERSION 3.5.1)
    # spark_add_executable_path(control-battery battery)
    # target_link_qt5(control-battery)            # 构建的目标需要使用 qt5 库
    
    
  5. 参阅内容:

  6. 本计划出处探索
    输入图片说明

评论 (7)

zinface 创建了任务
zinface 修改了描述
zinface 修改了描述
zinface 修改了描述
zinface 修改了描述
zinface 修改了描述
zinface 修改了描述
zinface 修改了描述
zinface 修改了描述
zinface 修改了描述
zinface 修改了描述
zinface 修改了描述
zinface 修改了描述
zinface 修改了描述
zinface 修改了描述
zinface 修改了描述
zinface 修改了描述
zinface 修改了描述
zinface 修改了描述
zinface 修改了描述
zinface 修改了描述
展开全部操作日志
control tool video widget ui other third
☑ battery ☑ comtool videobox ☑ colorwidget ☑ flatui ☑ bgdemo hotkey
☑ devicebutton ☑ nettool videopanel ☑ framelesswidget ☑ styledemo ☑ dbpage shortcut
☑ devicesizetable ☑ netserver videowidget ☑ gifwidget ☑ uidemo01 ☑ lineeditnext qwtdemo
☑ imageswitch ☑ base64helper ☑ lunarcalendarwidget ☑ uidemo08 ☑ mouseline qcustomplotdemo
☑ ipaddress ☑ countcode (win32)playffmpeg ☑ maskwidget ☑ uidemo09 ☑ ntpclient
☑ lightbutton ☑ emailtool (win32)playvlc ☑ movewidget ☑ uidemo10 ☑ trayicon designer
☑ navbutton ☑ moneytool (win32)plaympv ☑ screenwidget ☑ iconhelper ☑ echartgauge hotkey
☑ savelog ☑ pngtool ☑ multobj2slot
☑ saveruntime ☑ keytool ☑ lunarcalendarwidget hotkey
☑ smoothcurve ☑ keydemo shortcut
☑ zhtopy ☑ livetool miniblink
  ☑ livedemo qwtdemo
  • 在完成构建 control 层过程中产生了新的构建宏
    # spark_add_executable_paths
    # 自定义构建宏,基于指定的前缀名称,处理后续参数为子目录
        # item: 为进行遍历后的单项,类似于 python3 中的 (for item in items:)
        # file: 为在目录中不以递归(GLOB_RECURSE)方式寻找 qrc 文件,需要将其参与编译才能被 rcc
        # 并根据 prefix-<item> 生成构建目标,
    macro(spark_add_executable_paths _prefix_path)
        set(PATHS ${ARGN})
        foreach(item IN LISTS PATHS)
            file(GLOB QRCS "${item}/*.qrc")
            message(">>> add_executable: " "${_prefix_path}-${item} ${item} + ${QRCS}")
            spark_add_executable_path(${_prefix_path}-${item} ${item} ${QRCS})
            target_link_qt5(${_prefix_path}-${item})
        endforeach(item IN LISTS PATHS)
    endmacro(spark_add_executable_paths _prefix_path)
    
  • 在完成构建 other 层过程中产生了新的宏,用于扩展 target_link_<name>

    # spark_add_link
    # 自定义宏以代替当前使用 fucntion 定义 target_link_<name> 结构
        # _IN_NAME: 此宏生成 target_link_<name> 的要求参数
        # ARGN: 此宏剩余的参数列表
            # 在使用 target_link_<name> 时
            # _NAME: 用于此 fucntion 中的要求参数: <_NAME>目标将要连接此库
    macro(spark_add_link _IN_NAME)
        function(target_link_${_IN_NAME} _NAME)
            message("LINK ${_NAME} ${ARGN}")
            target_link_libraries(${_NAME} 
                ${ARGN})
        endfunction(target_link_${_IN_NAME} _NAME)
    endmacro(spark_add_link _IN_NAME)
    
    # function(target_link_qt5 NAME)
    #     target_link_libraries(${NAME} 
    #         Qt5::Core
    #         Qt5::Widgets
    #         Qt5::Network)
    # endfunction(target_link_qt5 NAME)
    
    # 使用 spark_add_link 生成 target_link_qt5 以替代上面内容 
    spark_add_link(qt5 Qt5::Core Qt5::Widgets Qt5::Network)
    
    # spark_add_link_qt5 
    # 自定义宏 spark_add_link_qt5 以扩展 target_link_qt5_<name> 结构
        # _IN_NAME: 此宏使用嵌套宏 spark_add_link 时追加 qt5_<name> 名称
        # 同等于 spark_add_link(qt_<name> ${ARGN})
    macro(spark_add_link_qt5 _IN_NAME)
        spark_add_link(qt5_${_IN_NAME} ${ARGN})
    endmacro(spark_add_link_qt5 _IN_NAME)
    
    # 使用 spark_add_link_qt5 生成 target_link_qt5_<name> 的宏
    spark_add_link_qt5(sql Qt5::Sql)
    spark_add_link_qt5(concurrent Qt5::Concurrent)
    spark_add_link_qt5(webenginewidgets Qt5::WebEngineWidgets)
    
    • 在处理构建 other-dbpage 时采用了以上的生成的 target_link_qt5_sql 宏用于链接 Qt5::Sql
  • 在完成构建 widget 层过程中,详细处理了 framelesswidget 的子模块部分构建
    cmake_minimum_required(VERSION 3.5.1)
    
    # 1. 使用宏自动展开单次构建为多次构建
    spark_add_executable_paths(widget 
        colorwidget         # 子构建说明注释
        framelesswidget     # 此可执行目标有后续依赖处理项
        gifwidget           # 子构建说明注释
        lunarcalendarwidget # 子构建说明注释
        maskwidget          # 子构建说明注释
        movewidget          # 子构建说明注释
        screenwidget        # 子构建说明注释
    )
    
    # 此处处理 framelesswidget 的各部分模块(其实这里应该再向下创建一层构建,不过算了)
    # 1. 首先构建 core
    spark_add_libraries_path(framelesscore framelesswidget/framelesscore)
    target_link_qt5(framelesscore)      # 构建的目标需要使用 qt5 库
    
    # 2. 再构建 form
        # form 依赖了 core
    spark_add_libraries_path(framelessform framelesswidget/framelessform)
    target_link_framelesscore(framelessform)    
    
    # 3. 可执行目标的依赖
        # framelesswidget 依赖了 from 并间接依赖了 core 及 Qt5 
    target_link_framelessform(widget-framelesswidget)
    
    
  • 在完成构建 tool 层过程中,详细处理了 comtool/nettool/netserver 的子模块部分构建

    cmake_minimum_required(VERSION 3.5.1)
    
    # 1. 构建第三方库
    set(QExtSerialPort_SOURCES
        3rd_qextserialport/qextserialport_global.h
        3rd_qextserialport/qextserialport_p.h
        3rd_qextserialport/qextserialport.cpp
        3rd_qextserialport/qextserialport.h
    )
    
    # 根据构建系统来导致相关文件
    if(CMAKE_HOST_WIN32)
        list(APPEND QExtSerialPort_SOURCES 3rd_qextserialport/qextserialport_win.cpp)
    elseif(CMAKE_HOST_UNIX)
        list(APPEND QExtSerialPort_SOURCES 3rd_qextserialport/qextserialport_unix.cpp)
    endif(CMAKE_HOST_WIN32)
    
    spark_add_libraries(qextserialport ${QExtSerialPort_SOURCES})
    target_link_qt5(qextserialport)
    
    spark_add_libraries_path(smtpclient 3rd_smtpclient)
    target_link_qt5(smtpclient)
    
    # 2. 使用宏自动展开单次构建为多次构建
    spark_add_executable_paths(tool 
        # comtool             # 特殊结构构建
        # nettool             # 特殊结构构建
        # netserver           # 特殊结构构建
        
        base64helper          # 子构建说明注释
        countcode             # 子构建说明注释
        emailtool             # 子构建说明注释
        moneytool             # 子构建说明注释
        pngtool               # 子构建说明注释
    
        keytool               # 子构建说明注释
        keydemo               # 子构建说明注释
        livetool              # 子构建说明注释
        livedemo              # 子构建说明注释
    )
    target_link_smtpclient(tool-emailtool)  # tool-emailtool 依赖了 smtpclient 库
    
    # 3. 构建 comtool
    # set(COMTOOL_INCLUDES
    #     comtool
    #     comtool/api
    #     comtool/form
    #     3rd_qextserialport
    # )
    # spark_add_libraries_path(comtool_api comtool/api)
    # target_link_qt5(comtool_api)
    # target_include_directories(comtool_api PUBLIC ${COMTOOL_INCLUDES})
    
    # spark_add_libraries_path(comtool_form comtool/form)
    # target_link_comtool_api(comtool_form)
    # target_link_qextserialport(comtool_form)
    
    # spark_add_executable_path(tool-comtool comtool comtool/qrc/main.qrc)
    # target_link_comtool_form(tool-comtool)
    
    
    # 4. 构建 nettool
    # set(NETTOOL_INCLUDES
    #     nettool
    #     nettool/api
    #     nettool/form
    #     3rd_qextserialport
    # )
    # spark_add_libraries_path(nettool_api nettool/api)
    # target_link_qt5(nettool_api)
    # target_link_qt5_websockets(nettool_api)
    # target_include_directories(nettool_api PUBLIC ${NETTOOL_INCLUDES})
    
    # spark_add_libraries_path(nettool_form nettool/form)
    # target_link_nettool_api(nettool_form)
    # target_link_qextserialport(nettool_form)
    
    # spark_add_executable_path(tool-nettool nettool nettool/qrc/main.qrc)
    # target_link_nettool_form(tool-nettool)
    
    
    # 此处发现结构类似,使用宏进行抽象构建
    
    # add_executable_api_form_qrc
    # 自定义宏用于抽象构建 comtool/nettool/netserver 这种特殊包含结构的子构建
    # 
    macro(add_executable_api_form_qrc _dir)
        spark_add_libraries_path(${_dir}_api ${_dir}/api)
        target_link_qt5(${_dir}_api)
        target_include_directories(${_dir}_api PUBLIC 
            ${_dir}
            ${_dir}/api
            ${_dir}/form
            3rd_qextserialport
        )
    
        spark_add_libraries_path(${_dir}_form ${_dir}/form)
        # target_link_${_dir}_api(${_dir}_form)     # 此处无法使用展开,将在外部处理
        target_link_qextserialport(${_dir}_form)
    
        spark_add_executable_path(tool-${_dir} ${_dir} ${_dir}/qrc/main.qrc)
        # target_link_${_dir}_form(tool-${_dir})    # 此处无法使用展开,将在外部处理
    endmacro(add_executable_api_form_qrc _dir)
    
    add_executable_api_form_qrc(comtool)
    target_link_comtool_api(comtool_form)
    target_link_comtool_form(tool-comtool)
    
    add_executable_api_form_qrc(nettool)
    target_link_nettool_api(nettool_form)
    target_link_nettool_form(tool-nettool)
    target_link_qt5_websockets(nettool_api)     # tool-nettool 需要依赖 QtWebSockets
    
    add_executable_api_form_qrc(netserver)
    target_link_netserver_api(netserver_form)
    target_link_netserver_form(tool-netserver)
    
    
    • 在处理 comtool/nettool/netserver 的子构建时,发现三个目标均有复杂形式的头文件包含过程,类似于循环包含(也可指循环依赖结构)。处理过程复杂,并且有三个相同构建过程,在使用宏抽象构建后减少了大量重复性构建过程。
  • 导出依赖图,可能因是头文件循环依赖原因,未在此处展现
    输入图片说明

可以,加油

  • 在完成构建 ui 层过程中,详细处理了 uidemo<x> 的部分构建(x01,08,09,10)

    cmake_minimum_required(VERSION 3.5.1)
    
    # 1. 使用宏自动展开单次构建为多次构建
    spark_add_executable_paths(ui
        # core_base           # 非独立库或程序不构建
        # core_qss            # 非独立库或程序不构建
        flatui              # 子构建说明注释
        iconhelper          # 子构建说明注释
        # styledemo           # qrc文件多,独立构建
        # uidemo01            # 复杂结构。宏构建
        # uidemo08            # 复杂结构。宏构建
        # uidemo09            # 复杂结构。宏构建
        # uidemo10            # 复杂结构。宏构建
    )
    
    # 2. 构建 styledemo
        # qrc 文件比较多
    spark_add_executable_path(ui-styledemo styledemo 
        styledemo/qrc/font.qrc
        styledemo/qrc/main.qrc
        styledemo/qrc/qm.qrc
        styledemo/qrc/qss.qrc
    )
    target_link_qt5(ui-styledemo)
    
    
    # 分析构建 uidemo<x>
        # 构建 uidemo<x> 复杂程度较高
    # 分析过程
        # uidemo<x> 使用了哪些文件(存在头文件交叉引用,第3、4点)
        # 1. 使用了 core_base/qrc 下的文件
        # 2. 使用了 core_qss 下的文件
        # 3. core_base 下的文件引用了 uidemo<x> 下的 head.h
        # 4. uidemo<x> 使用了 core_base/appinit.h
        # 5. uidemo<x>/form 使用了 core_base/iconhelper.h 与 core_base/quihelper.h
    
    # 分析结果
        # 抽象出构建结构并为 uidemo<x> 使用宏构建
    
    # 参与构建 uidemo01 的文件
    set(CORE_BASE_QRCS
        core_base/qrc/font.qrc
        core_base/qrc/image.qrc
        core_base/qrc/qm.qrc
    )
    set(CORE_QSS_QRCS
        core_qss/qss.qrc
    )
    set(UIHelper_Appinit 
        core_base/quihelper.cpp     # 被 uidemo<x>/form/frmmain.cpp 使用
        core_base/quihelper.h       # 被 uidemo<x>/form/frmmain.cpp 使用
        core_base/appinit.cpp       # 被 uidemo<x>/main.cpp 使用
        core_base/appinit.h         # 被 uidemo<x>/main.cpp 使用
    )
    set(IconHelper 
        iconhelper/iconhelper.cpp
        iconhelper/iconhelper.h
    )
    
    
    # 3. 构建 uidemo01 并制作抽象结构
        # 构建 uidemo1 的 form 库
        # 使用了 iconhelper
    spark_add_libraries_path(uidemo01_form uidemo01/form
        ${UIHelper_Appinit} 
        ${IconHelper}
    )
    target_include_directories(uidemo01_form PUBLIC 
        core_base/
        uidemo01/
    )
    target_link_qt5(uidemo01_form)
        # 构建 uidemo01 可执行文件
    spark_add_executable_path(ui-uidemo01 uidemo01 
        uidemo01/other/main.qrc
        ${CORE_BASE_QRCS}
        ${CORE_QSS_QRCS}
        ${UIHelper_Appinit} 
        ${IconHelper}
    )
    target_link_uidemo01_form(ui-uidemo01)
    
    
    
    # 使用宏进行抽象构建 uidemo<x> ,保留了 01 构建
    macro(spark_add_uidemo_id _id)
        spark_add_libraries_path(uidemo${_id}_form uidemo${_id}/form
            ${UIHelper_Appinit} 
            ${IconHelper}
        )
        target_include_directories(uidemo${_id}_form PUBLIC 
            core_base/
            uidemo${_id}/
        )
        target_link_qt5(uidemo${_id}_form)
        
        # 构建 uidemo${_id} 可执行文件
        if(NOT ${_id} STREQUAL "10")  
            set(uidemo${_id}_other
                uidemo${_id}/other/main.qrc) # uidemo10 不存在 other 目录,但其它存在
        endif(NOT ${_id} STREQUAL "10")
    
        spark_add_executable_path(ui-uidemo${_id} uidemo${_id} 
            ${uidemo${_id}_other} # 可能为空值的变量,uidemo10 将不存在此变量值
            ${CORE_BASE_QRCS}
            ${CORE_QSS_QRCS}
            ${UIHelper_Appinit} 
            ${IconHelper}
        )
        # target_link_uidemo${_id}_form(ui-uidemo${_id})     # 此处无法使用展开,将在外部处理
    endmacro(spark_add_uidemo_id _id)
    
    # spark_add_uidemo_id(01)  # 已构建,保留
    spark_add_uidemo_id(08)                 # 构建 uidemo08
    target_link_uidemo08_form(ui-uidemo08)
    spark_add_uidemo_id(09)                 # 构建 uidemo09
    target_link_uidemo09_form(ui-uidemo09)
    spark_add_uidemo_id(10)                 # 构建 uidemo10
    target_link_uidemo10_form(ui-uidemo10)
    
    
    • 在处理 uidemo01/uidemo08/uidemo09/uidemo10 的子构建时,发现三个目标均有复杂形式的头文件包含过程,类似于交叉包含形式。处理过程复杂,在理清关系后,尝试构建 uidemo01,并在成功之后使用相同结构进行抽象(为 uidemo08/uidemo09/uidemo10 进行了较为简单的构建处理)

登录 后才可以发表评论

状态
负责人
里程碑
Pull Requests
关联的 Pull Requests 被合并后可能会关闭此 issue
分支
开始日期   -   截止日期
-
置顶选项
优先级
参与者(2)
2067698 zinface 1623054918 59909 feiyangqingyun 1578915863
C++
1
https://gitee.com/feiyangqingyun/QWidgetDemo.git
git@gitee.com:feiyangqingyun/QWidgetDemo.git
feiyangqingyun
QWidgetDemo
QWidgetDemo

搜索帮助