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
5、消息機制
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
)
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()
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的文件中。如果文件已經存在,該命令會覆蓋已有的文件;如果文件不存在,它將創建該文件。
APPEND選項和WRITE選項一樣,將會寫一條消息到名為filename的文件中,只是該消息會附加到文件末尾。
READ選項將會讀一個文件中的內容並將其存儲在變量里。讀文件的位置從offset開始,最多讀numBytes個字節。如果指定了HEX參數,二進制代碼將會轉換為十六進制表達方式,並存儲在變量里。
STRINGS將會從一個文件中將一個ASCII字符串的list解析出來,然后存儲在variable變量中。文件中的二進制數據會被忽略。回車換行符會被忽略。它也可以用在Intel的Hex和Motorola的S-記錄文件;讀取它們時,它們會被自動轉換為二進制格式。可以使用NO_HEX_CONVERSION選項禁止這項功能。LIMIT_COUNT選項設定了返回的字符串的最大數量。LIMIT_INPUT設置了從輸入文件中讀取的最大字節數。LIMIT_OUTPUT設置了在輸出變量中存儲的最大字節數。LENGTH_MINIMUM設置了要返回的字符串的最小長度;小於該長度的字符串會被忽略。LENGTH_MAXIMUM設置了返回字符串的最大長度;更長的字符串會被分割成不長於最大長度的字符串。NEWLINE_CONSUME選項允許新行被包含到字符串中,而不是終止它們。REGEX選項指定了一個待返回的字符串必須滿足的正則表達式。典型的使用方式是:
file(STRINGS myfile.txt myfile)
該命令在變量myfile中存儲了一個list,該list中每個項是輸入文件中的一行文本。
GLOB選項將會為所有匹配查詢表達式的文件生成一個文件list,並將該list存儲進變量variable里。文件名查詢表達式與正則表達式類似,只不過更加簡單。如果為一個表達式指定了RELATIVE標志,返回的結果將會是相對於給定路徑的相對路徑。文件名查詢表達式的例子有:
*.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 查詢跟多有用的信息。
使用遞歸查詢的例子有:
/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命令生成的安裝腳本使用這個版本(它會使用一些沒有在文檔中涉及的內部使用的選項。)