CMake
M也就是说,从同一个抽象规则出发,它为各个编译器定制工程文件。5. cmake是抽象层次更高的项目管理工具,cmake命令执行的CMakeLists.txt文件6. qmake是Qt专用的项目管理工具,对应的工程文件是.pro,在Linux下面它也会生成Makefile,当然,在命令行下才会需要手动执行qmake,完全可以在qtcreator这个专用的IDE下面打开.pro文件,使用qmake命令的繁琐细节不用你管了。总结一下,make用来执行Makefile,cmake用来执行CMakeLists.txt,qmake用来处理.pro工程文件。Makefile的抽象层次最低,cmake和qmake在Linux等环境下最后还是会生成一个Makefile。cmake和qmake支持跨平台,cmake的做法是生成指定编译器的工程文件,而qmake完全自成体系。具体使用时,Linux下,小工程可手动写Makefile,大工程用automake来帮你生成Makefile,要想跨平台,就用cmake。如果GUI用了Qt,也可以用qmake+.pro来管理工程,这也是跨平台的。当然,cmake中也有针对Qt的一些规则,并代替qmake帮你将qt相关的命令整理好了。另外,需要指出的是,make和cmake主要命令只有一条,make用于处理Makefile,cmake用来转译CMakeLists.txt,而qmake是一个体系,用于支撑一个编程环境,它还包含除qmake之外的其它多条命令(比如uic,rcc,moc)。上个简图,其中cl表示visual studio的编译器,gcc表示linux下的编译器
作者:辉常哥
链接:https://www.zhihu.com/question/27455963/answer/89770919
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
gcc是GNU Compiler Collection(就是GNU编译器套件),也可以简单认为是编译器,它可以编译很多种编程语言(括C、C++、Objective-C、Fortran、Java等等)。
当你的程序只有一个源文件时,直接就可以用gcc命令编译它。
但是当你的程序包含很多个源文件时,用gcc命令逐个去编译时,你就很容易混乱而且工作量大
所以出现了make工具make工具可以看成是一个智能的批处理工具,它本身并没有编译和链接的功能,而是用类似于批处理的方式—通过调用makefile文件中用户指定的命令来进行编译和链接的。
makefile是什么?简单的说就像一首歌的乐谱,make工具就像指挥家,指挥家根据乐谱指挥整个乐团怎么样演奏,make工具就根据makefile中的命令进行编译和链接的。
makefile命令中就包含了调用gcc(也可以是别的编译器)去编译某个源文件的命令。
makefile在一些简单的工程完全可以人工手下,但是当工程非常大的时候,手写makefile也是非常麻烦的,如果换了个平台makefile又要重新修改。
这时候就出现了Cmake这个工具,cmake就可以更加简单的生成makefile文件给上面那个make用。当然cmake还有其他功能,就是可以跨平台生成对应平台能用的makefile,你不用再自己去修改了。
可是cmake根据什么生成makefile呢?它又要根据一个叫CMakeLists.txt文件(学名:组态档)去生成makefile。
到最后CMakeLists.txt文件谁写啊?亲,是你自己手写的。
接着是qmake,qmake是什么,先说一下Qt这个东西。Qt是跨平台C++图形用户界面应用程序开发框架。它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器。简单的说就是C++的第三方库,使用这个库你可以很容易生成windows,Linux,MAC os等等平台的图形界面。现在的Qt还包含了开发各种软件一般需要用到的功能模块(网络,数据库,XML,多线程啊等等),比你直接用C++(只带标准内裤那种)要方便和简单。
你可以用Qt简简单单就实现非常复杂的功能,是因为Qt对C++进行了扩展,你写一行代码,Qt在背后帮你写了几百上千行,而这些多出来的代码就是靠Qt专有的moc编译器(The Meta-Object Compiler)和uic编译器(User Interface Complier)来重新翻译你那一行代码。问题来了,你在进行程序编译前就必须先调用moc和uic对Qt源文件进行预处理,然后再调用编译器进行编译。上面说的那种普通makefile文件是不适用的,它没办法对qt源文件进行预处理。所以qmake就产生了。
qmake工具就是Qt公司制造出来,用来生成Qt 专用makefile文件,这种makefile文件就能自动智能调用moc和uic对源程序进行预处理和编译。qmake当然必须也是跨平台的,跟cmake一样能对应各种平台生成对应makefile文件。
qmake是根据Qt 工程文件(.pro)来生成对应的makefile的。工程文件(.pro)相对来说比较简单,一般工程你都可以自己手写,但是一般都是由Qt的开发环境 Qt Creator自动生成的,你还是只需要按下那个邪恶三角形就完事了。
还没有完,由于qmake很简单很好用又支持跨平台,而且是可以独立于它的IDE,所以你也可以用在非Qt工程上面,照样可以生成普通的makefile,只要在pro文件中加入CONFIG -= qt 就可以了。
这样qmake和cmake有什么区别? 不好意思,cmake也是同样支持Qt程序的,cmake也能生成针对qt 程序的那种特殊makefile, 只是cmake的CMakeLists.txt 写起来相对与qmake的pro文件复杂点。 qmake 是为 Qt 量身打造的,使用起来非常方便,但是cmake功能比qmake强大。 一般的Qt工程你就直接使用qmake就可以了,cmake的强大功能一般人是用不到的。 当你的工程非常大的时候,又有qt部分的子工程,又有其他语言的部分子工程,据说用cmake会 方便,我也没试过。
Qmake VS Cmake
2012年07月27日 09:36:23 vbskj 阅读数:11564 标签: qtwindowsincludecompilerbuildresources 更多
个人分类: 开源软件
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 了。还是从简单的学起吧
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
intmain(intargc,char**argv)
{
QCoreApplicationapp(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 需要一个 .pro 文件:
CONFIG += qt
QT -= gui
SOURCES += main.cpp
因为我们需要 Qt的库和头文件,所以需要 CONFIG += qt 。
这是默认项,可直接去掉该行
启用qt后,可以通过 QT -= gui 来进一步细调我们需要的模块
默认是 core gui。我们不需要gui模块,故去掉。
cmake 需要一个 CMakeLists.txt 文件:
PROJECT(example)
FIND_PACKAGE(Qt4REQUIRED)
SET(QT_DONT_USE_QTGUITRUE)
INCLUDE(${QT_USE_FILE})
ADD_EXECUTABLE(examplemain.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 的的话,一个简单的 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 的 CMakeLists.txt 文件
PROJECT(example)
CMAKE_MINIMUM_REQUIRED(VERSION2.6)
FIND_PACKAGE(Qt4REQUIRED)
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(examplemain.cppmainwindow.cpp${example_MOCS})
TARGET_LINK_LIBRARIES(example${QT_LIBRARIES})
需要 moc 的文件,用 QT4_WRAP_CPP 处理
生成的文件放入变量 example_MOCS 中,最后一块链接到可执行程序
需要 uic 的文件,用 QT4_WRAP_UI 处理
因为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 文件
TARGET = example
TEMPLATE = lib
HEADERS = mainwindow.h widget.h
SOURCES = main.cpp widget.cpp mainwindow.cpp
RESOURCES = main.qrc
RC_FILE = main.rc
PROJECT(example)
CMAKE_MINIMUM_REQUIRED(VERSION2.6)
FIND_PACKAGE(Qt4REQUIRED)
SET(QT_USE_QTMAINTRUE)
INCLUDE(${QT_USE_FILE})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
if(MINGW)
set(CMAKE_RC_COMPILER_INITwindres)
ENABLE_LANGUAGE(RC)
SET(CMAKE_RC_COMPILE_OBJECT
"<CMAKE_RC_COMPILER> <FLAGS> -O coff <DEFINES> -i <SOURCE> -o <OBJECT>")
endif(MINGW)
SET(example_SRCSmain.cppmainwindow.cppwidget.cppres/main.rc)
SET(example_MOC_SRCSmainwindow.hwidget.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(exampleWIN32main.cppmainwindow.cpp${example_SRCS})
TARGET_LINK_LIBRARIES(example${QT_LIBRARIES})
对Qt的资源文件,使用 QT4_ADD_RESOURCES 来调用rcc进行预处理
对 Windows 资源文件,直接和源文件一样,添加到列表中即可。只是:
MinGW 下仅仅这么做还不行,上面的 MinGW 块用来修复这个问题
使用 qmake 时,可以在 pro 文件内分别为两种模式设置不同的选项。
使用时,可以直接 make release 或 make debug 来编译不同的版本
不同于 qmake,由于 cmake 采用 out-of-source 方式。故:
建立debug release两目录,分别在其中执行cmake -DCMAKE_BUILD_TYPE=Debug(或Release)
需要编译不同版本时进入不同目录执行make
对生成 msvc 工程的情况, CMAKE_BUILD_TYPE 不起作用。生成工程后使用IDE自带的模式选择。
它允许开发人员以简单的可移植文本文件格式指定生成参数。然后,CMake 使用此文件为本机开发工具(包括Microsoft Visual Studio 、 Apple's Xcode)生成项目文件,以及unix、linux、nmake 和 borland各种类型的Makefiles文件。CMake处理构建软件的困难方面,如跨平台构建、系统内省以及用户自定义生产,使用户能够轻松地为复杂的硬件和软件系统量身定制构建。
对于任何项目,特别是跨平台项目,一般需要一个统一的构建系统。许多项目都带有UNIX makefile和Microsoft Visual Studio工作区。这要求开发人员不断尝试保持两个构建系统的最新和一致。要将其他生成系统(如:Bordand和Xcode)作为目标,需要更多的自定义文件副本,从而造成更大的问题。如果你尝试支持可选组件 (如系统上有 libjpeg 可用的 jpeg 支持), 则会加剧此问题。cmake 通过将这些不同的操作合并成一个简单易懂的文件格式来解决这一难题。
如果你有许多开发人员在一个项目或多个平台上工作,则该软件不得不构建在多台计算机上。考虑到安装一台现代计算机所涉及的软件和自定义选项的范围很广,有可能两台运行相同操作系统的两台计算机有可能略有不同。CMake为单平台多机开发环境提供了许多好处,其中包括:
1、能够自动搜索正在构建的软件所需的程序、库和头文件。其中包括在搜索程序所需的环境变量以及Windows的注册表设置能力。
2、在源文件树之外的目录树中构建的能力。这是许多UNIX平台上一个非常有用的特点。CMake将这一特点移植到了windows上,允许开发人员删除整个构建目录,而不用担心删除源文件。
3、能够为自动生成的文件创建复杂的自定义命令,例如Qt的moc(qt.nokia.com), Insight Toolkit的CABLE封装生成器。这些命令用于在构建过程中生产的源文件,然后再编译到软件中。
4、在配置时能够选择可选组件。例如,VTk的几个库是可选的,并且CMake为用户提供了一个简单的方法来选择生成的库。
5、能够从简单的文本文件中自动生成工作区和项目。这对于具有许多程序或测试用例的系统来说非常方便,每个程序或测试用例都需要单独的项目文件,通常采用IDE手段创建是一个非常繁琐的过程。
6、能够轻松地在静态和共享构建之间切换。CMake知道如何在支持的所有平台上创建共享库和模块。处理复杂的特定于平台的链接器标志,许多UNIX系统都支持诸如内置的运行时搜索的路径的共享释放器等高级功能。
7、自动生成文件依赖关系,并支持大多数平台上的并行构建。
在开发跨平台软件时,CMake提供了许多附加功能:
1、测试机器字节顺序和其他硬件具体特性的能力。
2、一组在所有平台上工作的构建配置文件。这避免了开发人员必须在项目中以几种不同格式维护相同信息的问题。
3、支持在所有平台上构建共享库。
4、使用系统相关信息配置文件的能力,例如数据文件的位置和其他信息。 CMake可以创建包含诸如数据文件的路径和其他信息的头文件,其格式为#define宏。 系统特定的标志也可以放置在配置的头文件中。 这比编译器的命令行-D选项有优势,因为它允许其他构建系统使用CMake构建的库,而不必指定在构建期间使用的完全相同的命令行选项。
1.1 CMake历史
CMake开发于1999年开始,作为由美国国家医学图书馆资助的Insight Toolkit(ITK,www.itk.org)的一部分。 ITK是一个大型软件项目,可在许多平台上运行,并可与许多其他软件包进行交互。 为了支持这一点,需要一个功能强大但易于使用的构建工具。 过去与大型项目的构建系统合作,开发人员设计了CMake来满足这些需求。 此后,CMake不断增长并受到广泛的喜爱,许多项目和开发人员采用它的易用性和灵活性。 自1999年以来,CMake一直处于积极的发展之中,已经成熟,成为广泛构建问题的经过验证的解决方案。 最明显的例子就是成功应用了CMake作为K桌面环境(KDE)的构建系统,可以说是现有的最大的开源软件项目。
CMake最近增加的其中之一是以CTest的形式包含软件测试支持。 测试软件的一部分过程涉及构建软件,可能安装软件,并确定软件的哪些部分适用于当前系统。 这使得CTest成为CMake的逻辑扩展,因为它已经拥有大部分信息。 类似地,一个新的CMake功能是CPack,它旨在支持软件的跨平台分发。 它为您的软件创建本机安装提供了跨平台的方法,利用现有的流行软件包,如NSIS,RPM,Cygwin和PackageMaker。
其他最近添加到 cmake 包括支持苹果的 xcode ide 和支持微软的 visual studio 10。使用 cmake, 一旦您编写了输入文件, 您就可以获得对新编译器的支持, 并免费构建系统, 因为对它们的支持是建立在新的 relaeases 中的 cmake, 而不是与您的软件分发有关。另一个最近添加到 cmake 是支持交叉编译到其他操作系统或嵌入式设备。cmake 中的许多命令现在都能正确处理主机系统和目标平台在交叉 compling 时的差异。
1.2 为什么不使用Autoconf?
在开发CMake之前,CMake的作者对现有的一些可用工具有经验。Autoconf与automake结合提供了与CMake相同的功能,但是在Windows平台上使用这些工具需要安装许多其他工具,而这些工具本来不属于Windows系统内。除了需要大量的工具外,autoconf 可能难以使用或扩展, 而且对于一些容易 cmake 的任务来说是不可能的。即使你在系统上运行了 autoconf 及其所需的环境, 它也会生成Makefiles, 迫使用户使用命令行。另一方面, cmake 提供了一个选择, 允许开发人员生成可以直接从 ide 中使用的项目文件, windows 和 xcode 开发人员都习惯于此。
虽然autoconf支持用户制定的选项,但它不支持依赖选项。其中一个选项依赖于某些其他属性或选择。例如,在CMake中,你可以使用用户选项来启用多线程处理,这取决于首先确定用户的系统是否具有多线程支持。CMake提供了一个交互式的用户界面,使用户可以方便地查看可用的选项以及如何设置它们。
对于UNIX用户,CMake还提供了自动依赖生成,而autoconf无法直接完成。CMake的简单输入格式也比Makefile.in和configure.in文件的最和更容易阅读和维护。CMake具有记忆和链接库依赖信息的能力,这在autoconf/automake中也是没有等价性的。
1.3为什么不使用JAM,qmake,SCons,or ANT?
其他工具,如:ANT, qmake, SCons 以及 JAM分别采用不同的方法来解决这些问题。他们帮助我们构建CMake。在这四个工具中,qmake与CMake最相识,但是它缺少CMake提供的大量的系统询问。qmake的输入格式与传统的Makefile更为密切相关。ANT,JAM和SCons也是跨平台的,但是它们不支持生成本地项目文件。ANT使用XML、JAM使用自己的语言,SCons使用python来摆脱传统的面向文件的输入。许多这些工具直接运行编译器,而不是让系统构建程序执行该任务。许多这些工具都需要其它工具,如python、java的安装才能工作。
1.4为什么不自己写脚本?
一些项目使用现有的脚本语言(如Perl或Python)来配置构建过程。 尽管类似的功能可以通过这样的系统来实现,但过度使用工具可以使构建过程更像复活节彩蛋,而不是简单易用的构建系统。 在构建软件包时,用户被迫找到并安装版本4.3.2,并且3.2.4之前甚至可以启动构建过程。 为了避免这个问题,决定使用CMake不需要比用于构建的软件更多的工具。 至少使用CMake需要一个C编译器,该编译器的本机构建工具和一个CMake可执行文件,CMake是用C ++编写的,只需要一个C ++编译器来构建并且预编译的二进制文件可用于大多数系统。 脚本自己也通常意味着您不会生成本机Xcode或Visual Studio工作区,使Mac和Windows构建有限。
1.5 CMake可以在哪些平台上运行?
CMake可以在各种平台上运行,包括Microsoft Windows,Apple Mac OS X以及大多数UNIX或类UNIX平台。 在撰写本书时,CMake在以下平台上进行了夜间测试:Windows 98/2000 / XP / Vista / 7,AIX,HPUX,IPIX,Linux,Mac OS X,Solaris,OSF,QNX,CYGWIN,MinGW ,和FreeBSD。 您可以查看www.cmake.org获取当前测试平台列表。
同样,CMake支持大多数常见的编译器。 它支持所有CMake支持的平台上的GNU编译器。 其他测试编译器包括Visual Studio 6,10,Intel C,SGI CC,Mips Pro,Borland,Sun CC和HP aCC。 CMake应该适用于开箱即用的大多数UNIX样式编译器。