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)

發佈了36 篇原創文章 · 獲贊 12 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章