天天看點

Qt 編譯方式之 cmakeCMake簡介Qmake VS Cmake基本文法規則CMake常用指令CMake常用變量簡單的例子

作者:billy

版權聲明:著作權歸作者所有,商業轉載請聯系作者獲得授權,非商業轉載請注明出處

CMake簡介

CMake是一個跨平台的、開源的建構工具。cmake是makefile的上層工具,它們的目的正是為了産生可移植的makefile,并簡化自己動手寫makefile時的巨大工作量。目前很多開源的項目都可以通過CMake工具來輕松建構工程,例如部落格之前分享的openHMD、hidapi、OSVR-Core等等,代碼的分享者提供源代碼和相應的Cmake配置檔案,使用者就可以非常友善的在自己的電腦上建構相應的工程,進行開發和調試。

Qmake VS Cmake

  • qmake 是為 Qt 量身打造的,使用起來非常友善
  • cmake 使用上不如qmake簡單直接,但複雜換來的是強大的功能
    • 内置的 out-of source 建構(目前QtCreator為qmake也預設啟用了該功能,詳情請搜尋“Qt影子建構”)
    • 為各種平台和場景提供條件編譯
    • 可處理多個可執行檔案情況,和很好配合 QtTest 工作

如何選擇建構方式?

Using CMake to Build Qt Projects 此書中提到:

對簡單的Qt工程,采用 qmake

對複雜度超過 qmake 處理能力的,采用 cmake(例如程式中調用了很多第三方庫)

接下來我們就一起來學習下CMake的文法和常用指令。

基本文法規則

  1. 變量使用 ${} 方式取值,但是在 IF 控制語句 中是直接使用變量名
  2. 指令(參數 1 參數 2…),參數使用括弧括起,參數之間使用空格或分号分開
  3. 指令是大小寫無關的,參數和變量是大小寫相關的,推薦全部使用大寫指令

CMake常用指令

  1. CMAKE_MINIMUM_REQUIRED (VERSION2.6 FATAL_ERROR)

    功能:規定cmake程式的最低版本

    這行指令是可選的,我們可以不寫這句話,但在有些情況下,如果CMakeLists.txt檔案中使用了一些高版本cmake特有的一些指令的時候,就需要加上這樣一行,提醒使用者更新到該版本之後再執行cmake

  2. PROJECT(<Name>)

    功能:用于指定項目的名稱

    這條指令會自動建立兩個變量:

    <projectnam>_SOURCE_DIR(源代碼路徑) 和 <projectname>_BINARY_DIR(二進制檔案儲存路徑)

    cmake系統也幫助我們預定義了 PROJECT_SOURCE_DIR 和 PROJECT_BINARY_DIR 其值與上述對應相等

    PROJECT_SOURCE_DIR 指向的目錄同内部建構相同,仍然是項目目錄

    而 PROJECT_BINARY_DIR 則有所不同,指向<項目目錄>/build目錄

  3. INCLUDE_DIRECTORIES ([AFTER|BEFORE] [SYSTEM] dir1 dir2 …)

    功能:設定頭檔案位置

    向工程添加多個特定的頭檔案搜尋路徑,路徑之間用空格分隔,如果路徑包含空格,可以使用雙引号将它括起來,預設的行為是追加到目前頭檔案搜尋路徑的後面

  4. ADD_LIBRARY(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL] source1 source2 … sourceN)

    功能:添加動态靜态庫

    • 添加一個名為<libname>的庫檔案
    • 指定STATIC, SHARED, MODULE參數來指定要建立的庫的類型, STATIC對應的靜态庫(.a),SHARED對應共享動态庫(.so)
    • [EXCLUDE_FROM_ALL], 如果指定了這一屬性,對應的一些屬性會在目标被建立時被設定(指明此目錄和子目錄中所有的目标,是否應當從預設建構中排除, 子目錄的IDE工程檔案/Makefile将從頂級IDE工程檔案/Makefile中排除)
    • source1 source2 … sourceN用來指定源檔案
  5. ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

    功能:去子目錄中檢視可用的CMakeLists.txt檔案

    如果目前目錄下還有子目錄時可以使用add_subdirectory,子目錄中也需要包含有CMakeLists.txt

    EXCLUDE_FROM_ALL含義:将這個目錄從編譯過程中排除

  6. ADD_EXECUTABLE( [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] [source1] [source2 …])

    功能:添加可執行檔案

    例:ADD_EXECUTABLE(hello ${SRC_LIST})

    定義了這個工程會生成一個檔案名為 hello 的可執行檔案,相關的源檔案是 SRC_LIST 中定義的源檔案清單

    這裡的 hello 和之前的項目名稱沒有任何關系,可以任意定義

  7. ADD_DEPENDENCIES(target-name depend-target1 depend-target2 …)

    功能:用于添加編譯器指令行标志(選項),通常的情況下我們使用其來添加預處理器定義

    讓一個頂層目标依賴于其他的頂層目标,保證某個目标在其他的目标之前被建構

  8. TARGET_LINK_LIBRARIES(<name> lib1 lib2 lib3)

    功能:将若幹庫連結到目标庫檔案

    例如:TARGET_LINK_LIBRARIES(hello log4cpp thrift)

    這句話指定在連結目标檔案的時候需要連結的外部庫,其效果類似gcc的編譯參數“-l”,可以解決外部庫的依賴問題

  9. SET_PROPERTY

    功能:在給定的作用域内設定一個命名的屬性,PROPERTY參數是必須的

set_property(<GLOBAL | 
            DIRECTORY [dir] | 
            TARGET [target ...] | 
            SOURCE [src1 ...] | 
            TEST [test1 ...] | 
            CACHE [entry1 ...]>
            [APPEND] 
            PROPERTY <name> [value ...])
             
第一個參數決定了屬性可以影響的作用域,必須為以下值:
GLOBAL 全局作作用域,不接受名字
DIRECTORY 預設為目前路徑,但是同樣也可以用[dir]指定路徑
TARGET 目标作用,可以是0個或多個已有的目标
SOURCE 源作用域, 可以是0個過多個源檔案
TEST 測試作用域, 可以是0個或多個已有的測試
CACHE 必須指定0個或多個cache中已有的條目
           
  1. SET_DIRECTORY_PROPERTIES(PROPERTIES prop1 value1 prop2 value2)

    功能:設定某個路徑的一種屬性

    prop1 prop2代表屬性,取值為:

    INCLUDE_DIRECTORIES

    LINK_DIRECTORIES

    INCLUDE_REGULAR_EXPRESSION

    ADDITIONAL_MAKE_CLEAN_FILES

  2. MESSAGE([STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR] “message todisplay”…)

    功能:向終端輸出使用者定義的資訊或變量的值

    SEND_ERROR 産生錯誤,生成過程被跳過

    STATUS 輸出字首為—的資訊

    FATAL_ERROR 立即終止所有cmake過程

  3. FIND_LIBRARY(<VAR> name1 [path1 path2 …])

    功能:用于查找庫檔案 name1 的路徑,如果找到則将路徑儲存在 VAR 中(此路徑為一個絕對路徑),如果沒有找到則=結果為 <VAR>-NOTFOUND

  4. FIND_PACKAGE(<Name>)

    功能:找相應庫的子產品

    windows下并不是很重要,但是在Unix下就非常重要了,find_package可以根據cmake内置的.cmake的腳本去找相應的庫的子產品,内建了很多庫的子產品變量,當調用了FIND_PACKAGE之後會有相應的變量生效

  5. SET(VAR [VALUE] [CACHE TYPEDOCSTRING [FORCE]])

    功能:用于設定變量,相當于為變量取别名

    SET(CMAKE_BUILE_TYPE DEBUG) 設定編譯類型debug 或者release,debug 版會生成相關調試資訊,可以使用GDB 進行調試;release不會生成調試資訊

    SET(CMAKE_C_FLAGS_DEBUG “-g -Wall”) 設定編譯器的類型

  6. FILE

    功能:檔案操作指令

# 将message寫入filename檔案中,會覆寫檔案原有内容
file(WRITE filename "message")

# 将message寫入filename檔案中,會追加在檔案末尾
file(APPEND filename "message")

# 從filename檔案中讀取内容并存儲到var變量中,如果指定了numBytes和offset,
# 則從offset處開始最多讀numBytes個位元組,另外如果指定了HEX參數,則内容會以十六進制形式存儲在var變量中
file(READ filename var [LIMIT numBytes] [OFFSET offset] [HEX])

# 重命名檔案
file(RENAME <oldname> <newname>)

# 删除檔案, 等于rm指令
file(REMOVE [file1 ...])

# 遞歸的執行删除檔案指令, 等于rm -r
file(REMOVE_RECURSE [file1 ...])

# 根據指定的url下載下傳檔案
# timeout逾時時間; 下載下傳的狀态會儲存到status中; 下載下傳日志會被儲存到log; sum指定所下載下傳檔案預期的MD5值,如果指定會自動進行比對,如果不一緻,則傳回一個錯誤; SHOW_PROGRESS,進度資訊會以狀态資訊的形式被列印出來
file(DOWNLOAD url file [TIMEOUT timeout] [STATUS status] [LOG log] [EXPECTED_MD5 sum] [SHOW_PROGRESS])

# 建立目錄
file(MAKE_DIRECTORY [dir1 dir2 ...])

# 會把path轉換為以unix的/開頭的cmake風格路徑,儲存在result中
file(TO_CMAKE_PATH path result)

# 它會把cmake風格的路徑轉換為本地路徑風格:windows下用"\",而unix下用"/"
file(TO_NATIVE_PATH path result)

# 将會為所有比對查詢表達式的檔案生成一個檔案list,并将該list存儲進變量variable裡, 如果一個表達式指定了RELATIVE, 傳回的結果将會是相對于給定路徑的相對路徑, 查詢表達式例子: *.cxx, *.vt?
NOTE: 按照官方文檔的說法,不建議使用file的GLOB指令來收集工程的源檔案
file(GLOB variable [RELATIVE path] [globbing expressions]...)
           

CMake常用變量

UNIX 如果為真,表示為 UNIX-like 的系統,包括 AppleOS X 和 CygWin

WIN32 如果為真,表示為 Windows 系統,包括 CygWin

APPLE 如果為真,表示為 Apple 系統

CMAKE_SIZEOF_VOID_P 表示 void* 的大小(例如為 4 或者 8),可以使用其來判斷目前建構為 32 位還是 64 位

CMAKE_CURRENT_LIST_DIR 表示正在處理的CMakeLists.txt 檔案的所在的目錄的絕對路徑(2.8.3 以及以後版本才支援)

CMAKE_ARCHIVE_OUTPUT_DIRECTORY 用于設定 ARCHIVE 目标的輸出路徑

CMAKE_LIBRARY_OUTPUT_DIRECTORY 用于設定 LIBRARY 目标的輸出路徑

CMAKE_RUNTIME_OUTPUT_DIRECTORY 用于設定 RUNTIME 目标的輸出路徑

簡單的例子

Qt 編譯方式之 cmakeCMake簡介Qmake VS Cmake基本文法規則CMake常用指令CMake常用變量簡單的例子

建立一個Qt工程,沒有做任何修改,在項目中添加 CMakeLists.txt 檔案,編寫完成之後按照下圖配置以cmake編譯

Qt 編譯方式之 cmakeCMake簡介Qmake VS Cmake基本文法規則CMake常用指令CMake常用變量簡單的例子

繼續閱讀