Qmake VS Cmake 对比讲解

2023-11-20

用 cmake 构建Qt工程(对比qmake进行学习)

cmake vs qmake

  • qmake 是为 Qt 量身打造的,使用起来非常方便
  • cmake 使用上不如qmake简单直接,但复杂换来的是强大的功能 内置的 out-of source 构建。(目前QtCreator为qmake也默认启用了该功能。) 为各种平台和场景提供条件编译 可处理多个可执行文件情况,和很好配合 QtTest 工作

如何选择?

  • 对简单的Qt工程,采用 qmake
  • 对复杂度超过 qmake 处理能力的,采用 cmake

尽管如此,如果简单Qt的工程都不知道怎么用 cmake 构建,复杂的工程,就更不知道如何使用 cmake 了。还是从简单的学起吧

1、简单的 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模块,故去掉。

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QT嵌入式开发,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

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自带的模式选择。

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QT嵌入式开发,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qmake VS Cmake 对比讲解 的相关文章

随机推荐

  • vue+java实现在线播放mp4视频

    首先如果本地的mp4视频可以播放 但是在网页就显示视频格式不正确 可能原视频不是mp4格式的 更改后缀名为mp4了 但是在网页上还是无法播放 可以用 ffmpeg转换视频格式 一般遇到格式问题都是视频格式不对 需要专门的工具来转换 java
  • 《Linux系统调用:localtime,setlocale》

    一 介绍 时区 不同国家 有的甚至是同一国家不同地区 使用不同的时区和夏时制 对于要输入和输出时间的程序来说 必须对系统所处的时区和夏时制加以考虑 所有的细节已经由C语言库包办了 时区的定义 时区信息繁琐又多 出于这个原因系统没有将其直接编
  • 【ES6】Reflect反射机制

    文章目录 一 Reflect概述 二 用法详解 1 Object gt Reflect 2 修改Object方法的返回结果 3 命令式操作 gt 函数式操作 4 与Proxy对象的方法一一对象 5 apply 总结 一 Reflect概述
  • xshell如何连接远程服务器

    1 打开xshell后 点击新建 gt 会话 2 名称可以随意写 主机需要按照要求填写 远程服务器的IP在这里找 3 点击用户身份验证 4 按照要求填写用户名和密码 5 点击确定后 如果出现下面的命令则说明连接成功 6 再次打开xshell
  • 2021 CCF大数据与计算智能大赛个贷违约预测top 73 解决方案

    目录 一 概述 二 解题过程 2 1 数据 2 2 构建基线 2 3 进阶思路一 2 4 进阶思路二 2 5 进阶思路三 2 6 融合 2 7 调优提分过程 2 8 其他工作 三 结语 一 概述 这是我第二次参加大数据类型的竞赛 也是第一次
  • 如何在Word中粘贴出好看的代码

    文章目录 前言 使用highlightcode实现 总结 前言 每到毕业设计时 论文中一大段一大段的代码阅读起来很难受 这还是python代码 相对比较短 如果是STM32相关代码 看起来更难受 有没有一种办法让代码看起来舒服一些呢 使用h
  • java 数组的长度_Java如何获取数组和字符串的长度(length还是length())

    限时 1 秒钟给出答案 来来来 听我口令 Java 如何获取数组和字符串的长度 length 还是 length 在逛 programcreek 的时候 我发现了上面这个主题 说实话 我当时脑海中浮现出了这样一副惊心动魄的画面 面试官老马坐
  • python中添加空白和删除空白

    添加空白的方法 制表符 字符组合 t 换行符 字符组合 n 删除空白 方法名 功能 rstrip 剔除末尾的空白 lstrip 剔除开头的空白 strip 剔除两端的空白 在实际程序中 这些剥除函数最长用于在存储用户输入前对其进行清理
  • 时序预测

    时序预测 MATLAB实现TCN LSTM时间卷积长短期记忆神经网络时间序列预测 目录 时序预测 MATLAB实现TCN LSTM时间卷积长短期记忆神经网络时间序列预测 预测效果 基本介绍 模型描述 程序设计 参考资料 预测效果 基本介绍
  • win10下的anaconda安装pymysql

    1 打开anaconda的终端 即 anaconda prompt 2 输入命令 pip install pymysql ps 其余包都可以使用pip install xxx来完成安装 若下载失败 可在一下链接查找相关包进行安装 https
  • Java 单例模式、工厂模式、代理模式

    文章目录 单例模式 概念 单例模式的类型 破坏单例模式 枚举实现单例模式 工厂模式 概述 简单工厂模式 工厂方法 抽象工厂 代理模式 Proxy 概述 静态代理 动态代理 单例模式 概念 单例模式指在内存中创建对象且仅创建一次的设计模式 在
  • 《Pyramid Scene Parsing Network》

    Pytorch代码 1 研究问题 目前基于FCN的语义分割网络缺乏利用不同尺度全局上下文信息的能力 对于复杂图像的语义分割 如ADE20K数据集 存在问题 注 感受野的大小可以粗略表示为使用上下文信息的程度 2 研究方法 提出了金字塔场景理
  • Mybatis的常用注解

    加载配置文件的时候 绝对路径和相对路径的写法都不太好用 我们经常使用的两种方法第一种就是使用类加载器 他只能读取类路径的配置文件 第二种就是使用ServletContext对象的getRealPath 函数 mybatis的常用注解 1 与
  • jsp+servlet+ajax实现登录

    该案列使用jsp servlet ajax实现登录 页面简洁大方 弹框都是封装的插件 整体案列采用三层的模式 链接数据库方面用的是dbcp的链接池 数据库时mysql 运行效果如下图 下载地址 jsp servlet ajax实现登录案例
  • c++(对象赋值与拷贝构造函数)

    对象赋值 同一个类的对象之间可以相互赋值 默认情况下 进行的是对象成员之间的复制 也称为 按位复制 或 浅复制 当类的数据成员中没有指针类型的变量时 直接对两个对象进行赋值没有问题 但是一旦类的数据成员含有指针变量 那么直接对这两个对象进行
  • MySQL常用基础 - 小白必看(二)

    MySQL数据库基本操作 一 DDL 概念 是一个数据定义语言 该语言部分包括 1 对数据库的常用操作 创建数据库 1 create database 数据库名 直接删除 2 create database if not exists 数据
  • 《effective java》中关于解决构造函数/方法签名包含大量参数的解决方法

    针对构造方法 重叠构造器模式 重叠构造器模式是一种编程中的反模式 指的是一个类有多个构造函数 每个构造函数都有不同数量的参数 从而可以根据不同的情况创建对象 这种方式会导致代码可读性和可维护性降低 因为构造函数过多 参数顺序容易混淆 Jav
  • 使用 Composer 安装 JWT 失败错误 The "https://packagist.org/packages.json" file could not be downloaded 解决方案

    错误信息 The https packagist laravel china org packages json file could not be downloaded SSL operation failed with code 1 O
  • Redis3.0集群方案分析

    在Redis3 0集群出来之前 大家都对作者antirez寄予厚望 因为Redis从来没有让我们失望过 现在Redis3 0集群出来了 网上出了很多评论文章 都说他的功能多么强大 包括下面这张图是彻底把我欺骗了 等到我把Redis3 0客户
  • Qmake VS Cmake 对比讲解

    用 cmake 构建Qt工程 对比qmake进行学习 cmake vs qmake qmake 是为 Qt 量身打造的 使用起来非常方便 cmake 使用上不如qmake简单直接 但复杂换来的是强大的功能 内置的 out of source