cmake_minimum_required (VERSION 2.8)
cmake_minimum_required用於規定cmake程序的最低版本,可選。若是CMakeLists.txt文件中使用了高版本cmake特有的一些命令時,就須要使用cmake_minimum_required對CMake進行版本限制,提醒用戶升級到相應版本後再執行cmake。node
project(project_name)
project用於指定項目的名稱。項目最終編譯生成的可執行文件並不必定是項目名稱,由另外一條命令肯定。
在cmake中有兩個預約義變量:projectname_BINARY_DIR以及projectname_SOURCE_DIR,同時cmake還預約義了PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR變量。內部編譯狀況下,projectname_BINARY_DIR與PROJECT_BINARY_DIR相同;外部編譯狀況下,PROJECT_BINARY_DIR指向build構建目錄。工程實踐中,推薦使用PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR變量,即便項目名稱發生變化也不會影響CMakeLists.txt文件。ios
經過執行cmake生成MakeFile文件,執行make進行編譯安裝,其方法以下:
方法一(內部構建):
在工程CMakeLists.txt所在目錄下執行:
cmake .
make
方法二(外部構建):
在工程CMakeLists.txt所在目錄下執行:
mkdir build
cd build
cmake ../
make
兩種方法最大的不一樣在於執行cmake和make的工做路徑不一樣。第一種方法中,cmake生成的全部中間文件和可執行文件都會存放在項目目錄中;而第二種方法中,中間文件和可執行文件都將存放在build目錄中,避免了源代碼被污染,第二中方法的build目錄能夠建立在任意目錄下,只須要在執行cmake時指定工程的CMakeLists.txt目錄便可。因爲第二種方法的生成、編譯和安裝是發生在不一樣於項目目錄的其它目錄中,所以第二種方法稱爲外部構建。
CMake官方推薦使用外部構建方法,能夠避免源碼被污染。c++
add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
add_subdirectory指令用於向當前工程添加存放源文件的子目錄,並能夠指定中間二進制和目標二進制存放的位置。EXCLUDE_FROM_ALL參數的含義是將相應目錄從編譯過程當中排除。如工程的example目錄可能須要工程構建完成後再進入example目錄單獨進行構建。正則表達式
aux_source_directory(dir variable)
aux_source_directory用於蒐集在指定目錄下全部的源文件的文件名(不包括頭文件),將輸出結果列表儲存在指定的變量中。aux_source_directory不會對目錄下的子目錄進行遞歸調用。
aux_source_directory能夠很方便的爲一個庫或可執行目標獲取源文件的清單,但aux_source_directory的缺點在於,若是CMakeLists.txt中使用了aux_source_directory,那麼CMake將不能生成一個能夠感知新的源文件什麼時候被加進來的構建系統(即新文件的加入並不會致使CMakeLists.txt過期,從而不能引發CMake從新運行,開發者能夠手動從新運行CMake來產生一個新的構建系統)。一般,CMake生成的構建系統可以感知什麼時候須要從新運行CMake,由於須要修改CMakeLists.txt來引入一個新的源文件。當源文件僅僅是加到了目錄下,但沒有修改CMakeLists.txt文件,使用者只能手動從新運行CMake來產生一個包含新文件的構建系統。express
設置編譯選項能夠經過add_compile_options命令,也能夠經過set命令修改CMAKE_CXX_FLAGS或CMAKE_C_FLAGS。 add_compile_options命令添加的編譯選項是針對全部編譯器的(包括c和c++編譯器),而set命令設置CMAKE_C_FLAGS或CMAKE_CXX_FLAGS變量則是分別只針對c和c++編譯器的。
#判斷編譯器類型,若是是gcc編譯器,則在編譯選項中加入c++11支持ide
if(CMAKE_COMPILER_IS_GNUCXX) add_compile_options(-std=c++11) message(STATUS "optional:-std=c++11") endif(CMAKE_COMPILER_IS_GNUCXX)
設置C++標準:set(CMAKE_CXX_STANDARD 11)
設置C編譯器:set(CMAKE_C_COMPILER "gcc")
設置C++編譯器:set(CMAKE_CXX_COMPILER "g++")
設置C編譯器編譯選項:set(CMAKE_C_FLAGS「$ {CMAKE_C_FLAGS} -fPIC」)
設置C++編譯器編譯選項:set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
設置可執行文件輸出目錄:SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
函數
設置庫文件輸出目錄:SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
設置Build類型:set(CMAKE_BUILD_TYPE MATCHES "Debug")
Build類型爲Debug, Release, RelWitchDebInfo,RelWitchDebInfo,MinSizeRel。工具
IF (CMAKE_BUILD_TYPE MATCHES "Debug" OR CMAKE_BUILD_TYPE MATCHES "None") MESSAGE(STATUS "CMAKE_BUILD_TYPE is Debug") ELSEIF (CMAKE_BUILD_TYPE MATCHES "Release") MESSAGE(STATUS "CMAKE_BUILD_TYPE is Release") ELSEIF (CMAKE_BUILD_TYPE MATCHES "RelWitchDebInfo") MESSAGE(STATUS "CMAKE_BUILD_TYPE is RelWitchDebInfo") ELSEIF (CMAKE_BUILD_TYPE MATCHES "MinSizeRel") MESSAGE(STATUS "CMAKE_BUILD_TYPE is MinSizeRel") ELSE () MESSAGE(STATUS "unknown CMAKE_BUILD_TYPE = " ${CMAKE_BUILD_TYPE}) ENDIF ()
設置構建庫的類型:set(BUILD_SHARED_LIBS shared)
庫類型爲shared和static
增長編譯選項:oop
add_definitions("-Wall -lpthread -g") if( CMAKE_BUILD_TYPE STREQUAL "Release") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -std=c++11 -fPIC") else() SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -std=c++11 -fPIC")#設置尋找外部庫的cmake參數的 endif() message("*** ${PROJECT_NAME}: Build type:" ${CMAKE_BUILD_TYPE} ${CMAKE_CXX_FLAGS} "***")
find_package(<package> [version] [EXACT] [QUIET] [[REQUIRED|COMPONENTS] [components...]] [NO_POLICY_SCOPE])
QUIET選項將會禁掉包沒有被發現時的警告信息。REQUIRED選項表示若是報沒有找到的話,cmake的過程會終止,並輸出警告信息。
find_package能夠根據cmake內置的.cmake腳本去查找相應庫的模塊,調用find_package成功後,會有相應的變量生成。如調用find_package(Qt5Widgets)後,會生成變量Qt5Widgets_FOUND,Qt5Widgets_INCLUDE_DIRS,而後在CMakeLists.txt裏可使用使用上述變量。
find_package會調用預約義在CMAKE_MODULE_PATH下的 Findname.cmake模塊。能夠本身定義Findname模塊,將其放入工程的某個目錄中,經過 SET(CMAKE_MODULE_PATH dir)設置查找路徑,供工程FIND_PACKAGE使用。開發工具
find_library ( <VAR> name | NAMES name1 [name2 ...] [NAMES_PER_DIR] [HINTS path1 [path2 ... ENV var]] [PATHS path1 [path2 ... ENV var]] [PATH_SUFFIXES suffix1 [suffix2 ...]] [DOC "cache documentation string"] [NO_DEFAULT_PATH] [NO_CMAKE_ENVIRONMENT_PATH] [NO_CMAKE_PATH] [NO_SYSTEM_ENVIRONMENT_PATH] [NO_CMAKE_SYSTEM_PATH] [CMAKE_FIND_ROOT_PATH_BOTH | ONLY_CMAKE_FIND_ROOT_PATH | NO_CMAKE_FIND_ROOT_PATH] )
FIND_LIBRARY(RUNTIME_LIB rt /usr/local/lib NO_DEFAULT_PATH)
cmake會在目錄中查找,若是全部目錄中都沒有,RUNTIME_LIB就會被賦值爲NO_DEFAULT_PATH。
include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])
include_directories用於指定編譯過程當中編譯器搜索頭文件的路徑。 默認狀況下,將指定目錄追加到目錄列表最後。經過使用BEFORE或AFTER能夠指定目錄追加在目錄列表的前面或後面。若是設定SYSTEM選項,編譯器認定爲系統包含目錄。
當項目須要的頭文件不在系統默認的搜索路徑時,須要指定相應頭文件路徑。
link_directories(directory1 directory2 ...)
link_directories用於指定要連接的庫文件的路徑,可選。find_package和find_library指令能夠獲得庫文件的絕對路徑。若是本身寫的動態庫文件放在本身新建的目錄下時,能夠用link_directories指令指定該目錄的路徑以便工程可以找到。
link_libraries(library1 debug | optimized library2 ...)
庫名稱能夠是絕對路徑,庫名,支持多個。
add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] source1 [source2 ...])
ADD_EXECUTABLE(ExcutableName SRC)
ADD_EXECUTABLE定義了工程生成的可執行文件名稱,相關的源文件是 SRC中定義的源文件列表。
能夠經過SET指令從新定義EXECUTABLE_OUTPUT_PATH和 LIBRARY_OUTPUT_PATH變量來指定最終的目標二進制的位置(指最終生成的可執行文件或者最終的共享庫,而不包含編譯生成的中間文件)。
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
add_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] [source1] [source2] [...])
add_library用於將指定的源文件生成庫文件,而後添加到工程中。
name表示庫文件的名字,庫文件會根據命令裏列出的源文件來建立。而STATIC、SHARED和MODULE的做用是指定生成的庫文件的類型。STATIC庫是目標文件的歸檔文件,在連接其它目標的時候使用。SHARED庫會被動態連接(動態連接庫),在運行時會被加載。MODULE庫是一種不會被連接到其它目標中的插件,但可能會在運行時使用dlopen-系列的函數。
target_link_libraries(<target> [item1] [item2] [...] [[debug|optimized|general] <item>] ...)
target_link_libraries用於指定在連接目標文件的時候須要連接的外部庫,能夠解決外部庫的依賴問題。
target是指經過add_executable()和add_library()指令生成已經建立的目標文件。而[item]表示庫文件沒有後綴的名字。默認狀況下,庫依賴項是傳遞的。當target目標連接到另外一個目標時,連接到target目標的庫也會出如今另外一個目標的連接線上。
SET(CMAKE_INSTALL_PREFIX /usr/local)
顯式將CMAKE_INSTALL_PREFIX的值定義爲/usr/local,在外部構建狀況下執行make install命令時,make會將生成的可執行文件拷貝到/usr/local/bin目錄下。
可執行文件的安裝路徑CMAKE_INSTALL_PREFIX也能夠在執行cmake命令的時候指定,cmake參數以下:
cmake -DCMAKE_INSTALL_PREFIX=/usr ..
若是cmake參數和CMakeLists.txt文件中都不指定CMAKE_INSTALL_PREFIX值的話,則默認爲/usr/local。
執行INSTALL命令時須要注意CMAKE_INSTALL_PREFIX參數的值。INSTALL命令形式以下:
INSTALL(TARGETS targets... [[ARCHIVE|LIBRARY|RUNTIME] [DESTINATION < dir >] [PERMISSIONS permissions...] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT < component >] [OPTIONAL] ] [...])
參數TARGETS後跟目標是經過ADD_EXECUTABLE或者ADD_LIBRARY定義的目標文件,多是可執行二進制、動態庫、靜態庫。
DESTINATION定義安裝的路徑,若是路徑以/開頭,那麼是絕對路徑,此時CMAKE_INSTALL_PREFIX將無效。若是但願使用CMAKE_INSTALL_PREFIX來定義安裝路徑,須要寫成相對路徑,即不要以/開頭,安裝路徑就是${CMAKE_INSTALL_PREFIX} /destination定義的路徑
TARGETS指定的目標文件不須要指定路徑,只須要寫上TARGETS名稱就。
非目標文件的可執行程序安裝(如腳本):
INSTALL(PROGRAMS files... DESTINATION < dir > [PERMISSIONS permissions...] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT < component >] [RENAME < name >] [OPTIONAL])
安裝後權限爲755。
安裝一個目錄的命令以下:
INSTALL(DIRECTORY dirs... DESTINATION < dir > [FILE_PERMISSIONS permissions...] [DIRECTORY_PERMISSIONS permissions...] [USE_SOURCE_PERMISSIONS] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT < component >] [[PATTERN < pattern > | REGEX < regex >] [EXCLUDE] [PERMISSIONS permissions...]] [...])
DIRECTORY後鏈接的是所在Source目錄的相對路徑,但務必注意:abc 和 abc/有很大的區別。若是目錄名不以/結尾,那麼目錄將被安裝爲目標路徑下的 abc,若是目錄名以/結尾,表明將目錄中的內容安裝到目標路徑,但不包括目錄自己。
INSTALL(DIRECTORY icons scripts/ DESTINATION share/myproj PATTERN "CVS" EXCLUDE PATTERN "scripts/*" PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ)
將icons目錄安裝到prefix/share/myproj,將scripts/中的內容安裝到prefix/share/myproj,不包含目錄名爲CVS的目錄,對於
scripts/*文件指定權限爲755。<br/>
INSTALL(DIRECTORY doc/ DESTINATION share/doc/crnode)`
message([STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR] "message to display" ...)
(無) = 重要消息
STATUS = 非重要消息
WARNING = CMake警告,會繼續執行
AUTHOR_WARNING = CMake警告(dev),會繼續執行
SEND_ERROR = CMake錯誤,繼續執行,但會跳過生成步驟 FATAL_ERROR = CMake錯誤,終止全部處理過程
操做符是大小寫敏感的。
一元操做符有:EXISTS,COMMAND,DEFINED
二元操做符有:EQUAL,LESS,LESS_EQUAL,GREATER,GREATER_EQUAL,STREQUAL,STRLESS,STRLESS_EQUAL,,STRGREATER,STRGREATER_EQUAL,VERSION_EQUAL,VERSION_LESS,VERSION_LESS_EQUAL,VERSION_GREATER,VERSION_GREATER_EQUAL,MATCHES
邏輯操做符有:NOT,AND,OR
布爾常量值是大小寫敏感的。
true:1,ON,YES,TRUE,Y,非0的值。
false:0,OFF,NO,FALSE,N,IGNORE,NOTFOUND,空字符串」」,以-NOTFOUND結尾的字符串。
if(表達式) # 要執行的命令塊 COMMAND1(ARGS ...) COMMAND2(ARGS ...) elseif(表達式2) # 要執行的命令塊 COMMAND1(ARGS ...) COMMAND2(ARGS ...) else(表達式) # 要執行的命令塊 COMMAND1(ARGS ...) COMMAND2(ARGS ...) endif(表達式)
elseif和else是可選的,能夠有多條elseif ,縮進和空格對語句解析沒有影響。
IF (COMMAND cmd)
若是cmd確實是命令並可調用,爲真
IF (EXISTS dir)
IF (EXISTS file)
若是目錄或文件存在,爲真
IF (file1 IS_NEWER_THAN file2)
當file1比file2新,或file1/file2中有一個不存在時爲真,文件名需使用全路徑
IF (IS_DIRECTORY dir)
當dir是目錄時,爲真
IF (DEFINED var)
若是變量被定義,爲真
IF (var MATCHES regex)
var能夠用var名,也能夠用${var}
IF (string MATCHES regex)
當給定的變量或者字符串可以匹配正則表達式regex時爲真
IF (variable LESS number)
variable小於number時爲真
IF (string LESS number)
string小於number時爲真
IF (variable GREATER number)
variable大於number時爲真
IF (string GREATER number)
string大於number時爲真
IF (variable EQUAL number)
variable等於number時爲真
IF (string EQUAL number)
string等於number時爲真
IF (variable STRLESS string)
variable小於字符串string
IF (string STRLESS string)
字符串string小於字符串string
IF (variable STRGREATER string)
variable大於字符串string
IF (string STRGREATER string)
字符串string大於字符串string
IF (variable STREQUAL string)
Variable等於字符串string
IF (string STREQUAL string)
字符串string等於字符串string
不一樣操做系統平臺的判斷代碼以下:
IF (WIN32) #do something related to WIN32 ELSEIF (UNIX) #do something related to UNIX ELSEIF(APPLE) #do something related to APPLE ENDIF (WIN32)
WHILE(condition) COMMAND1(ARGS ...) COMMAND2(ARGS ...) ... ENDWHILE(condition)
foreach列表語法:
FOREACH(loop_var arg1 arg2 ...) COMMAND1(ARGS ...) COMMAND2(ARGS ...) ... ENDFOREACH(loop_var)
實例以下:
AUX_SOURCE_DIRECTORY(. SRC_LIST) FOREACH(F ${SRC_LIST}) MESSAGE(${F}) ENDFOREACH(F)
foreach範圍語法:
FOREACH(loop_var RANGE total) COMMAND1(ARGS ...) COMMAND2(ARGS ...) ... ENDFOREACH(loop_var)
實例以下:
#從0到total以1爲步進 FOREACH(VAR RANGE 10) MESSAGE(${VAR}) ENDFOREACH(VAR)
foreach範圍和步進語法:
FOREACH(loop_var RANGE start stop [step]) COMMAND1(ARGS ...) COMMAND2(ARGS ...) ... ENDFOREACH(loop_var)
從start開始到stop結束,以step爲步進,直到遇到ENDFOREACH指令,整個語句塊纔會獲得真正的執行。
FOREACH(A RANGE 5 15 3) MESSAGE(${A}) ENDFOREACH(A)
一般,使用set命令定義的變量能從父目錄傳遞到子目錄,但不能在同級目錄間傳遞,所以用set定義的變量沒法共享,須要用set(variable value CACHE INTERNAL docstring )定義變量,把變量加入到CMakeCache.txt,而後各級目錄共享會訪問到變量。variable爲變量名稱,value爲變量的值,docstring爲變量描述,不能爲空。
set_property提供了實現共享變量的方法,但set_property不會將變量寫入CMakeCache.txt,而是寫入內存中。
當用set_property定義的property時,第一個指定做用域(scope)的參數設爲GLOBAL,這個property在cmake運行期間做用域就是全局的。而後其餘目錄下的CMakeLists.txt能夠用get_property來讀取這個property
在opencl目錄的CMakeLists.txt中定義一個名爲INCLUDE_OPENCL_1_2 的global property:set_property(GLOBAL PROPERTY INCLUDE_OPENCL_1_2 "${CMAKE_CURRENT_LIST_DIR}/include/1.2" )
在其它模塊的CMakeLists.txt中讀取property:get_property(INCLUDE_OPENCL GLOBAL PROPERTY "INCLUDE_OPENCL_1_2" )
set_target_properties(target1 target2 ...PROPERTIES prop1 value1 prop2 value2 ...)
set_target_properties指令能夠用來設置輸出的名稱。對於動態庫,還能夠用來指定動態庫版本和API版本。爲了實現動態庫版本號,使用 set_target_properties指令方法以下:set_target_properties (hello PROPERTIES VERSION 1.2 SOVERSION 1)
VERSION指代動態庫版本,SOVERSION指代API版本。
Hello庫包含Hello.cpp、Hello.h兩個文件。
Hello.h文件以下:
#include <iostream> class Hello { public: void Print(); };
Hello.cpp文件以下:
#include "Hello.h" void Hello::Print() { std::cout << "Hello world." << std::endl; }
CMakeLists.txt文件以下:
cmake_minimum_required(VERSION 2.8.9) SET (LIBHELLO_SRC Hello.cpp) # 添加動態庫,關鍵詞爲shared,不須要寫全libhello.so, ADD_LIBRARY (hello SHARED ${LIBHELLO_SRC}) # 添加靜態庫,關鍵詞爲static,不須要寫全libhello_static.a # target不能重名,所以靜態庫的target不一樣與動態庫的target重名,修改成hello_static ADD_LIBRARY (hello_static STATIC ${LIBHELLO_SRC}) # 一般,靜態庫名字跟動態庫名字是一致的,只是擴展名不一樣; # 即:靜態庫名爲 libhello.a; 動態庫名爲libhello.so; # 所以,但願"hello_static"在輸出時,以"hello"的名字顯示 SET_TARGET_PROPERTIES (hello_static PROPERTIES OUTPUT_NAME "hello") GET_TARGET_PROPERTY (OUTPUT_VALUE hello_static OUTPUT_NAME) MESSAGE (STATUS "This is the hello_static OUTPUT_NAME: " ${OUTPUT_VALUE}) # cmake在構建一個新的target時,會嘗試清理掉其它使用target名字的庫, # 所以,在構建libhello.a時,就會清理掉libhello.so. # 爲了不清理問題,好比再次使用SET_TARGET_PROPERTIES定義 CLEAN_DIRECT_OUTPUT屬性。 SET_TARGET_PROPERTIES (hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1) SET_TARGET_PROPERTIES (hello PROPERTIES CLEAN_DIRECT_OUTPUT 1) #一般,動態庫包含一個版本號,VERSION指代動態庫版本,SOVERSION指代API版本。 SET_TARGET_PROPERTIES (hello PROPERTIES VERSION 1.2 SOVERSION 1) #構建完成後須要將libhello.a, libhello.so.x以及hello.h安裝到系統目錄, # 將hello的共享庫安裝到<prefix>/lib目錄; # 將hello.h安裝<prefix>/include/hello目錄。 INSTALL (TARGETS hello hello_static LIBRARY DESTINATION lib ARCHIVE DESTINATION lib) INSTALL (FILES hello.h DESTINATION include/hello)
建立build目錄,進入build目錄。
cmake ../
make
生成的目標文件以下:
執行安裝:
sudo make install
相應的庫文件和頭文件分別被安裝到/usr/local/lib和/usr/local/include/hello目錄下。
get_target_property(OUTPUT_VALUE hello_static OUTPUT_NAME) message(STATUS "This is the hello_static OUTPUT_NAME: "${OUTPUT_VALUE})
若是沒有定義hello_static變量的OUTPUT_NAME屬性,則OUTPUT_VALUE被賦值NOTFOUND。
set_property(<GLOBAL | DIRECTORY [dir] | TARGET [target1 [target2 ...]] | SOURCE [src1 [src2 ...]] | TEST [test1 [test2 ...]] | CACHE [entry1 [entry2 ...]]> [APPEND][APPEND_STRING] PROPERTY <name>[value1 [value2 ...]])
在某個域中對零個或多個對象設置一個屬性。第一個參數決定該屬性設置所在的域,必須爲下面中的其中之一:
GLOBAL域是惟一的,而且不接特殊的任何名字。
DIRECTORY域默認爲當前目錄,但能夠用全路徑或相對路徑指定其它目錄(指定目錄必須已經被CMake處理)。
TARGET域可命名零或多個已經存在的目標。
SOURCE域可命名零或多個源文件,源文件屬性只對在相同目錄下的目標是可見的(CMakeLists.txt)。
TEST域可命名零或多個已存在的測試。
CACHE域必須命名零或多個已存在條目的cache。
必選項PROPERTY後爲要設置的屬性的名字。其它參數用於構建以分號隔開的列表形式的屬性值。若是指定了APPEND選項,則指定的列表將會追加到任何已存在的屬性值當中。若是指定了APPEND_STRING選項,則會將值做爲字符串追加到任何已存在的屬性值。
get_property(<variable> <GLOBAL | DIRECTORY [dir] | TARGET <target> | SOURCE <source> | TEST <test> | CACHE <entry> | VARIABLE> PROPERTY <name> [SET | DEFINED |BRIEF_DOCS | FULL_DOCS])
必選項PROPERTY後面緊跟着要獲取的屬性的名字。若是指定了SET選項,則變量會被設置爲一個布爾值,代表該屬性是否已設置。若是指定了DEFINED選項,則變量也會被設置爲一個布爾值,代表該屬性是否已定義(如經過define_property)。若是定義了BRIEF_DOCS或FULL_DOCS選項,則該變量被設置爲一個字符串,包含了對請求的屬性的文檔。若是該屬性沒有相關文件,則會返回NOTFOUND。
get_target_property(OUTPUT_VALUE all STATUS) if(${OUTPUT_VALUE} STREQUAL OUTPUT_VALUE-NOTFOUND) #Target all 不存在 else() #Target all 存在 endif()
定義列表
set(列表名 值1 值2 ... 值N)
set(列表名 「值1;值2; ...;值N」)
set(list_var 1 2 3 4) # list_var = 1;2;3;4 set(list_foo "5;6;7;8") # list_foo = 5;6;7;8 message(${list_var})#輸出: 1234 message(${list_foo})#輸出:5678 message("${list_var}")#輸出:1;2;3;4 message("${list_foo}")#輸出:5;6;7;8
不加引號的引用cmake將自動在分號處進行切分紅多個列表元素,並將其做爲多個獨立的參數傳給命令。加引號的引用cmake不會進行切分並保持分號不動,把整個引號內的內容看成一個參數傳給命令。
經常使用列表操做以下:list(LENGTH list output variable)
LENGTH返回列表的長度
list(GET <list> <elementindex> [<element index> ...] <output variable>)
GET返回列表中指定下標的元素
list(APPEND <list><element> [<element> ...])
APPEND添加新元素到列表中
list(FIND <list> <value><output variable>)
FIND查找list列表中爲value的值
list(INSERT <list><element_index> <element> [<element> ...])
INSERT 將新元素插入到列表中指定的位置
list(REMOVE_ITEM <list> <value>[<value> ...])
REMOVE_ITEM從列表中刪除某個元素
list(REMOVE_AT <list><index> [<index> ...])
REMOVE_AT從列表中刪除指定下標的元素
list(REMOVE_DUPLICATES <list>)
REMOVE_DUPLICATES從列表中刪除重複的元素
list(REVERSE <list>)
REVERSE將列表的內容實地反轉,改變的是列表自己,而不是其副本
list(SORT <list>)
SORT將列表按字母順序實地排序,改變的是列表自己,而不是其副本
列表的操做方法會在當前的CMake變量域建立一些新值,即便列表自己是在父域中定義的,LIST命令也只會在當前域建立新的變量值,爲了將操做結果向上傳遞,須要經過SET PARENT_SCOPE, SET CACHE INTERNAL或其餘值域擴展的方法。
當指定索引值時,element index爲大於或等於0的值,從列表的開始處索引,0表明列表的第一個元素。若是element index爲小於或等於-1的值,從列表的結尾處索引,-1表明列表的最後一個元素。
file(WRITE filename "message towrite"... )
WRITE將一則信息寫入文件’filename’中,若是文件存在,會覆蓋,若是不存在,會建立文件。
file(APPEND filename "message to write"... )
APPEND將信息內容追加到文件末尾。file(READ filename variable [LIMIT numBytes] [OFFSEToffset] [HEX])
READ會讀取文件的內容並將其存入到變量中。會在給定的偏移量處開始讀取最多numBytes個字節。若是指定了HEX參數,二進制數據將會被轉換成十進制表示形式並存儲到變量中。file(<MD5|SHA1|SHA224|SHA256|SHA384|SHA512> filenamevariable)
MD5, SHA1, SHA224, SHA256, SHA384, SHA512會計算出文件內容對應的加密散列。
file(STRINGS filename variable [LIMIT_COUNT num] [LIMIT_INPUT numBytes] [LIMIT_OUTPUTnumBytes] [LENGTH_MINIMUM numBytes] [LENGTH_MAXIMUMnumBytes] [NEWLINE_CONSUME] [REGEX regex] [NO_HEX_CONVERSION])
STRINGS從文件中解析出ASCII字符串列表並存儲在變量中。文件中的二進制數據將被忽略,回車符(CR)也會被忽略。能夠解析Intel Hex和Motorola S-record文件,兩種文件在讀取時會自動轉換爲二進制格式,可使用參數NO_HEX_CONVERSION禁用自動轉換。LIMIT_COUNT設置可返回的最大數量的字符串。LIMIT_INPUT 設置從輸入文件中可讀取的最大字節數。LIMIT_OUTPUT設置了存儲在輸出變量中最大的字節數。 LENGTH_MINIMUM設置了返回的字符串的最小長度。小於這個長度的字符串將被忽略。 LENGTH_MAXIMUM 設置返回的字符串的最大長度。大於這個長度的字符串將被切分爲長度不大於於最大長度值的子字符串。NEWLINE_CONSUME 容許換行符包含進字符串中而不是截斷它們。REGEX 指定了返回的字符串必須匹配的正則表達式的模式。典型用法file(STRINGS file.txt myfile)
將輸入文件的每行內容存儲在變量"myfile"中。file(GLOB variable [RELATIVE path] [globbingexpressions]...)
GLOB 會產生一個由全部匹配globbing表達式的文件組成的列表,並將其保存到變量中。Globbing表達式與正則表達式相似,但更簡單。若是指定了RELATIVE 標記,返回的結果將是與指定的路徑相對的路徑構成的列表。 (一般不推薦使用GLOB命令來從源碼樹中收集源文件列表。
globbing 表達式包括:
*.cxx - match all files with extension cxx *.vt? - match all files with extension vta,...,vtz f[3-5].txt - match files f3.txt,f4.txt, f5.txt
file(GLOB_RECURSE variable [RELATIVE path] [FOLLOW_SYMLINKS] [globbingexpressions]...)
GLOB_RECURSE會遍歷匹配目錄的全部文件以及子目錄下面的文件。對於屬於符號連接的子目錄,只有FOLLOW_SYMLINKS指定1或者cmake策略CMP0009沒有設置爲NEW時,纔會遍歷連接目錄。
file(RENAME <oldname> <newname>)
RENAME 將文件系統中的文件或目錄移動到目標位置,並自動替換目標位置處的文件或目錄。file(REMOVE [file1 ...])
REMOVE 會刪除指定的文件以及子目錄下的文件。 file(REMOVE_RECURSE [file1 ...])
REMOVE_RECURSE 會刪除指定的文件及子目錄,包括非空目錄。file(MAKE_DIRECTORY [directory1 directory2 ...])
MAKE_DIRECTORY在指定目錄處建立子目錄,若是父目錄不存在,會建立父目錄。file(RELATIVE_PATH variable directory file)
RELATIVE_PAT推斷出指定文件相對於特定目錄的路徑。file(TO_CMAKE_PATH path result)
TO_CMAKE_PATH會將路徑轉換成cmake風格的路徑表達形式。file(TO_NATIVE_PATH path result)
TO_NATIVE_PATH與TO_CMAKE_PATH相似,但執行反向操做,將cmake風格的路徑轉換爲操做系統特定風格的路徑表式形式。
file(DOWNLOAD url file [INACTIVITY_TIMEOUT timeout] [TIMEOUT timeout] [STATUS status] [LOGlog] [SHOW_PROGRESS] [EXPECTED_MD5 sum])
DOWNLOAD下載指定URL的資源到指定的文件上。若是指定了LOG 參數,將會把下載的日誌保存到相應的變量中。若是指定了STATUS變量,操做的狀態信息就會保存在相應的變量中。返回的狀態是一個長度爲2的列表。第一個元素是操做的返回值。0表示操做過程當中無錯誤發生。若是指定了TIMEOUT,單位於秒,且必須爲整數,那麼在指定的時間後,操做將會超時,INACTIVITY_TIMEOUT指定了操做在處於活動狀態超過指定的秒數後,應該中止。若是指定了EXPECTED_MD5,若是操做會檢驗下載後的文件的實際md5校驗和是否與預期的匹配,若是不匹配,操做將會失敗,並返回相應的錯誤碼。若是指定了 SHOW_PROGRESS,那麼進度的信息將會被打印成狀態信息直到操做完成。
file(UPLOADfilename url [INACTIVITY_TIMEOUT timeout] [TIMEOUT timeout] [STATUS status][LOG log] [SHOW_PROGRESS])
UPLOAD執行的是一個上傳操做。參數含義與DOWNLOAD 一致。
file(<COPY|INSTALL> files... DESTINATION<dir> [FILE_PERMISSIONS permissions...] [DIRECTORY_PERMISSIONSpermissions...] [NO_SOURCE_PERMISSIONS][USE_SOURCE_PERMISSIONS] [FILES_MATCHING] [[PATTERN <pattern> | REGEX<regex>] [EXCLUDE] [PERMISSIONSpermissions...]] [...])
COPY表示複製文件,目錄以及符號連接到一個目標文件夾中。輸入路徑將視爲相對於當前源碼目錄的路徑。目標路徑則是相對於當前的構建目錄。複製保留輸入文件的一些權限屬性。
EXEC_PROGRAM(Executable [dir where to run] [ARGS <args>][OUTPUT_VARIABLE <var>] [RETURN_VALUE <value>])
用於在指定目錄運行某個程序(默認爲當前CMakeLists.txt所在目錄),經過ARGS添加參數,經過OUTPUT_VARIABLE和RETURN_VALUE獲取輸出和返回值
# 在src中運行ls命令,在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)
$ENV{VAR}是對環境變量VAR的引用,cmake支持變量嵌套引用,解引用的順序從內到外。
message("PATH = $ENV{PATH}")
自定義函數命令格式以下:
function(<name> [arg1 [arg2 [arg3 ...]]]) # 自定義命令塊 COMMAND1(ARGS ...) COMMAND2(ARGS ...) endfunction(<name>)
函數名爲name,參數爲arg1, arg2, arg3, ...的函數命令。參數之間用空格進行分隔,若是某一參數裏面包含空格最好用雙引號把該參數包起來(引號內的全部字符串只看成一個參數),好比」arg1」。若是不指定參數列表,則函數能夠接受任意的參數,ARGC內置變量代表傳人蔘數的個數,ARGV0, ARGV1, ARGV2, ...內置變量能夠得到對應傳入的參數,ARGV內置變量能夠得到整個參數列表。
# print函數定義 function(print x y z) message("Calling function 'print':") message(" x = ${x}") message(" y = ${y}") message(" z = ${z}") message("ARGC = ${ARGC} arg1 = ${ARGV0} arg2 = ${ARGV1} arg3 = ${ARGV2} all args = ${ARGV}") # endfunction(print) # 函數調用 print(1 2 3)
自定義宏命令以下:
macro(<name> [arg1 [arg2 [arg3 ...]]]) COMMAND1(ARGS ...) COMMAND2(ARGS ...) endmacro(<name>)