用 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM