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()
改变代码的编译过程
// 在cmakelists.txt中定义
ADD_DEFINITIONS(-DTEST_DEBUG) // 配置源码中的条件编译
#ifdef TEST_DEBUG
...
...
#else
...
#endif
debug调试
ADD_DEFINITIONS("-Wall -g")
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的问题
3. Windows下如何使用cmake和gcc
3.1 安装MinGW Installation Manager和CMake的windows安装包,安装gcc编译工具链(mingw32-gcc, mingw32-gcc-g++, mingw32-make ...缺少的依赖可以从MinGW Installation Manager里面安装)
3.2 配置环境变量
*3.3 mingw32-make.exe 复制后重命名为 cmake.exe
3.4 指定编译方案:cmake -G "MinGW Makefiles" . (如果编译器为vs的话使用"NMake Makefiles")
3.5 make 完成编译
*3.6 因为mingw已经不再更新,建议使用mingw-w64代替
Qt构建cmake工程方法总结的更多相关文章
- 【经验分享】win10 cmake 构建 Tengine 工程
欢迎关注我的公众号 [极智视界],回复001获取Google编程规范 O_o >_< o_O O_o ~_~ o_O 本教程详细记录了在 win10 环境中 ...
- cmake使用方法详解
cmake 简介 CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程).他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性 ...
- CMake 使用方法(转)
CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程).他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的 ...
- 转:CMake 使用方法
CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程).他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的 ...
- CMake 使用方法
CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程).他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的 ...
- CMake 使用方法 & CMakeList.txt<转>
CMake 使用方法 & CMakeList.txt cmake 简介 CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程).他能够输出各种各样的make ...
- Qt程序打包发布方法(使用官方提供的windeployqt工具)
Qt程序打包发布方法(使用官方提供的windeployqt工具) 转自:http://tieba.baidu.com/p/3730103947?qq-pf-to=pcqq.group Qt 官方开发环 ...
- 构建编译TVM方法
构建编译TVM方法 本文提供如何在各种系统上构建和安装TVM包的说明.它包括两个步骤: 1. 首先从C代码构建共享库( libtvm.so for linux, libtvm.dylib fo ...
- 使用BLADE构建c++工程管理
使用BLADE构建c++工程管理 字数764 阅读2753 评论2 喜欢4 一. c++工程依赖管理 之前在百度一直使用comake2构建c++项目,十分方便.免去了手写Makefile的痛苦,很多项 ...
- 解析Qt中QThread使用方法
本文讲述的是在Qt中QThread使用方法,QThread似乎是很难的一个东西,特别是信号和槽,有非常多的人(尽管使用者本人往往不知道)在用不恰当(甚至错误)的方式在使用QThread,随便用goog ...
随机推荐
- java面试一日一题:java内存区域
问题:请讲下java内存区域? 分析:该问题比较容易和jvm内存模型相混淆,内存模型说的是java的内存规范,规定的是多线程下访问主内存的规则:而内存区域,说的是java运行时的内存划分,换句话说就是 ...
- 关于MultipartFile
首先,他来自spring框架,用于处理文件上传的问题 一般来讲,这个接口主要是实现以表单形式上传文件的功能 常用方法: getOriginalFileName:获取文件名+拓展名 getContent ...
- hbuilder打包的应用上架appstore屏幕快照的生成方法
当我们使用hbuiderX或apicloud这些打包工具进行打包的时候,我们需要将打包好的ipa文件进行上架,但是你会发现,我们上架的时候需要上传5.5寸的iphone.6.5寸的iphone X和两 ...
- 《最新出炉》系列初窥篇-Python+Playwright自动化测试-58 - 文件下载
1.简介 前边几篇文章讲解完如何上传文件,既然有上传,那么就可能会有下载文件.因此宏哥就接着讲解和分享一下:自动化测试下载文件.可能有的小伙伴或者童鞋们会觉得这不是很简单吗,还用你介绍和讲解啊,不说就 ...
- 对比python学julia(第二章)--(第二节)勾股树—分形之美
2.1.问题描述 二话不说,先上图: 图一.勾股定理图形 图二.勾股树 ...
- [rCore学习笔记 021]多道程序与分时任务
写在前面 本随笔是非常菜的菜鸡写的.如有问题请及时提出. 可以联系:1160712160@qq.com GitHhub:https://github.com/WindDevil (目前啥也没有 导读 ...
- 国产深度学习框架吸引用户的一种免费手段——免费GPU时长
国产的深度学习框架基本成为了一个头部公司的标配了,不论是阿里.百度还是华为都推出了自己的深度学习框架,这几家公司为了吸引用户也都采取了免费使用GPU的活动,但是与阿里.百度的不同,华为是与固定的高校的 ...
- gym.ActionWrapper使用时的注意点——step函数可以覆盖observation函数
本文说的这个gym.ActionWrapper继承类的问题和gym.ObservationWrapper继承类的问题性质是一样的,具体看: gym.ObservationWrapper使用时的注意点- ...
- UE Websocket 通信
项目中遇到UE需要对接Websocket协议接收实时数据. 所以需要实现一个Websocket Client的功能. 由于UE引擎已经集成了Websocket库(基于libwebsocket),可以通 ...
- Kotlin 循环与函数详解:高效编程指南
Kotlin 循环 当您处理数组时,经常需要遍历所有元素. 要遍历数组元素,请使用 for 循环和 in 操作符: 示例 输出 cars 数组中的所有元素: val cars = arrayOf(&q ...