您好,登錄后才能下訂單哦!
cmake_minimum_required (VERSION 2.8)
cmake_minimum_required用于規定cmake程序的最低版本,可選。如果CMakeLists.txt文件中使用了高版本cmake特有的一些命令時,就需要使用cmake_minimum_required對CMake進行版本限制,提醒用戶升級到相應版本后再執行cmake。
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文件。
通過執行cmake生成MakeFile文件,執行make進行編譯安裝,其方法如下:
方法一(內部構建):
在工程CMakeLists.txt所在目錄下執行:
cmake .
make
方法二(外部構建):
在工程CMakeLists.txt所在目錄下執行:
mkdir build
cd build
cmake ../
make
兩種方法最大的不同在于執行cmake和make的工作路徑不同。第一種方法中,cmake生成的所有中間文件和可執行文件都會存放在項目目錄中;而第二種方法中,中間文件和可執行文件都將存放在build目錄中,避免了源代碼被污染,第二中方法的build目錄可以創建在任意目錄下,只需要在執行cmake時指定工程的CMakeLists.txt目錄即可。由于第二種方法的生成、編譯和安裝是發生在不同于項目目錄的其它目錄中,因此第二種方法稱為外部構建。
????CMake官方推薦使用外部構建方法,可以避免源碼被污染。
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來產生一個包含新文件的構建系統。
設置編譯選項可以通過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支持
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
增加編譯選項:
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 path2 [path3 ... ENV var]]
[PATHS path2 [path3 ... 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>)
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。