CMake學習

CMake學習


參考自《Cmake Practice --Cjacker》


基本語法規則

變量的引用

${variable}

變量使用${}方式取值,但是在 IF 控制語句中是直接使用變量名。

環境變量的引用

$ENV{NAME}

指令的引用

instruction(param1 param2 ...)

參數使用括弧括起,參數之間使用空格或分號分開。

注意

指令是大小寫無關的,參數和變量是大小寫相關的。

常用變量和常用變量環境

1

  • CMAKE_BINARY_DIR
  • PROJECT_BINARY_DIR
  • <projectname>_BINARY_DIR

這三個變量指代的內容是一致的,如果是 in source 編譯,指得就是工程頂層目錄,如果是 out-of-source 編譯,指的是工程編譯發生的目錄。PROJECT_BINARY_DIR 跟其他指令稍有區別,現在,你可以理解為他們是一致的。

2

  • CMAKE_SOURCE_DIR
  • PROJECT_SOURCE_DIR
  • <projectname>_SOURCE_DIR

這三個變量指代的內容是一致的,不論采用何種編譯方式,都是工程頂層目錄。也就是在 in source 編譯時,他跟 CMAKE_BINARY_DIR 等變量一致。PROJECT_SOURCE_DIR 跟其他指令稍有區別,現在,你可以理解為他們是一致的。

3

  • CMAKE_CURRENT_SOURCE_DIR

指的是當前處理的 CMakeLists.txt 所在的路徑。

4

  • CMAKE_CURRRENT_BINARY_DIR

如果是 in-source 編譯,它跟 CMAKE_CURRENT_SOURCE_DIR 一致,如果是 out-of-source 編譯,他指的是 target 編譯目錄。

使用 ADD_SUBDIRECTORY(src bin)可以更改這個變量的值。

使用 SET(EXECUTABLE_OUTPUT_PATH <新路徑>)并不會對這個變量造成影響,它僅僅修改了最終目標文件存放的路徑。

5

  • CMAKE_CURRENT_LIST_FILE

輸出調用這個變量的 CMakeLists.txt 的完整路徑。

6

  • CMAKE_CURRENT_LIST_LINE

輸出這個變量所在的行。

7

  • CMAKE_MODULE_PATH

這個變量用來定義自己的 cmake 模塊所在的路徑。

8

  • EXECUTABLE_OUTPUT_PATH
  • LIBRARY_OUTPUT_PATH

分別用來重新定義最終結果的存放目錄。

9

  • PROJECT_NAME

返回通過 PROJECT 指令定義的項目名稱。

系統信息

  • CMAKE_MAJOR_VERSION,CMAKE 主版本號,比如 2.4.6 中的 2。
  • CMAKE_MINOR_VERSION,CMAKE 次版本號,比如 2.4.6 中的 4。
  • CMAKE_PATCH_VERSION,CMAKE 補丁等級,比如 2.4.6 中的 6。
  • CMAKE_SYSTEM,系統名稱,比如 Linux-2.6.22。
  • CMAKE_SYSTEM_NAME,不包含版本的系統名,比如 Linux。
  • CMAKE_SYSTEM_VERSION,系統版本,比如 2.6.22。
  • CMAKE_SYSTEM_PROCESSOR,處理器名稱,比如 i686。
  • UNIX,在所有的類 UNIX 平臺為 TRUE,包括 OS X 和 cygwin。
  • WIN32,在所有的 win32 平臺為 TRUE,包括 cygwin。

開關選項

  • CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS

用來控制 IF ELSE 語句的書寫方式。

  • BUILD_SHARED_LIBS

這個開關用來控制默認的庫編譯方式,如果不進行設置,使用 ADD_LIBRARY 并沒有指定庫類型的情況下,默認編譯生成的庫都是靜態庫。

如果 SET(BUILD_SHARED_LIBS ON)后,默認生成的為動態庫。

  • CMAKE_C_FLAGS

設置 C 編譯選項,也可以通過指令 ADD_DEFINITIONS()添加。

  • CMAKE_CXX_FLAGS

設置 C++編譯選項,也可以通過指令 ADD_DEFINITIONS()添加。

基本指令

PROJECT指令語法

PROJECT(projectname [CXX] [C] [Java])

這個指令隱式的定義了兩個 cmake 變量:

  • <projectname>_BINARY_DIR
  • <projectname>_SOURCE_DIR

同時 cmake 系統也幫助我們預定義了 PROJECT_BINARY_DIR 和 PROJECT_SOURCE_DIR變量,他們的值分別跟 <projectname>_BINARY_DIR 與 <projectname>_SOURCE_DIR 一致。

SET指令語法

SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])

SET 指令可以用來顯式的定義變量。

MESSAGE指令語法

MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message to display"...)

這個指令用于向終端輸出用戶定義的信息,包含了三種類型:

  • SEND_ERROR,產生錯誤,生成過程被跳過。
  • STATUS,輸出前綴為"-- "的信息。
  • FATAL_ERROR,立即終止所有 cmake 過程。

ADD_EXECUTABLE指令語法

ADD_EXECUTABLE(executablename sourcelists)

定義了這個工程會生成一個文件名為 executablename 的可執行文件,相關的源文件是 sourcelists 中定義的源文件列表。

ADD_SUBDIRECTORY指令語法

ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

這個指令用于向當前工程添加存放源文件的子目錄,并可以指定中間二進制和目標二進制存放的位置。EXCLUDE_FROM_ALL 參數的含義是將這個目錄從編譯過程中排除,比如工程的 example,可能就需要工程構建完成后,再進入 example 目錄單獨進行構建。

SUBDIRS指令語法

SUBDIRS(dir1 dir2...)

這個指令已經不推薦使用。它可以一次添加多個子目錄,并且即使外部編譯,子目錄體系仍然會被保存。

INSTALL指令語法

INSTALL(TARGETS targets...
    [[ARCHIVE|LIBRARY|RUNTIME] 
    [DESTINATION <dir>]
    [PERMISSIONS permissions...]
    [CONFIGURATIONS
    [Debug|Release|...]]
    [COMPONENT <component>]
    [OPTIONAL]
    ] [...])

ADD_LIBRARY指令語法

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

類型有三種:

  • SHARED,動態庫
  • STATIC,靜態庫
  • MODULE,在使用 dyld 的系統有效,如果不支持 dyld,則被當作 SHARED 對待。

EXCLUDE_FROM_ALL 參數的意思是這個庫不會被默認構建,除非有其他的組件依賴或者手工構建。

SET_TARGET_PROPERTIES指令語法

SET_TARGET_PROPERTIES(target1 target2 ...
            PROPERTIES prop1 value1
            prop2 value2 ...)

這條指令可以用來設置輸出的名稱,對于動態庫,還可以用來指定動態庫版本和 API 版本。

GET_TARGET_PROPERTY指令語法

GET_TARGET_PROPERTY(VAR target property)

LINK_DIRECTORIES指令語法

LINK_DIRECTORIES(directory1 directory2 ...)

這個指令非常簡單,添加非標準的共享庫搜索路徑,比如,在工程內部同時存在共享庫和可執行二進制,在編譯時就需要指定一下這些共享庫的路徑。

TARGET_LINK_LIBRARIES指令語法

TARGET_LINK_LIBRARIES(target library1
            <debug | optimized> library2
            ...)

這個指令可以用來為 target 添加需要鏈接的共享庫,但是同樣可以用于為自己編寫的共享庫添加共享庫鏈接。

CMAKE_INCLUDE_CURRENT_DIR

自動添加 CMAKE_CURRENT_BINARY_DIR 和 CMAKE_CURRENT_SOURCE_DIR 到當前處理的 CMakeLists.txt。相當于在每個 CMakeLists.txt 加入:

INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})

CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE

將工程提供的頭文件目錄始終至于系統頭文件目錄的前面,當你定義的頭文件確實跟系統發生沖突時可以提供一些幫助。

CMAKE_INCLUDE_PATH 和 CMAKE_LIBRARY_PATH

ADD_DEFINITIONS

向 C/C++編譯器添加-D 定義,比如:

ADD_DEFINITIONS(-DENABLE_DEBUG-DABC)

參數之間用空格分割。

如果你的代碼中定義了#ifdef ENABLE_DEBUG #endif,這個代碼塊就會生效。

如果要添加其他的編譯器開關,可以通過 CMAKE_C_FLAGS 變量和 CMAKE_CXX_FLAGS 變量設置。

ADD_DEPENDENCIES

定義 target 依賴的其他 target,確保在編譯本 target 之前,其他的 target 已經被構建。

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

ADD_TEST 與 ENABLE_TESTING

ADD_TEST 指令的語法是:

ADD_TEST(testname Exename arg1 arg2 ...)

testname 是自定義的 test 名稱,Exename 可以是構建的目標文件也可以是外部腳本等等。后面連接傳遞給可執行文件的參數。如果沒有在同一個 CMakeLists.txt 中打開ENABLE_TESTING()指令,任何 ADD_TEST 都是無效的。

ENABLE_TESTING 指令用來控制 Makefile 是否構建 test 目標,涉及工程所有目錄。語法很簡單,沒有任何參數,ENABLE_TESTING(),一般情況這個指令放在工程的主CMakeLists.txt 中。

AUX_SOURCE_DIRECTORY

基本語法是:

AUX_SOURCE_DIRECTORY(dir VARIABLE)

作用是發現一個目錄下所有的源代碼文件并將列表存儲在一個變量中,這個指令臨時被用來自動構建源文件列表。因為目前 cmake 還不能自動發現新添加的源文件。

CMAKE_MINIMUM_REQUIRED

其語法為

CMAKE_MINIMUM_REQUIRED(VERSION versionNumber [FATAL_ERROR])

比如 CMAKE_MINIMUM_REQUIRED(VERSION 2.5 FATAL_ERROR)

如果 cmake 版本小與 2.5,則出現嚴重錯誤,整個過程中止。

EXEC_PROGRAM

在 CMakeLists.txt 處理過程中執行命令,并不會在生成的 Makefile 中執行。具體語法為:

EXEC_PROGRAM(Executable [directory in which to run]
            [ARGS <arguments to executable>]
            [OUTPUT_VARIABLE <var>]
            [RETURN_VALUE <var>])

用于在指定的目錄運行某個程序,通過 ARGS 添加參數,如果要獲取輸出和返回值,可通過OUTPUT_VARIABLE 和 RETURN_VALUE 分別定義兩個變量。

這個指令可以幫助你在 CMakeLists.txt 處理過程中支持任何命令,比如根據系統情況去修改代碼文件等等。

FILE 指令

文件操作指令,基本語法為:

FILE(WRITE filename "message to write"...)
FILE(APPEND filename "message to append"...)
FILE(READ filename variable)
FILE(GLOB variable [RELATIVE path] [globbing expressions]...)
FILE(GLOB_RECURSE variable [RELATIVE path] [globbing expressions]...)
FILE(REMOVE [directory]...)
FILE(REMOVE_RECURSE [directory]...)
FILE(MAKE_DIRECTORY [directory]...)
FILE(RELATIVE_PATH variable directory file)
FILE(TO_CMAKE_PATH path result)
FILE(TO_NATIVE_PATH path result)

INCLUDE 指令

用來載入 CMakeLists.txt 文件,也用于載入預定義的 cmake 模塊。

INCLUDE(file [OPTIONAL])
INCLUDE(module [OPTIONAL])

OPTIONAL 參數的作用是文件不存在也不會產生錯誤。

你可以指定載入一個文件,如果定義的是一個模塊,那么將在 CMAKE_MODULE_PATH 中搜索這個模塊并載入。

載入的內容將在處理到 INCLUDE 語句是直接執行。

FIND_ 指令

FIND_系列指令主要包含一下指令:

FIND_FILE(<VAR> name1 path1 path2 ...)

VAR 變量代表找到的文件全路徑,包含文件名。

FIND_LIBRARY(<VAR> name1 path1 path2 ...)

VAR 變量表示找到的庫全路徑,包含庫文件名。

FIND_PATH(<VAR> name1 path1 path2 ...)

VAR 變量代表包含這個文件的路徑。

FIND_PROGRAM(<VAR> name1 path1 path2 ...)

VAR 變量代表包含這個程序的全路徑。

FIND_PACKAGE(<name> [major.minor] [QUIET] [NO_MODULE]
        [[REQUIRED|COMPONENTS] [componets...]])

用來調用預定義在 CMAKE_MODULE_PATH 下的 Find<name>.cmake 模塊,你也可以自己定義 Find<name>模塊,通過 SET(CMAKE_MODULE_PATH dir)將其放入工程的某個目錄中供工程使用,我們在后面的章節會詳細介紹FIND_PACKAGE 的使用方法和 Find 模塊的編寫。

控制指令

  • IF 指令,基本語法為:
IF(expression)
    # THEN section.
    COMMAND1(ARGS ...)
    COMMAND2(ARGS ...)
    ...
ELSE(expression)
    # ELSE section.
    COMMAND1(ARGS ...)
    COMMAND2(ARGS ...)
    ...
ENDIF(expression)

另外一個指令是 ELSEIF,總體把握一個原則,凡是出現 IF 的地方一定要有對應的ENDIF。出現 ELSEIF 的地方,ENDIF 是可選的。

  • WHILE 指令的語法是:
WHILE(condition)
    COMMAND1(ARGS ...)
    COMMAND2(ARGS ...)
    ...
ENDWHILE(condition)
  • FOREACH

FOREACH 指令的使用方法有三種形式:

1、 列表

FOREACH(loop_var arg1 arg2 ...)
    COMMAND1(ARGS ...)
    COMMAND2(ARGS ...)
    ...
ENDFOREACH(loop_var)

2、 范圍

FOREACH(loop_var RANGE total)
    COMMAND1(ARGS ...)
    COMMAND2(ARGS ...)
    ...
ENDFOREACH(loop_var)

3、范圍和步進

FOREACH(loop_var RANGE start stop [step])
    COMMAND1(ARGS ...)
    COMMAND2(ARGS ...)
    ...
ENDFOREACH(loop_var)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,702評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,615評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,606評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,044評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,826評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,227評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,307評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,447評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,992評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,807評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,001評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,550評論 5 361
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,243評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,667評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,930評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,709評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,996評論 2 374

推薦閱讀更多精彩內容

  • CMake學習 本篇分享一下有關CMake的一些學習心得以及相關使用。 本文目錄如下: [1、CMake介紹] [...
    AlphaGL閱讀 12,276評論 11 79
  • 注:首發地址 1. 前言 當在做 Android NDK 開發時,如果不熟悉用 CMake 來構建,讀不懂 CMa...
    cfanr閱讀 24,478評論 1 53
  • cmake 學習筆記 最近接觸到一些工程上的代碼,都是用cmake來編譯的,每次看著CMakeLists.txt ...
    thinkpp閱讀 8,440評論 0 1
  • 可以設置的變量 使用方式cmake -DCMAKE_INSTALL_PREFIX=yourpath 或在CMAKE...
    趙海洋閱讀 1,388評論 0 3
  • 我是一個愛運動的人,喜歡旅游,喜歡爬山,喜歡跑步。 一有時間,就去旅游,尤其周末的時候,似乎不出門去,總是缺少了什...
    讀寫人家閱讀 647評論 3 4