cmake使用示例與整理總結 http://blog.csdn.net/wzzfeitian/article/details/40963457/ 對應的demo:https://github.com/carl-wang-cn/demo/tree/master/cmake
CMakeList學習 參考資源http://www.cnblogs.com/wengzilin/p/4466708.html 官方文檔:https://cmake.org/cmake/help/v3.0/manual/cmake-commands.7.html 編寫CMakeLists.txt 1、指定版本及工程名 cmake_minimum_required(VERSION 2.8) project(TEST) 2、添加一些option選項 option(BUILD_ANDROID "whether to build on android platform" OFF) #BUILD_ANDROID本身定義的,能夠經過if判斷使用 if (BUILD_ANDROID) message(STATUS "BUILD_ANDROID status is : " ${BUILD_ANDROID}) 3、獲取依賴模塊文件路徑(非系統目錄下,通常須要指定) 假設當前項目在文件夾test下,而後在test下創建的這個CMakeList,那麼這個目錄DEP_HOME 就在於test同一級目錄下的dependence_modes文件夾下 即:~mydir$ test dependence_modes #在mydir目錄下有兩個文件夾,test和dependence_modes,dependence_modes是對應的依賴工程 ## locate dependence mode and add cmake modules path get_filename_component(DEP_HOME ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) #得到當前項目test所在的目錄,這裏是」mydir「 set(DEP_HOME "${DEP_HOME}/dependence_modes") if (EXISTS ${DEP_HOME}) message(STATUS "Found dependence_modes: ${DEP_HOME}") include_directories(SYSTEM ${DEP_HOME}) ##能夠將DEP_HOME目錄添加到SYSTEM目錄 else() message(FATAL_ERROR "dependence_modes not found.") endif() 4、設置全部cmake模塊的路徑,CMAKE_MODULE_PATH是cmake的自動的變量,find_package的時候,也能夠經過其指定搜索路徑 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${DEP_HOME}/cmake) #若是DEP_HOME中有對應的cmake須要依賴調用,則須要添加進來 message(STATUS "CMAKE_MODULE_PATH: " ${CMAKE_MODULE_PATH})
find_path(TEST_PATH NAMES test.h PATHS /usr/local/include /usr/hostname/test DOC "this is a test for find_path") message(${TEST_PATH})
輸出爲:
//this is a test for find_path
TEST_PATH:PATH=/usr/hostname/test
五、消息機制
message(FATAL_ERROR "dependence_modes not found.") #發錯錯誤消息,並退出
message(STATUS "BUILD_ANDROID status is : " ${BUILD_ANDROID}) #顯示當前狀態
6、指定頭文件和源文件 include_directories 通常用於指定目錄,或者添加目錄 ##如下語句爲將CMAKE_CURRENT_SOURCE_DIR當前目錄添加到當前項目的搜索目錄 include_directories( ${CMAKE_CURRENT_SOURCE_DIR} )
後面能夠添加:
include_directories(CMAKE_CURRENT_SOURCE_DIR ${DEP_HOME}) ##將DEP_HOME目錄添加到當前目錄中
file(GLOB_RECURSE box2d_source_files "${CMAKE_CURRENT_SOURCE_DIR}/Box2D/*.cpp") set 將一個CMAKE變量設置爲給定值。 (屬性的設置及set的一些說明能夠看官方文檔或者博客http://www.cnblogs.com/coderfenghc/archive/2012/10/20/2712806.html) set(<variable> <value> [[CACHE <type> <docstring> [FORCE]] | PARENT_SCOPE]) 將變量<variable>的值設置爲<value>。在<variable>被設置以前,<value>會被展開。若是有CACHE選項,那麼<variable>就會添加到cache中; 這時<type>和<docstring>是必需的。 <type>被CMake GUI用來選擇一個窗口,讓用戶設置值。<type>能夠是下述值中的一個: FILEPATH = 文件選擇對話框。 PATH = 路徑選擇對話框。 STRING = 任意的字符串。 BOOL = 布爾值選擇複選框。 INTERNAL = 不須要GUI輸入端。(適用於永久保存的變量)。 若是在一個變量中添加東西可使用set,SET 命令用於將文件組成一個列表。 例如:在 MY_SOURCE_FILES中添加源文件 set(MY_SOURCE_FILES Hell.c File2.c File3.c)
set(MY_SOURCE_FILES ${MY_SOURCE_FILES} test_image_src.cpp)
或者list(APPEND MY_SOURCE_FILES test_image_src.cpp)
) 若是有多個變量添加,可使用for循環,例如:
SET(test
${PROJECT_SOURCE_DIR}/test/test1.cpp
${PROJECT_SOURCE_DIR}/test/test2.cpp
${PROJECT_SOURCE_DIR}/test/test3.cpp
)html
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) //設置執行文件輸出路徑
FOREACH (test ${tests})
STRING(REGEX MATCH "[^/]+$" test_file ${test})
STRING(REPLACE ".cpp" "" test_basename ${test_file})
ADD_EXECUTABLE(test_${test_basename} ${test})
TARGET_LINK_LIBRARIES(test_${test_basename}
${TEST_LINK_LIBS}
)
ENDFOREACH()python
2、添加環境變量(可選, added by 編程小翁, 博客園) add_definitions( -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_REENTRANT -DENV_UNIX -DBREAK_HANDLER -DUNICODE -D_UNICODE) 若是須要判斷平臺,能夠這麼寫: IF(APPLE) add_definitions(-DENV_MACOSX) FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation) ENDIF(APPLE) 其中 FIND_LIBRARY還能夠指定對應的路徑,例如: #look for the Tcl library FIND_LIBRARY(TCL_LIBRARY NAMES tcl tc184 tc183 tc 182 tc 180 PATHS /usr/lib /usr/local/lib) IF (TCL_LIBRARY) TARGET_ADD_LIBRARY (Hello TCL_LIBRARY) ENDIF(TCL_LIBRARY)
link_directories(${LINK_DIR}) //添加連接庫時的 搜索路徑
configure_file(<input> <output> [COPYONLY] [ESCAPE_QUOTES] [@ONLY] [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
Copy a file to another location and modify its contents.
例如在當前目錄下定義了foo.h.in的頭文件,頭文件內容以下:
#ifndef FOO_H
#define FOO_H
#cmakedefine FOO_ENABLE
#cmakedefine FOO_STRING "@FOO_STRING@"
#cmakedefine01 FOO_ENABLE
#endif
若是cmakelist 中配置了configure_file(./foo.h.in ${CMAKE_CURRENT_BINARY_DIR}/foo.h)
而且在cmakelist中使用:
option(FOO_ENABLE "whether open FOO" ON)
if(FOO_ENABLE)
set(FOO_STRING "new_string")
endif
最後會在build目錄下的當前cmake_current_binary_dir目錄下生成頭文件foo.h,內容爲:
#ifndef FOO_H
#define FOO_H
#define FOO_ENABLE
#define FOO_STRING new_string
#define FOO_ENABLE 1
#endif
不然就是如下內容:
#ifndef FOO_H
#define FOO_H
/* undefine FOO_ENABLE */
/* undefine FOO_STRING */
#define FOO_ENABLE 0
#endif
而後須要include_directories(${CMAKE_CURRENT_BINARY_DIR})
3、庫自動連接,查找庫 find_package(LibXML++ REQUIRED) #若是包是可選的,能夠忽略REQUIRED關鍵字 無論使用哪種模式,只要找到包,就會生成如下變量,而後能夠在其餘地方中使用: <NAME>_FOUND <NAME>_INCLUDE_DIRS or <NAME>_INCLUDES <NAME>_LIBRARIES or <NAME>_LIBRARIES or <NAME>_LIBS <NAME>_DEFINITIONS if(LibXML++_FOUND) include_directories(${LibXML++_INCLUDE_DIRS}) set(LIBS ${LIBS} ${LibXML++_LIBRARIES}) message(STATUS "LibXML++ lib DIR is: " ${LibXML++_INCLUDE_DIRS}) #輸出對應的庫路徑, endif() 能夠詳細見:http://www.yeolar.com/note/2014/12/16/cmake-how-to-find-libraries/ 「CMAKE 如何查找連接庫」 另外,還能夠設置須要鏈接的庫的前綴、後綴 set(CMAKE_IMPORT_LIBRARY_PREFIX "lib") #指定鏈接庫的前綴名字有lib set(CMAKE_IMPORT_LIBRARY_SUFFIX ".dll") #指定鏈接庫的後綴名字有lib 4、設置生成庫的名字跟類型
舉例: add_library(Box2D STATIC ${box2d_source_files}) 這裏add_library表示最終編譯爲一個庫,static表示是靜態庫,若是想編譯動態庫,能夠修改成shared. 至此,一個靜態庫的配置就完成了。固然,由於這個庫沒有包括其它外部的頭文件,因此會比較簡單。 5、Get a specific component of a full filename. get_filename_component(<VAR> <FileName> <COMP> [CACHE]) Set <VAR> to a component of <FileName>, where <COMP> is one of: DIRECTORY = Directory without file name NAME = File name without directory EXT = File name longest extension (.b.c from d/a.b.c) NAME_WE = File name without directory or longest extension ABSOLUTE = Full path to file REALPATH = Full path to existing file with symlinks resolved PATH = Legacy alias for DIRECTORY (use for CMake <= 2.8.11) 舉例: file(GLOB_RECURSE examples_srcs "${PROJECT_SOURCE_DIR}/examples/*.cpp") foreach(source_file ${examples_srcs}) # get file name get_filename_component(name ${source_file} NAME_WE) # get folder name get_filename_component(path ${source_file} PATH) get_filename_component(folder ${path} NAME_WE) add_executable(${name} ${source_file}) target_link_libraries(${name} ${Caffe_LINK}) caffe_default_properties(${name}) # set back RUNTIME_OUTPUT_DIRECTORY set_target_properties(${name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/examples/${folder}") caffe_set_solution_folder(${name} examples) # install install(TARGETS ${name} DESTINATION bin) if(UNIX OR APPLE) # Funny command to make tutorials work # TODO: remove in future as soon as naming is standartaized everywhere set(__outname ${PROJECT_BINARY_DIR}/examples/${folder}/${name}${CAffe_POSTFIX}) add_custom_command(TARGET ${name} POST_BUILD COMMAND ln -sf "${__outname}" "${__outname}.bin") endif() endforeach() 6、一個完整的CMakeList,若是還有新的CMakeList.txt須要包含進來, 可使用add_subdirectory(${sub_cmakelistpath}) cmake_minimum_required(VERSION 3.2) #1、添加頭文件目錄,能夠多引用,可是不能缺,由於缺了就編譯不過 include_directories( "../../../myWindows" "../../../" "../../../include_windows" ) #2、添加環境變量,請結合實際項目要求,不是必須的 add_definitions( -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_REENTRANT -DENV_UNIX -DBREAK_HANDLER -DUNICODE -D_UNICODE) IF(APPLE) add_definitions(-DENV_MACOSX) FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation ) #FIND_LIBRARY命令用於尋找在一些指定目錄下的特定的相關COREFOUNDATION_LIBRARY庫文件,還能夠指定對應的庫路徑 #3、源文件 file(GLOB_RECURSE src_files "../../../../C/7zCrc.c" "../../../../C/7zCrcOpt.c" "../../../../C/7zStream.c" "../../../../C/Aes.c") #4、設置生成靜態庫以及名稱 add_library(myLibName STATIC ${src_files}) IF(APPLE) TARGET_LINK_LIBRARIES(myLibName ${COREFOUNDATION_LIBRARY} ${CMAKE_THREAD_LIBS_INIT}) ELSE(APPLE) IF(HAVE_PTHREADS) TARGET_LINK_LIBRARIES(myLibName ${CMAKE_THREAD_LIBS_INIT}) ENDIF(HAVE_PTHREADS) ENDIF(APPLE) #5、生成執行文件 add_executable(${exename} folder/${src_files}) target_link_libraries(${exename} ${TESTS_LINK_LIBS}) 7、屬性設置 set_property set_source_files_properties set_target_properties 舉例:set_target_properties(target1 target2 ... PROPERTIES prop1 value1 prop2 value2 ...) 例如設置生成庫屬性,舉例: add_library(libname_static STATIC ${LIBNAME_${ARCH}_SRC}) #生成靜態庫 set_target_properties(libname_static PROPERTIES OUTPUT_NAME "librename") #設置輸出名字 set_target_properties(libname_static PROPERTIES CLEAN_DIRECT_OUTPUT 1) #設置爲使用clean時,可清除 8、make install install(DIRECTORY ${src_dir} DESTINATION ${dst_dir} #把src_dir 安裝到dst_dir目錄下 FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ DIRECTORY_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ) 9、交叉編譯用得比較多的部分 set(CMAKE_FIND_ROOT_PATH "${ANDROID_TOOLCHAIN_ROOT}/sysroot") 列出文件系統搜索的「根目錄列表」.經常在交叉編譯時使用得比較多. CMake將把這個「根目錄列表」中做爲可選的搜索的目錄,而且經過 find_package(), find_library() 等方式來搜索對應的文件和庫 https://cmake.org/cmake/help/v3.1/variable/CMAKE_FIND_ROOT_PATH_MODE_PROGRAM.html set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) This variable controls whether the CMAKE_FIND_ROOT_PATH and CMAKE_SYSROOT are used by find_program(). If set to ONLY, then only the roots in CMAKE_FIND_ROOT_PATH will be searched. If set to NEVER, then the roots in CMAKE_FIND_ROOT_PATH will be ignored and only the host system root will be used. If set to BOTH, then the host system paths and the paths in CMAKE_FIND_ROOT_PATH will be searched. set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) This variable controls whether the CMAKE_FIND_ROOT_PATH and CMAKE_SYSROOT are used by find_library(). If set to ONLY, then only the roots in CMAKE_FIND_ROOT_PATH will be searched. If set to NEVER, then the roots in CMAKE_FIND_ROOT_PATH will be ignored and only the host system root will be used. If set to BOTH, then the host system paths and the paths in CMAKE_FIND_ROOT_PATH will be searched. 同理:CMAKE_FIND_ROOT_PATH_MODE_INCLUDE COMPILER設置: set(CMAKE_C_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/arm-linux-androideabi-gcc") set(CMAKE_CXX_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/arm-linux-androideabi-g++") ##能夠打印對應的信息 Compiler setting message(STATUS "CMAKE_SYSTEM_NAME: " ${CMAKE_SYSTEM_NAME}) ##linux MAC 等等 message(STATUS "CXX_COMPILER_ID: " ${CMAKE_CXX_COMPILER_ID}) ##GNU Clang 等等 message(STATUS "CXX_COMPILER_VERSION: " ${CMAKE_CXX_COMPILER_VERSION}) ## NDK 4.9.1 message(STATUS "CMAKE_SYSTEM_PROCESSOR: " ${CMAKE_SYSTEM_PROCESSOR}) ##x86_64等等 ##判斷CMAKE_CXX_COMPILER_ID "GNU" "Clang"等等 if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") message(STATUS "CXX_COMPILER_ID: " ${CMAKE_CXX_COMPILER_ID}) endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -fPIC -Wall -std=c++11") ## -O3 -fPIC -Wall -std=c++11 獲取CMake主機名: if(CMAKE_HOST_SYSTEM_NAME MATCHES Linux*) set(TARGET_OS linux) elseif(CMAKE_HOST_SYSTEM_NAME MATCHES Darwin*) set(TARGET_OS mac) elseif(CMAKE_HOST_SYSTEM_NAME MATCHES Windows*) set(TARGET_OS windows) else() message(FATAL_ERROR "Host system does not support!") endif()
http://www.cnblogs.com/coderfenghc/archive/2012/07/08/2581734.html
CMD#28: file
文件操做命令
file(WRITE filename "message to write"... )
file(APPEND filename "message to write"... )
file(READ filename variable [LIMIT numBytes] [OFFSET offset] [HEX])
file(STRINGS filename variable [LIMIT_COUNT num]
[LIMIT_INPUT numBytes] [LIMIT_OUTPUT numBytes]
[LENGTH_MINIMUM numBytes] [LENGTH_MAXIMUM numBytes]
[NEWLINE_CONSUME] [REGEX regex]
[NO_HEX_CONVERSION])
file(GLOB variable [RELATIVE path] [globbing expressions]...)
file(GLOB_RECURSE variable [RELATIVE path]
[FOLLOW_SYMLINKS] [globbing expressions]...)
file(RENAME <oldname> <newname>)
file(REMOVE [file1 ...])
file(REMOVE_RECURSE [file1 ...])
file(MAKE_DIRECTORY [directory1 directory2 ...])
file(RELATIVE_PATH variable directory file)
file(TO_CMAKE_PATH path result)
file(TO_NATIVE_PATH path result)
file(DOWNLOAD url file [TIMEOUT timeout] [STATUS status] [LOG log]
[EXPECTED_MD5 sum] [SHOW_PROGRESS])
WRITE選項將會寫一條消息到名爲filename的文件中。若是文件已經存在,該命令會覆蓋已有的文件;若是文件不存在,它將建立該文件。linux
APPEND選項和WRITE選項同樣,將會寫一條消息到名爲filename的文件中,只是該消息會附加到文件末尾。android
READ選項將會讀一個文件中的內容並將其存儲在變量裏。讀文件的位置從offset開始,最多讀numBytes個字節。若是指定了HEX參數,二進制代碼將會轉換爲十六進制表達方式,並存儲在變量裏。c++
STRINGS將會從一個文件中將一個ASCII字符串的list解析出來,而後存儲在variable變量中。文件中的二進制數據會被忽略。回車換行符會被忽略。它也能夠用在Intel的Hex和Motorola的S-記錄文件;讀取它們時,它們會被自動轉換爲二進制格式。可使用NO_HEX_CONVERSION選項禁止這項功能。LIMIT_COUNT選項設定了返回的字符串的最大數量。LIMIT_INPUT設置了從輸入文件中讀取的最大字節數。LIMIT_OUTPUT設置了在輸出變量中存儲的最大字節數。LENGTH_MINIMUM設置了要返回的字符串的最小長度;小於該長度的字符串會被忽略。LENGTH_MAXIMUM設置了返回字符串的最大長度;更長的字符串會被分割成不長於最大長度的字符串。NEWLINE_CONSUME選項容許新行被包含到字符串中,而不是終止它們。REGEX選項指定了一個待返回的字符串必須知足的正則表達式。典型的使用方式是:git
file(STRINGS myfile.txt myfile)
該命令在變量myfile中存儲了一個list,該list中每一個項是輸入文件中的一行文本。
GLOB選項將會爲全部匹配查詢表達式的文件生成一個文件list,並將該list存儲進變量variable裏。文件名查詢表達式與正則表達式相似,只不過更加簡單。若是爲一個表達式指定了RELATIVE標誌,返回的結果將會是相對於給定路徑的相對路徑。文件名查詢表達式的例子有:github
*.cxx - 匹配全部擴展名爲cxx的文件。
*.vt? - 匹配全部擴展名是vta,...,vtz的文件。
f[3-5].txt - 匹配文件f3.txt, f4.txt, f5.txt。
GLOB_RECURSE選項將會生成一個相似於一般的GLOB選項的list,只是它會尋訪全部那些匹配目錄的子路徑並同時匹配查詢表達式的文件。做爲符號連接的子路徑只有在給定FOLLOW_SYMLINKS選項或者cmake策略CMP0009被設置爲NEW時,纔會被尋訪到。參見cmake --help-policy CMP0009 查詢跟多有用的信息。正則表達式
使用遞歸查詢的例子有:express
/dir/*.py - 匹配全部在/dir及其子目錄下的python文件。
MAKE_DIRECTORY選項將會建立指定的目錄,若是它們的父目錄不存在時,一樣也會建立。(相似於mkdir命令——譯註)編程
RENAME選項對同一個文件系統下的一個文件或目錄重命名。(相似於mv命令——譯註)
REMOVE選項將會刪除指定的文件,包括在子路徑下的文件。(相似於rm命令——譯註)
REMOVE_RECURSE選項會刪除給定的文件以及目錄,包括非空目錄。(相似於rm -r 命令——譯註)
RELATIVE_PATH選項會肯定從direcroty參數到指定文件的相對路徑。
TO_CMAKE_PATH選項會把path轉換爲一個以unix的 / 開頭的cmake風格的路徑。輸入能夠是一個單一的路徑,也能夠是一個系統路徑,好比"$ENV{PATH}"。注意,在調用TO_CMAKE_PATH的ENV周圍的雙引號只能有一個參數(Note the double quotes around the ENV call TO_CMAKE_PATH only takes one argument. 原文如此。quotes和後面的takes讓人後糾結,這句話翻譯可能有誤。歡迎指正——譯註)。
TO_NATIVE_PATH選項與TO_CMAKE_PATH選項很類似,可是它會把cmake風格的路徑轉換爲本地路徑風格:windows下用\,而unix下用/。
DOWNLOAD 將給定的URL下載到指定的文件中。若是指定了LOG var選項,下載日誌將會被輸出到var中。若是指定了STATUS var選項,下載操做的狀態會被輸出到var中。該狀態返回值是一個長度爲2的list。list的第一個元素是操做的數字返回值,第二個返回值是錯誤的字符串值。錯誤信息若是是數字0,操做中沒有發生錯誤。若是指定了TIMEOUT time選項,在time秒以後,操做會超時退出;time應該是整數。若是指定了EXPECTED_MD5 sum選項,下載操做會認證下載的文件的實際MD5和是否與指望值匹配。若是不匹配,操做將返回一個錯誤。若是指定了SHOW_PROGRESS選項,進度信息會以狀態信息的形式被打印出來,直到操做完成。
file命令還提供了COPY和INSTALL兩種格式:
file(<COPY|INSTALL> files... DESTINATION <dir>
[FILE_PERMISSIONS permissions...]
[DIRECTORY_PERMISSIONS permissions...]
[NO_SOURCE_PERMISSIONS] [USE_SOURCE_PERMISSIONS]
[FILES_MATCHING]
[[PATTERN <pattern> | REGEX <regex>]
[EXCLUDE] [PERMISSIONS permissions...]] [...])
COPY版本把文件、目錄以及符號鏈接拷貝到一個目標文件夾。相對輸入路徑的評估是基於當前的源代碼目錄進行的,相對目標路徑的評估是基於當前的構建目錄進行的。複製過程將保留輸入文件的時間戳;而且若是目標路徑處存在同名同時間戳的文件,複製命令會把它優化掉。賦值過程將保留輸入文件的訪問權限,除非顯式指定權限或指定NO_SOURCE_PERMISSIONS選項(默認是USE_SOURCE_PERMISSIONS)。參見install(DIRECTORY)命令中關於權限(permissions),PATTERN,REGEX和EXCLUDE選項的文檔。
INSTALL版本與COPY版本只有十分微小的差異:它會打印狀態信息,而且默認使用NO_SOURCE_PERMISSIONS選項。install命令生成的安裝腳本使用這個版本(它會使用一些沒有在文檔中涉及的內部使用的選項。)