cmake vs qmake
- qmake 是為 Qt 量身打造的,使用起來(lái)非常方便
- cmake 使用上不如qmake簡(jiǎn)單直接,但復(fù)雜換來(lái)的是強(qiáng)大的功能
如何選擇?
Using CMake to Build Qt Projects 一文中說(shuō):
- 對(duì)簡(jiǎn)單的Qt工程,采用 qmake
- 對(duì)復(fù)雜度超過(guò) qmake 處理能力的,采用 cmake
盡管如此,如果簡(jiǎn)單Qt的工程都不知道怎么用 cmake 構(gòu)建,復(fù)雜的工程,就更不知道如何使用 cmake 了。還是從簡(jiǎn)單的學(xué)起吧
簡(jiǎn)單的 Qt 程序
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
int main(int argc, char** argv)
{
QCoreApplication app(argc, argv);
qDebug()<<"hello qt!";
app.exec();
}
如果不使用構(gòu)建工具,直接調(diào)用編譯器來(lái)編譯的話,只需要類似這樣的一條命令:
g++ main.cpp -Ie:/Qt/4.7.0/include -o main -Le:/Qt/4.7.0/lib -lQtCore4
指定頭文件目錄,以及需要鏈接的庫(kù)
qmake
qmake 需要一個(gè) .pro 文件:
CONFIG += qt
QT -= gui
SOURCES += main.cpp
cmake
cmake 需要一個(gè) 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 來(lái)啟用 Qt4
- 默認(rèn)使用了core 和 gui,故手動(dòng)禁用 QTGUI
- 包含一個(gè)CMake為Qt提供的配置文件,${QT_USE_FILE}變量是一個(gè)文件名
- 添加可執(zhí)行程序目標(biāo)
- 鏈接到 Qt 的庫(kù)
復(fù)雜一點(diǎn)
考慮一個(gè)常規(guī)Qt程序:
- main.cpp
- mainwindows.ui
- mainwindows.h
- mainwindows.cpp
如果手動(dòng)編譯的話:
- mainwindow.ui 需要使用 uic 預(yù)處理
uic mainwindow.ui -o ui_mainwindow.h
- mainwindow.h 需要 moc 預(yù)處理
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 的的話,一個(gè)簡(jiǎn)單的 pro 文件
TARGET = example
TEMPLATE = app
SOURCES += main.cpp mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
HEADERS 中的文件是否需要 moc 進(jìn)行預(yù)處理,qmake 運(yùn)行時(shí)會(huì)根據(jù)其是否含有Q_OBJECT自動(dòng)判斷。
這也是為什么 很多人添加Q_OBJECT宏后不重新運(yùn)行qmake會(huì)出錯(cuò)誤的原因。
cmake
看看相應(yīng)的 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 中,最后一塊鏈接到可執(zhí)行程序
- 需要 uic 的文件,用 QT4_WRAP_UI 處理
Windows
因?yàn)閣indows下鏈接時(shí)分為 console 和 windows 兩個(gè)子系統(tǒng),所以windows下有些問(wèn)題需要特殊處理。
用 qmake 時(shí):
- 默認(rèn)是 windows 子系統(tǒng)
- 可以通過(guò) CONFIG += console 使用 console 子系統(tǒng)
用 cmake 是:
- 默認(rèn)是 console 子系統(tǒng)
- 使用 windows 子系統(tǒng)需要
SET(QT_USE_QTMAIN TRUE)
ADD_EXECUTABLE(example WIN32 main.cpp mainwindow.cpp ${example_MOCS})
前者啟用 qtmain.lib 庫(kù)來(lái)提供windows下的 WinMain 入口函數(shù)。后者鏈接 windows 子系統(tǒng)
再?gòu)?fù)雜一點(diǎn)
- main.cpp
- mainwindows.ui
- mainwindows.h
- mainwindows.cpp
- main.qrc
- main.rc
前面已經(jīng)用到了Qt的 moc 和 uic,這次增加了資源系統(tǒng) 需要用 rcc
rcc main.qrc -o qrc_main.cpp
同時(shí),使用了windows下的資源文件 .rc (比如給程序添加圖標(biāo))
- MVSC 中使用 rc.exe 對(duì) .rc 文件進(jìn)行處理
- 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})
- 對(duì)Qt的資源文件,使用 QT4_ADD_RESOURCES 來(lái)調(diào)用rcc進(jìn)行預(yù)處理
- 對(duì) Windows 資源文件,直接和源文件一樣,添加到列表中即可。只是:
- MinGW 下僅僅這么做還不行,上面的 MinGW 塊用來(lái)修復(fù)這個(gè)問(wèn)題
Debug 與 Release
qmake
使用 qmake 時(shí),可以在 pro 文件內(nèi)分別為兩種模式設(shè)置不同的選項(xiàng)。
使用時(shí),可以直接 make release 或 make debug 來(lái)編譯不同的版本
cmake
不同于 qmake,由于 cmake 采用 out-of-source 方式。故:
- 建立debug release兩目錄,分別在其中執(zhí)行cmake -DCMAKE_BUILD_TYPE=Debug(或Release)
- 需要編譯不同版本時(shí)進(jìn)入不同目錄執(zhí)行make
對(duì)生成 msvc 工程的情況, CMAKE_BUILD_TYPE 不起作用。生成工程后使用IDE自帶的模式選擇。