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)
- 我的個人主頁:http://www.techping.cn/
- 我的個人站點博客:http://www.techping.cn/blog/wordpress/
- 我的CSDN博客:http://blog.csdn.net/techping
- 我的簡書:http://www.lxweimin.com/users/b2a36e431d5e/timeline
- 我的GitHub:https://github.com/techping
歡迎相互follow~