用 cmake 构建Qt工程(对比qmake进行学习)
cmake vs qmake
- qmake 是为 Qt 量身打造的,使用起来非常方便
- cmake 使用上不如qmake简单直接,但复杂换来的是强大的功能
内置的 out-of source 构建。(目前QtCreator为qmake也默认启用了该功能。参考:浅谈 qmake 之 shadow build)
- 为各种平台和场景提供条件编译
可处理多个可执行文件情况,和很好配合 QtTest 工作
如何选择?
Using CMake to Build Qt Projects 一文中说:
- 对简单的Qt工程,采用 qmake
- 对复杂度超过 qmake 处理能力的,采用 cmake
尽管如此,如果简单Qt的工程都不知道怎么用 cmake 构建,复杂的工程,就更不知道如何使用 cmake 了。还是从简单的学起吧
简单的 Qt 程序
- #include <QtCore/QCoreApplication>
- #include <QtCore/QDebug>
- int main(int argc, char** argv)
- {
- QCoreApplication app(argc, argv);
- qDebug()<<"hello qt!";
- app.exec();
- }
如果不使用构建工具,直接调用编译器来编译的话,只需要类似这样的一条命令:
- g++ main.cpp -Ie:\Qt\4.7.0\include -o main -Le:\Qt\4.7.0\lib -lQtCore4
指定头文件目录,以及需要链接的库
qmake
qmake 需要一个 .pro 文件:
- CONFIG += qt
- QT -= gui
- SOURCES += main.cpp
因为我们需要 Qt的库和头文件,所以需要 CONFIG += qt 。
- 这是默认项,可直接去掉该行
- 启用qt后,可以通过 QT -= gui 来进一步细调我们需要的模块
- 默认是 core gui。我们不需要gui模块,故去掉。
cmake
cmake 需要一个 CMakeLists.txt 文件:
- PROJECT(example)
- FIND_PACKAGE(Qt4 REQUIRED)
- SET(QT_DONT_USE_QTGUI TRUE)
- INCLUDE(${QT_USE_FILE})
- ADD_EXECUTABLE(example main.cpp)
- TARGET_LINK_LIBRARIES(example ${QT_LIBRARIES})
- FIND_PACKAGE 来启用 Qt4
- 默认使用了core 和 gui,故手动禁用 QTGUI
这两行可以直接使用 FIND_PACKAGE(Qt4 COMPONENTS QtCore REQUIRED),未指定的模块将被禁用
- 包含一个CMake为Qt提供的配置文件,${QT_USE_FILE}变量是一个文件名
- 添加可执行程序目标
- 链接到 Qt 的库
复杂一点
考虑一个常规Qt程序:
- main.cpp
- mainwindows.ui
- mainwindows.h
- mainwindows.cpp
如果手动编译的话:
- mainwindow.ui 需要使用 uic 预处理
- uic mainwindow.ui -o ui_mainwindow.h
- mainwindow.h 需要 moc 预处理
- moc mainwindow.h -o moc_mainwindow.cpp
- 调用编译器进行编译
- g++ main.cpp mainwindow.cpp moc_mainwindow.cpp -Ie:\Qt\4.7.0\include -o main -Le:\Qt\4.7.0\lib -lQtCore4 -lQtGui4
qmake
使用 qmake 的的话,一个简单的 pro 文件
- TARGET = example
- TEMPLATE = app
- SOURCES += main.cpp mainwindow.cpp
- HEADERS += mainwindow.h
- FORMS += mainwindow.ui
HEADERS 中的文件是否需要 moc 进行预处理,qmake 运行时会根据其是否含有Q_OBJECT自动判断。
这也是为什么 很多人添加Q_OBJECT宏后不重新运行qmake会出错误的原因。
cmake
看看相应的 cmake 的 CMakeLists.txt 文件
- PROJECT(example)
- CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
- FIND_PACKAGE(Qt4 REQUIRED)
- INCLUDE(${QT_USE_FILE})
- INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
- QT4_WRAP_CPP(example_MOCS mainwindow.h)
- QT4_WRAP_UI(example_UIS mainwindow.ui)
- ADD_EXECUTABLE(example main.cpp mainwindow.cpp ${example_MOCS})
- TARGET_LINK_LIBRARIES(example ${QT_LIBRARIES})
- 需要 moc 的文件,用 QT4_WRAP_CPP 处理
- 生成的文件放入变量 example_MOCS 中,最后一块链接到可执行程序
- 需要 uic 的文件,用 QT4_WRAP_UI 处理
Windows
因为windows下链接时分为 console 和 windows 两个子系统,所以windows下有些问题需要特殊处理。
用 qmake 时:
- 默认是 windows 子系统
- 可以通过 CONFIG += console 使用 console 子系统
用 cmake 是:
- 默认是 console 子系统
- 使用 windows 子系统需要
- SET(QT_USE_QTMAIN TRUE)
- ADD_EXECUTABLE(example WIN32 main.cpp mainwindow.cpp ${example_MOCS})
前者启用 qtmain.lib 库来提供windows下的 WinMain 入口函数。后者链接 windows 子系统
再复杂一点
- main.cpp
- mainwindows.ui
- mainwindows.h
- mainwindows.cpp
- main.qrc
- main.rc
前面已经用到了Qt的 moc 和 uic,这次增加了资源系统 需要用 rcc
- rcc main.qrc -o qrc_main.cpp
同时,使用了windows下的资源文件 .rc (比如给程序添加图标)
- MVSC 中使用 rc.exe 对 .rc 文件进行处理
- MinGW 中使用 windres.exe 处理 .rc 文件
qmake
- TARGET = example
- TEMPLATE = lib
- HEADERS = mainwindow.h widget.h
- SOURCES = main.cpp widget.cpp mainwindow.cpp
- RESOURCES = main.qrc
- RC_FILE = main.rc
cmake
- PROJECT(example)
- CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
- FIND_PACKAGE(Qt4 REQUIRED)
- SET(QT_USE_QTMAIN TRUE)
- INCLUDE(${QT_USE_FILE})
- INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
- if(MINGW)
- set(CMAKE_RC_COMPILER_INIT windres)
- ENABLE_LANGUAGE(RC)
- SET(CMAKE_RC_COMPILE_OBJECT
- "<CMAKE_RC_COMPILER> <FLAGS> -O coff <DEFINES> -i <SOURCE> -o <OBJECT>")
- endif(MINGW)
- SET(example_SRCS main.cpp mainwindow.cpp widget.cpp res/main.rc)
- SET(example_MOC_SRCS mainwindow.h widget.h)
- QT4_WRAP_CPP(example_MOCS ${example_MOC_SRCS})
- QT4_ADD_RESOURCES(example_RCC_SRCS main.qrc)
- SET(example_SRCS ${example_SRCS} ${example_MOCS} ${example_RCC_SRCS})
- ADD_EXECUTABLE(example WIN32 main.cpp mainwindow.cpp ${example_SRCS})
- TARGET_LINK_LIBRARIES(example ${QT_LIBRARIES})
- 对Qt的资源文件,使用 QT4_ADD_RESOURCES 来调用rcc进行预处理
- 对 Windows 资源文件,直接和源文件一样,添加到列表中即可。只是:
- MinGW 下仅仅这么做还不行,上面的 MinGW 块用来修复这个问题
Debug 与 Release
qmake
使用 qmake 时,可以在 pro 文件内分别为两种模式设置不同的选项。
使用时,可以直接 make release 或 make debug 来编译不同的版本
cmake
不同于 qmake,由于 cmake 采用 out-of-source 方式。故:
- 建立debug release两目录,分别在其中执行cmake -DCMAKE_BUILD_TYPE=Debug(或Release)
- 需要编译不同版本时进入不同目录执行make
对生成 msvc 工程的情况, CMAKE_BUILD_TYPE 不起作用。生成工程后使用IDE自带的模式选择。
参考
http://blog.csdn.net/frestone2010/article/details/6690854
用 cmake 构建Qt工程(对比qmake进行学习)的更多相关文章
- 用CMake 构建Qt 项目
译:用CMake构建Qt项目作者: Johan Thelin 译者:赖敬文原链接:http://developer.qt.nokia.com/quarterly/view/using_cmake_t ...
- 【经验分享】win10 cmake 构建 Tengine 工程
欢迎关注我的公众号 [极智视界],回复001获取Google编程规范 O_o >_< o_O O_o ~_~ o_O 本教程详细记录了在 win10 环境中 ...
- 用CMake构建Qt5的Visual Studio工程
使用Visual Studio构建Qt工程的方法有很多种,可以使用Visual Studio自带的功能手动创建配置工程,也可以创建pro文件,然后通过VS的Qt插件导入进行创建.还有一种方式是通过CM ...
- mac book pro macOS10.13.3安装qt、qt creator C++开发环境,qt5.11.1,并解决cmake构建:qt mac this file is not part of any project the code
因为之前在Ubuntu下使用的是qtcreator开发,现在想在mac上装一个系统,因为许久未装了,还是花了点时间,不如写个博客,下次就更快安装了.在Mac OS X下使用Qt开发,需要配置Qt库和编 ...
- QT工程构建目录下,将生成的中间文件和可执行文件分离
在QT工程中,当我们选择了构建目录后,编译生成程序后,总会发现在debug目录下会有混淆着各类文件,如下图 很多时候,我们又仅仅只需要可执行文件或者自定义的动态链接库.如下图 当然,如果不觉得麻烦,有 ...
- 在 linux 下使用 CMake 构建应用程序
学习cmake http://xwz.me/wiki/doku.php?id=cmake 碰到的一些问题: 1.You have changed variables that require your ...
- Qt 工程 pro文件
工作中,感觉pro文件的有些内容真不太懂,现系统性的学习一下.于此备录,分享共勉. 为了更好的理解,先创建一个简单的工程作为实践. [1]创建一个pro文件 1.1 新建proDemo工程.步骤如下: ...
- QT工程pro设置实践(with QtCreator)----非弄的像VS一样才顺手?
源地址:http://my.oschina.net/jinzei/blog/100989?fromerr=DhQJzZQe 相信大家很多和我一样,用多了微软给的便利,用人家的就十分不习惯.于是就琢磨原 ...
- QT中的qmake详解
关于qmake,好一段时间令我一头雾水,不知道用来干嘛的,只知道怎么用,而且也只懂那么一两个命令,详细看过资料以后整理如下: 1.首先,感性的认识是,qmake可以利用源文件(包括头文件h,实现文件c ...
随机推荐
- 基于Maven,Spring+ActiveMQ实现,贴近实际
本文只实现了Topic,queue改点配置就行了 一.pom依赖 Spring的太长了,具体可以看下面源码里面 <dependency> <groupId>org.apache ...
- AOP概述:
AOP可以在不修改源代码的情况下,对程序进行增强. AOP面向切面进行编程,Spring将AOP引入到框架中,但是也需要遵守AOP联盟的规范. 通过预编译的方式和运行期动态代理实现程序功能的同意维护的 ...
- ios开发瀑布流框架的应用
一:瀑布流框架的应用:将封装好的瀑布流框架导入,遵守协议 二:代码: #import "HMShopsViewController.h" #import "HMShopC ...
- Android图表和图形创建库:EazeGraph
EazeGraph是一个 Android 库用于创建漂亮和花哨的图表.它具有易于使用和高度可定制的特点.当前支持四种不同的图表如下: Chart types Bar Chart Stacked Bar ...
- cocos2d-x 3.4 中文乱码解决之道
cocos2dx 中文乱码解决之道 须要引入五个文件 1.iconv.h 2.iconvString.cpp 3.iconvString.h 4.iconv.dll 5.libiconv.lib 完整 ...
- linux网络编程学习笔记之二 -----错误异常处理和各种碎碎(更新中)
errno 在unix系统中对大部分系统调用非正常返回时,通常返回值为-1.并设置全局变量errno(errno.h),如socket(), bind(), accept(), listen(). e ...
- JVM源码分析之System.currentTimeMillis及nanoTime原理详解
JDK7和JDK8下的System.nanoTime()输出完全不一样,而且差距还非常大,是不是两个版本里的实现不一样,之前我也没注意过这个细节,觉得非常奇怪,于是自己也在本地mac机器上马上测试了一 ...
- 再续FPGA初心,京微齐力脱胎京微雅格重新起航(700万元天使轮,泰有基金领投,水木基金、臻云创投、泰科源跟投。数千万元Pre-A轮融资,领投方为海康基金)
集微网消息,新的一年开启新的希望,新的空白承载新的梦想.这是年初一集微网给读者们拜年时写的寄语.在中国农历新年开年之际,半导体产业里也迎来了许多新的起点.例如长江存储在与苹果就采购前者的Nand闪存芯 ...
- C# 静态构造函数,静态变量执行顺序(升华版)
上篇 是基本语法基础下的执行顺序,包括继承这个维度下的执行顺序,我们可以依照的规律顺下来,下面我们看下一些摸不到头脑的情况 我们实验 一个 类中的方法 去调用另一个非继承类的情况, 我们主要看下 ...
- Android如何获得系统版本
如何获得Android系统版本 项目移植中,遇到需要区分不同系统版本的问题.于是查找相关方法如下: android.os.Build类提供了当前系统信息. 可用if (Build.VERSION.SD ...