cmake常用命令

目錄:


常用指令

ADD_DEFINITIONS

向 C/C++編譯器添加-D 定義,比如:
ADD_DEFINITIONS(-DENABLE_DEBUG -DABC),參數(shù)之間用空格分割。
如果你的代碼中定義了#ifdef ENABLE_DEBUG #endif,這個代碼塊就會生效。
如果要添加其他的編譯器開關(guān),可以通過 CMAKE_C_FLAGS 變量和 CMAKE_CXX_FLAGS 變 量設(shè)置。

ADD_DEPENDENCIES

定義 target 依賴的其他 target,確保在編譯本 target 之前,其他的 target 已經(jīng)被構(gòu)建。
ADD_DEPENDENCIES(target-name depend-target1 depend-target2 ...)

ADD_EXECUTABLE

生成可執(zhí)行程序

ADD_LIBRARY

創(chuàng)建庫,動態(tài)和靜態(tài)庫

ADD_SUBDIRECTORY

添加子目錄

ADD_TEST 與 ENABLE_TESTING 指令

ENABLE_TESTING 指令用來控制 Makefile 是否構(gòu)建 test 目標,涉及工程所有目錄。語 法很簡單,沒有任何參數(shù),ENABLE_TESTING(),一般情況這個指令放在工程的主 CMakeLists.txt 中.
ADD_TEST 指令的語法是:
ADD_TEST(testname Exename arg1 arg2 ...)
testname 是自定義的 test 名稱,Exename 可以是構(gòu)建的目標文件也可以是外部腳本等 等。后面連接傳遞給可執(zhí)行文件的參數(shù)。如果沒有在同一個 CMakeLists.txt 中打開 ENABLE_TESTING()指令,任何 ADD_TEST 都是無效的。
比如我們前面的 Helloworld 例子,可以在工程主 CMakeLists.txt 中添加

ADD_TEST(mytest ${PROJECT_BINARY_DIR}/bin/main)
ENABLE_TESTING()

生成Makefile后,就可以運行make test來執(zhí)行測試了。

AUX_SOURCE_DIRECTORY

基本語法是:
AUX_SOURCE_DIRECTORY(dir VARIABLE)
作用是發(fā)現(xiàn)一個目錄下所有的源代碼文件并將列表存儲在一個變量中,這個指令臨時被用來自動構(gòu)建源文件列表。因為目前 cmake 還不能自動發(fā)現(xiàn)新添加的源文件。
比如

AUX_SOURCE_DIRECTORY(. SRC_LIST)
ADD_EXECUTABLE(main ${SRC_LIST})

你也可以通過后面提到的 FOREACH 指令來處理這個 LIST

CMAKE_MINIMUM_REQUIRED

其語法為

CMAKE_MINIMUM_REQUIRED(VERSION versionNumber [FATAL_ERROR]) 

比如CMAKE_MINIMUM_REQUIRED(VERSION 2.5 FATAL_ERROR)
如果 cmake 版本小與 2.5,則出現(xiàn)嚴重錯誤,整個過程中止。

EXEC_PROGRAM

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

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

[RETURN_VALUE <var>]) 用于在指定的目錄運行某個程序,通過 ARGS 添加參數(shù),如果要獲取輸出和返回值,可通過
OUTPUT_VARIABLERETURN_VALUE 分別定義兩個變量.
這個指令可以幫助你在 CMakeLists.txt 處理過程中支持任何命令,比如根據(jù)系統(tǒng)情況去
修改代碼文件等等。
舉個簡單的例子,我們要在 src 目錄執(zhí)行 ls 命令,并把結(jié)果和返回值存下來。
可以直接在 src/CMakeLists.txt 中添加:

EXEC_PROGRAM(ls ARGS "*.c" OUTPUT_VARIABLE LS_OUTPUT RETURN_VALUE
LS_RVALUE)
IF(not LS_RVALUE)
MESSAGE(STATUS "ls result: " ${LS_OUTPUT})
ENDIF(not LS_RVALUE)

在cmake 生成Makefile的過程中,就會執(zhí)行l(wèi)s命令,如果返回0,則說明成功執(zhí)行, 那么就輸出ls *.c的結(jié)果。關(guān)于IF語句,后面的控制指令會提到。

FILE 指令

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

FILE(WRITE filename "message to write"... )  # 寫文件
FILE(APPEND filename "message to write"... ) # 添加內(nèi)容到文件
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]...) # 創(chuàng)建目錄
FILE(RELATIVE_PATH variable directory file) #獲得相對路徑
FILE(TO_CMAKE_PATH path result) 
FILE(TO_NATIVE_PATH path result)

INCLUDE

用來載入 CMakeLists.txt 文件,也用于載入預(yù)定義的 cmake 模塊.

INCLUDE(file1 [OPTIONAL])
INCLUDE(module [OPTIONAL]) 

OPTIONAL 參數(shù)的作用是文件不存在也不會產(chǎn)生錯誤。
你可以指定載入一個文件,如果定義的是一個模塊,那么將在 CMAKE_MODULE_PATH 中搜索這個模塊并載入。載入的內(nèi)容將在處理到 INCLUDE 語句是直接執(zhí)行。

FIND指令

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

FIND_FILE

FIND_FILE(<VAR> name1 path1 path2 ...)
VAR 變量代表找到的文件全路徑,包含文件名

FIND_LIBRARY

FIND_LIBRARY(<VAR> name1 path1 path2 ...)
VAR 變量表示找到的庫全路徑,包含庫文件名

FIND_PATH

FIND_PATH(<VAR> name1 path1 path2 ...)
VAR 變量代表包含這個文件的路徑, 不包含文件名

FIND_PROGRAM

FIND_PROGRAM(<VAR> name1 path1 path2 ...)
VAR 變量代表包含這個程序的全路徑。

FIND_PACKAGE

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

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

FIND_LIBRARY(libX X11 /usr/lib) 
IF(NOT libX)
MESSAGE(FATAL_ERROR “l(fā)ibX not found”) 
ENDIF(NOT libX)

控制指令

IF指令

IF 指令,基本語法為:

IF(expression)
  # THEN section.
  COMMAND1(ARGS ...)
  COMMAND2(ARGS ...)
  ...
ELSE(expression)
  # ELSE section.
  COMMAND1(ARGS ...)
  COMMAND2(ARGS ...)
  ...
ENDIF(expression)

另外一個指令是 ELSEIF,總體把握一個原則,凡是出現(xiàn) IF 的地方一定要有對應(yīng)的
ENDIF.出現(xiàn) ELSEIF 的地方,ENDIF 是可選的。

IF(var),如果變量不是:空,0,N, NO, OFF, FALSE, NOTFOUND或 <var>_NOTFOUND 時,表達式為真。
IF(NOT var ),與上述條件相反。
IF(var1 AND var2),當兩個變量都為真是為真。
IF(var1 OR var2),當兩個變量其中一個為真時為真。
IF(COMMAND cmd),當給定的cmd確實是命令并可以調(diào)用是為真。
IF(EXISTS dir)或者IF(EXISTS file),當目錄名或者文件名存在時為真。
IF(file1 IS_NEWER_THAN file2),當file1比file2新,或者file1/file2其 中有一個不存在時為真,文件名請使用完整路徑。
IF(IS_DIRECTORY dirname),當dirname是目錄時,為真。
IF(variable MATCHES regex)
IF(string MATCHES regex) 當給定的變量或者字符串能夠匹配正則表達式 regex 時為真。比如: 
IF("hello" MATCHES "ell")
MESSAGE("true")
ENDIF("hello" MATCHES "ell")

IF(variable LESS number) 
IF(string LESS number) 
IF(variable GREATER number) 
IF(string GREATER number) 
IF(variable EQUAL number) 
IF(string EQUAL number)
數(shù)字比較表達式

IF(variable STRLESS string)
IF(string STRLESS string)
IF(variable STRGREATER string)
IF(string STRGREATER string)
IF(variable STREQUAL string)
IF(string STREQUAL string) 
按照字母序的排列進行比較.

IF(DEFINED variable),如果變量被定義,為真。

一個小例子,用來判斷平臺差異:

IF(WIN32)
    MESSAGE(STATUS “This is windows.”) #作一些 Windows 相關(guān)的操作
ELSE(WIN32)
    MESSAGE(STATUS “This is not windows”) #作一些非 Windows 相關(guān)的操作
ENDIF(WIN32)

上述代碼用來控制在不同的平臺進行不同的控制,但是,閱讀起來卻并不是那么舒服, ELSE(WIN32)之類的語句很容易引起歧義。
這就用到了我們在“常用變量”一節(jié)提到的 CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS開關(guān)。
可以SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)這時候就可以寫成:

IF(WIN32)
ELSE()
ENDIF()

如果配合 ELSEIF 使用,可能的寫法是這樣:

IF(WIN32)
#do something related to WIN32 ELSEIF(UNIX)
#do something related to UNIX
ELSEIF(APPLE)
#do something related to APPLE
ENDIF(WIN32)

WHILE指令

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

其真假判斷條件可以參考 IF 指令。

FOREACH

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

1,列表

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

像我們前面使用的 AUX_SOURCE_DIRECTORY 的例子

AUX_SOURCE_DIRECTORY(. SRC_LIST) 
FOREACH(F ${SRC_LIST})
     MESSAGE(${F})
ENDFOREACH(F)

2,范圍

FOREACH(loop_var RANGE total) 
ENDFOREACH(loop_var)

從 0 到 total 以1為步進
舉例如下:

FOREACH(VAR RANGE 10) 
    MESSAGE(${VAR}) 
ENDFOREACH(VAR)

最終得到的輸出是:
0 1 2 3 4 5 6 7 8 9 10

3, 范圍和步進

FOREACH(loop_var RANGE start stop [step]) 
ENDFOREACH(loop_var)

從 start 開始到 stop 結(jié)束,以 step 為步進, 舉例如下

FOREACH(A RANGE 5 15 3) 
  MESSAGE(${A}) 
ENDFOREACH(A) 

最終得到的結(jié)果是:
5 8 11 14
這個指令需要注意的是,知道遇到 ENDFOREACH 指令,整個語句塊才會得到真正的執(zhí)行。

RF:
cmake practice 中文版

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容