zoukankan      html  css  js  c++  java
  • Qt构建cmake工程方法总结

    由于工作需要,最近打算统一将所有C/C++项目都改成使用cmake编译。传统后台业务问题不大,但是有些牵涉到跨平台的Qt项目还是折腾了一阵。下面对这段时间的收获做一个总结,也希望帮助看到本文的朋友少走弯路。特此声明,以下配置均为Qt5.6.3 MinGW 4.9.2 32位版本。

    1. 基本配置项

    1.1 moc ui和rcc编译开关

    SET(CMAKE_AUTOMOC ON)
    SET(CMAKE_AUTOUIC ON)
    SET(CMAKE_AUTORCC ON)

    1.2 启用C++11标准

    * 如果在.h文件中直接对参数初始化或使用了nullptr等,请务必配置这一项

    SET(CMAKE_CXX_STANDARD 11)

    1.3 包含所有.h文件

    * 有些只编写了.h文件,例如常量声明,结构体声明等,请务必配置这一项

    SET(CMAKE_INCLUDE_CURRENT_DIR ON)

    1.4 查找Qt模块

    * 首先是CMAKE_PREFIX_PATH,对应各个模块的cmake文件路径,其次FIND_PACKAGE才能生效

    SET(CMAKE_PREFIX_PATH <PREFIX_PATH>/lib/cmake)
    FIND_PACKAGE(Qt5 COMPONENTS Core Xml Sql Gui Widgets REQUIRED)

     1.5 引入外部头文件和动态链接库

    * 我习惯在src的同级目录使用include和lib路径来保存依赖,这样让整个系统看起来更整洁

    INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/../include)
    LINK_DIRECTORIES(${PROJECT_SOURCE_DIR}/../lib)

     1.6 统一配置各目录层级的.cpp

    * 网上有很多做法是每一个目录编写独立的CMakeLists.txt,但是个人感觉没有单一CMakeLists.txt文件配置方便,特别是如果各个目录间存在依赖的情况下更容易出错

    AUX_SOURCE_DIRECTORY(./<mod_1> mod_1_src_list)
    AUX_SOURCE_DIRECTORY(./<mod_2> mod_2_src_list)
    AUX_SOURCE_DIRECTORY(. src_list)

    1.7 指定最终编译产物的输出路径 

    * 和使用include和lib作为外部依赖路径类似,我也习惯在src的同级目录分别创建bin和out用来存放最终的编译产物

    SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/../bin)
    SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/../out)

    1.8 区分release和debug生成的动态库

    * 有时候为了方便调试,我们需要让debug版本的动态以d结尾

    SET(CMAKE_DEBUG_POSTFIX d)

    1.9 QDebug在release下依然可以输出函数名和行号

    * 主要是为了保证日志数据有效

    ADD_DEFINITIONS(-DQT_MESSAGELOGCONTEXT)

     1.10 添加链接库

    TARGET_LINK_LIBRARIES(${target} Qt5::Sql Qt5::Gui <lib>)

     1.11 输出

    ADD_EXECUTABLE(${target} ${SRC_LIST})
    ADD_LIBRARY(${target} SHARED ${SRC_LIST})

    1.12 根据release和debug分目录数据产物

    * 主要是针对动态库产物的输出,分不同的目录更适合大型项目的统编

    SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_SOURCE_DIR}/../debug)
    SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/../release)

    1.13 添加自定义的宏

    * 可以在项目中通过条件编译的方式选择不同的配置

    OPTION(C_MODE "Use Customize Mode" ON)
    IF(C_MODE)
     # 其他指令
    ENDIF()

    1.14 添加指定文件

    * 一般来说,一个.cpp文件都会有一个.h来对应。编译的时候我们只需要告诉编译器所有的.cpp文件即可。例如:ADD_EXECUTABLE(sth ${cpp})。但是有时候,我们会定义一些结构体或常量,并将他们集中声明在一个.h文件里。

    FILE(GLOB HEADER_FILES "*.h")
    FILE(GLOB SOURCE_FILES "*.cpp")

    1.15 安装与复制

    * 当我们需要在编译完成以后执行copy或install的时候

    FILE(COPY ${HEADER_FILES} DESTINATION ${PROJECT_SOURCE_DIR}/../include/${target})
    
    INSTALL(TARGETS mylib
            RUNTIME DESTINATION bin
            LIBRARY DESTINATION lib
            ARCHIVE DESTINATION libstatic)

    2. 注意事项

    2.1 如果是使用MinGW编译windows下的动态库不需要添加导出类的宏

    2.2 LINK_DIRECTORIES 指令必须放在ADD_指令前

    2.3 对多级目录的项目使用cmake做统编,每一个层级的编译应该使用动态库的方式

    2.4 如果你使用的是QtCreator,自定义宏的方式可能不生效,但这并不是cmake的问题

  • 相关阅读:
    用.NET读取Flash格式文件信息
    通过ASP.NET页面重启服务器
    Webservice优点与缺点
    iClient 6R for Flex移动端开发的Q&A
    GIS十年路
    脚本调用命令行
    FME的简单介绍
    GIS从信息化到领域化(一)
    GIS从信息化到领域化(二)
    理性的看待地理信息共享交换平台建设
  • 原文地址:https://www.cnblogs.com/learnhow/p/15110705.html
Copyright © 2011-2022 走看看