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进行学习)的更多相关文章

  1. 用CMake 构建Qt 项目

    译:用CMake构建Qt项目作者: Johan Thelin  译者:赖敬文原链接:http://developer.qt.nokia.com/quarterly/view/using_cmake_t ...

  2. 【经验分享】win10 cmake 构建 Tengine 工程

      欢迎关注我的公众号 [极智视界],回复001获取Google编程规范   O_o   >_<   o_O   O_o   ~_~   o_O   本教程详细记录了在 win10 环境中 ...

  3. 用CMake构建Qt5的Visual Studio工程

    使用Visual Studio构建Qt工程的方法有很多种,可以使用Visual Studio自带的功能手动创建配置工程,也可以创建pro文件,然后通过VS的Qt插件导入进行创建.还有一种方式是通过CM ...

  4. 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库和编 ...

  5. QT工程构建目录下,将生成的中间文件和可执行文件分离

    在QT工程中,当我们选择了构建目录后,编译生成程序后,总会发现在debug目录下会有混淆着各类文件,如下图 很多时候,我们又仅仅只需要可执行文件或者自定义的动态链接库.如下图 当然,如果不觉得麻烦,有 ...

  6. 在 linux 下使用 CMake 构建应用程序

    学习cmake http://xwz.me/wiki/doku.php?id=cmake 碰到的一些问题: 1.You have changed variables that require your ...

  7. Qt 工程 pro文件

    工作中,感觉pro文件的有些内容真不太懂,现系统性的学习一下.于此备录,分享共勉. 为了更好的理解,先创建一个简单的工程作为实践. [1]创建一个pro文件 1.1 新建proDemo工程.步骤如下: ...

  8. QT工程pro设置实践(with QtCreator)----非弄的像VS一样才顺手?

    源地址:http://my.oschina.net/jinzei/blog/100989?fromerr=DhQJzZQe 相信大家很多和我一样,用多了微软给的便利,用人家的就十分不习惯.于是就琢磨原 ...

  9. QT中的qmake详解

    关于qmake,好一段时间令我一头雾水,不知道用来干嘛的,只知道怎么用,而且也只懂那么一两个命令,详细看过资料以后整理如下: 1.首先,感性的认识是,qmake可以利用源文件(包括头文件h,实现文件c ...

随机推荐

  1. POJ 1751 Highways (ZOJ 2048 ) MST

    http://poj.org/problem?id=1751 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2048 题目大 ...

  2. stackedit

    https://github.com/benweet/stackedit/ https://github.com/waltcow/blog/issues/4

  3. iir调试记录

    1.目的 实现採样率fs=50MHz,通带为5MHz~15MHz.阻带衰减60dB的IIR带通滤波器 2.方案 採取直接型 3.具体设计 (1)确定滤波器的系数,系数和滤波器输出量化位宽 先依据要求的 ...

  4. 一起talk C栗子吧(第八十三回:C语言实例--进程间通信概述)

    各位看官们,大家好,前二回中咱们说的是进程停止的样例,这一回咱们说的样例是:进程间通信.闲话休提,言归正转.让我们一起talk C栗子吧! 看官们.每一个进程都拥有自己的资源,假设不同进程之间须要共享 ...

  5. ios开发Base64编码以及加密相关学习

    一:.Base64补充 ```objc 1.Base64简单说明 描述:Base64可以成为密码学的基石,非常重要. 特点:可以将任意的二进制数据进行Base64编码 结果:所有的数据都能被编码为并只 ...

  6. 调用另一个Activity 分类: H1_ANDROID 2013-09-22 14:11 2217人阅读 评论(0) 收藏

    参考自Google官方文档Traning/Getting Started/Building a simple user interface, Startinganother activity,http ...

  7. 日期和时间的格式化定义(ISO C89)

    格式化定义本质上控制的是占位. 日期 %Y:4位数的年份: %y:2位数的年份: %m:2位数的月份(1-12) %d:2位数的日(01-31) 时间 %H:24小时制(0-23) %I:12小时制( ...

  8. MinGW 与MSVC的区别

    Qt 中有两种方式编译,一种是MinGW ,另一种MSVC. 其中:MSVC是指微软的VC编译器 MingGW是指是Minimalist GNU on Windows的缩写.它是一个可自由使用和自由发 ...

  9. 【u211】编码

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] 假设phi(W)得到是按照以下算法编码后的结果: 1. 如果W的长度为1那么phi(W)即为W: 2. ...

  10. [CSS] Specify grid columns, rows, and areas at once with the grid-template shorthand

    We can specify grid columns, rows, and areas in one property using the grid-template shorthand. .con ...