Qt構建cmake工程方法總結


由於工作需要,最近打算統一將所有C/C++項目都改成使用cmake編譯。傳統后台業務問題不大,但是有些牽涉到跨平台的Qt項目還是折騰了一陣。下面對這段時間的收獲做一個總結,也希望幫助看到本文的朋友少走彎路。特此聲明,以下配置均為Qt5.6.3 MinGW 4.9.2 32位版本。

1. 基本配置項

1.1 moc ui和rcc編譯開關

SET(CMAKE_AUTOMOC ON)
SET(CMAKE_AUTOUIC ON)
SET(CMAKE_AUTORCC ON)

1.2 啟用C++11標准

* 如果在.h文件中直接對參數初始化或使用了nullptr等,請務必配置這一項

SET(CMAKE_CXX_STANDARD 11)

1.3 包含所有.h文件

* 有些只編寫了.h文件,例如常量聲明,結構體聲明等,請務必配置這一項

SET(CMAKE_INCLUDE_CURRENT_DIR ON)

1.4 查找Qt模塊

* 首先是CMAKE_PREFIX_PATH,對應各個模塊的cmake文件路徑,其次FIND_PACKAGE才能生效

SET(CMAKE_PREFIX_PATH <PREFIX_PATH>/lib/cmake)
FIND_PACKAGE(Qt5 COMPONENTS Core Xml Sql Gui Widgets REQUIRED)

 1.5 引入外部頭文件和動態鏈接庫

* 我習慣在src的同級目錄使用include和lib路徑來保存依賴,這樣讓整個系統看起來更整潔

INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/../include)
LINK_DIRECTORIES(${PROJECT_SOURCE_DIR}/../lib)

 1.6 統一配置各目錄層級的.cpp

* 網上有很多做法是每一個目錄編寫獨立的CMakeLists.txt,但是個人感覺沒有單一CMakeLists.txt文件配置方便,特別是如果各個目錄間存在依賴的情況下更容易出錯

AUX_SOURCE_DIRECTORY(./<mod_1> mod_1_src_list)
AUX_SOURCE_DIRECTORY(./<mod_2> mod_2_src_list)
AUX_SOURCE_DIRECTORY(. src_list)

1.7 指定最終編譯產物的輸出路徑 

* 和使用include和lib作為外部依賴路徑類似,我也習慣在src的同級目錄分別創建bin和out用來存放最終的編譯產物

SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/../bin)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/../out)

1.8 區分release和debug生成的動態庫

* 有時候為了方便調試,我們需要讓debug版本的動態以d結尾

SET(CMAKE_DEBUG_POSTFIX d)

1.9 QDebug在release下依然可以輸出函數名和行號

* 主要是為了保證日志數據有效

ADD_DEFINITIONS(-DQT_MESSAGELOGCONTEXT)

 1.10 添加鏈接庫

TARGET_LINK_LIBRARIES(${target} Qt5::Sql Qt5::Gui <lib>)

 1.11 輸出

ADD_EXECUTABLE(${target} ${SRC_LIST})
ADD_LIBRARY(${target} SHARED ${SRC_LIST})

1.12 根據release和debug分目錄數據產物

* 主要是針對動態庫產物的輸出,分不同的目錄更適合大型項目的統編

SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_SOURCE_DIR}/../debug)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/../release)

1.13 添加自定義的宏

* 可以在項目中通過條件編譯的方式選擇不同的配置

OPTION(C_MODE "Use Customize Mode" ON)
IF(C_MODE)
 # 其他指令
ENDIF()

改變代碼的編譯過程

// 在cmakelists.txt中定義
ADD_DEFINITIONS(-DTEST_DEBUG)

// 配置源碼中的條件編譯
#ifdef TEST_DEBUG
...
...
#else 
...
#endif

debug調試

ADD_DEFINITIONS("-Wall -g")

1.14 添加指定文件

* 一般來說,一個.cpp文件都會有一個.h來對應。編譯的時候我們只需要告訴編譯器所有的.cpp文件即可。例如:ADD_EXECUTABLE(sth ${cpp})。但是有時候,我們會定義一些結構體或常量,並將他們集中聲明在一個.h文件里。

FILE(GLOB HEADER_FILES "*.h")
FILE(GLOB SOURCE_FILES "*.cpp")

1.15 安裝與復制

* 當我們需要在編譯完成以后執行copy或install的時候

FILE(COPY ${HEADER_FILES} DESTINATION ${PROJECT_SOURCE_DIR}/../include/${target})

INSTALL(TARGETS mylib
        RUNTIME DESTINATION bin
        LIBRARY DESTINATION lib
        ARCHIVE DESTINATION libstatic)

2. 注意事項

2.1 如果是使用MinGW編譯windows下的動態庫不需要添加導出類的宏

2.2 LINK_DIRECTORIES 指令必須放在ADD_指令前

2.3 對多級目錄的項目使用cmake做統編,每一個層級的編譯應該使用動態庫的方式

2.4 如果你使用的是QtCreator,自定義宏的方式可能不生效,但這並不是cmake的問題

 

3. Windows下如何使用cmake和gcc 

3.1 安裝MinGW Installation Manager和CMake的windows安裝包,安裝gcc編譯工具鏈(mingw32-gcc, mingw32-gcc-g++, mingw32-make ...缺少的依賴可以從MinGW Installation Manager里面安裝)

3.2 配置環境變量

*3.3 mingw32-make.exe 復制后重命名為 cmake.exe

3.4 指定編譯方案:cmake -G   "MinGW Makefiles" . (如果編譯器為vs的話使用"NMake Makefiles")

3.5 make 完成編譯

編譯方法

*3.6 因為mingw已經不再更新,建議使用mingw-w64代替


免責聲明!

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



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