用CMake 構建Qt 專案

2021-08-18 21:19:36 字數 3743 閱讀 5621

在本文中我們將只關注cmake本身,並且指出如何將它與qt結合起來。首先,我們看乙個簡單但典型的基於cmake的專案。從下面的列表可以看出,這個工程包括一些源**及文字檔案。

$ ls

cmakelists.txt

hellowindow.cpp

hellowindow.h

main.cpp

最基本的,cmakelists.txt檔案將qmake需要使用到的工程檔案替換了。如果需要編譯這個工程,可以建立乙個build目錄,並在其內使用cmake及make來編譯。

$ mkdir build

$ cd build

$ cmake .. && make

建立乙個build目錄的原因是我們想達到」out-of-source」編譯的目的,即我們可以把編譯過程中產生的中間檔案與源**隔離開來。當然,用qmake也可以做到這一點,但是需要做額外的一些步驟,但cmake可以很容易得做到這一點。

cmake 正在編譯乙個基本的專案 

cmake中使用的引數代表指cmakelists.txt檔案所在的目錄。這個cmakelists.txt檔案控制了整個編譯的過程。為了更徹底地理解它,我們用以下這個圖來看看整個編譯的流程。下面這張圖表明使用者編寫的檔案(源**,標頭檔案,.ui檔案,.qrc檔案)在編譯過程中是如何被qt的工具進行處理,並整合到整個編譯流程中的。因為qmake是用於處理這個流程的,它隱藏了這個流程中的很多細節。

qt編譯系統

當使用cmake的時候,這些中間過程必須要顯式地進行處理。這也就是說,在標頭檔案中如果有使用q_object巨集的話,則這個檔案需要被moc進行處理,.ui檔案也必須要由uic處理,.qrc檔案需要由rcc程式處理。

在上面的例子中,我們簡化了這些步驟,我們只需要處理包含了q_object巨集的標頭檔案。也就是說,我們需要用moc對helloworld.h檔案進行處理。與此工程相對應的cmakelists.txt檔案如下:

project(helloworld)

find_package(qt4 required)

上述兩句的意思指定義此工程為helloworld,並且讓cmake自動去尋找qt4,下面,我們需要用set命令把需要定義的標頭檔案與cpp檔案等串起來. 

set(helloworld_sources main.cpp hellowindow.cpp)

set(helloworld_headers hellowindow.h)

為了呼叫moc程式,需要使用 qt4_wrap_cpp巨集。 定義如下: 

qt4_wrap_cpp(helloworld_headers_moc $)

這一步的作用實際上與在命令列中使用

$moc –o helloworld_moc.h helloworld.h

是類似的,上述的helloworld_headers_moc只是為了後續使用而取的名字。

為了編譯這個qt工程,需要包含qt的庫檔案目錄並且包含一些定義:

include($)

add_definitions($)

最後,cmake需要知道最終應用程式的名字以及加入鏈結庫來生成它。這個在cmake中可以很方便地使用add_executable 和     target_link_libraries. 因此,在cmakelists.txt中加入如下:

add_executable(helloworld $ 

$)target_link_libraries(helloworld $)

重新回顧上述cmakelists.txt, 你會覺得相對於qmake來說,要多寫一些配置,這實際上已經大大簡化了,因為cmake並不是如qmake一樣專為qt而使用。

2.加入更多的qt元素

從上面的最基本的例子繼續,我們再在加入資源檔案及ui檔案。在上述的例子中增加了hellowindow.ui及images.qrc檔案,相應的cmakelists.txt增加以下的內容:

set(helloworld_sources main.cpp hellowindow.cpp)

set(helloworld_headers hellowindow.h)

set(helloworld_forms hellowindow.ui)

set(helloworld_resources images.qrc)

.qrc檔案及.ui檔案通過巨集 qt4_wrap_ui 和 qt4_add_resources進行處理。這些巨集與qt4_wrap_cpp的巨集的作用是一樣的,實際上都是在編譯過程中呼叫相應的應用程式對其進行處理。即針對.qrc檔案通過呼叫rcc程式對其處理,對.ui檔案通過呼叫uic程式對其處理。對cmakelists.txt增加內容如下:

qt4_wrap_cpp(helloworld_headers_moc $)

qt4_wrap_ui(helloworld_forms_headers $)

qt4_add_resources(helloworld_resources_rcc $)

同樣地,這些中間生成的檔案在最終生成應用程式的時候需要用到,因此,add_executable修改如下: 

add_executable(helloworld $ 

$ $ 

$)在編譯之前,還有乙個問題要處理,如上所述,我們要進行的是在源**之外 的編譯,因此,這些生成的中間檔案都會在build目錄下,這樣的話,編譯器則不能定位由uic程式產生的諸如ui_hellowindow.h等檔案。所以,我們需要把build目錄新增到包含目錄中,如下: 

include_directories($)

加入這一行之後,所以中間生成的檔案都會被包含在include路徑中。 

3.更多qt 模組

目前為止,我們均只依賴於qtcore和qtgui模組。如果需要引用其它模組,cmake需要顯式地開啟它。通過set命令將特定的模組設定為true則可。例如,如果要在程式中使用opengl的支援,則需要在cmakelists.txt中使用如下這一行:

set(qt_use_qtopengl true)

其它較常用的模組包括:

qt_use_qtnetwork

qt_use_qtopengl

qt_use_qtsql

qt_use_qtxml

qt_use_qtsvg

qt_use_qttest

qt_use_qtdbus

qt_use_qtscript

qt_use_qtwebkit

qt_use_qtxmlpatterns

qt_use_phonon

此外,還有其它的巨集可以用,具體地可參見cmake/share/modules/findqt4.cmake 

4.獲益與複雜性的平衡

如上可以看到,使用cmake並不如qmake輕鬆,但是cmake提供了更多的功能。最顯著的獲益是cmake支援」out-of-source」編譯,這可能會更改使用習慣,但是這樣做使得對源**的版本跟蹤變得更加方便。

同樣地,使用cmake的另外乙個好處是不只是針對qt,cmake使得新增額外的庫的支援變得更加容易,比如,針對不同的平台,鏈結不同的庫或者是將qt與其它庫一起使用以構建較大型的程式,此時cmake的優勢開始顯現。

其它的強大的功能是具有了在一次設定的過程中產生不同版本的應用程式的能力,也就是說,針對乙個單一的配置檔案,可以產生多種不同的編譯過程。 

cmake與qmake之間的選擇其實很簡單,對於只使用qt的專案,qmake是個很好的先把。而當編譯的需求超過了qmake的處理能力或者使用qmake配置變得很複雜時,cmake可以替代它

用CMake 構建Qt 專案

譯 用cmake構建qt專案 qtsdk中已經包含了qmake用於處理跨平台的編譯問題。然而,還存在其它編譯工具,比如autotools,scons和cmake.這些工具滿足不同的需求,比如外部依賴。當kde專案從使用qt3公升級到使用qt4時,整個專案將構建工具從autotools轉而使用cmak...

cmake構建qt工程

如何選擇?using cmake to build qt projects 一文中說 儘管如此,如果簡單qt的工程都不知道怎麼用 cmake 構建,複雜的工程,就更不知道如何使用 cmake 了。還是從簡單的學起吧 include include qdebug int main int argc,c...

CMake構建CUDA專案

在大量的c c 的專案中都使用cmake來進行專案的管理,而cuda又是很流行的平行計算庫,利用cmake來構建cuda專案就顯得很有必要了,而且專案中使用的cmakelists.txt基本框架一致的,下面簡單地記載一下這種cmakelists.txt檔案的內容 cmakelists.txt for...