01 cmake參考手冊

cmake使用手冊

(V1)

1、cmake 查閱

cmake --help-module-list | findstr -i bz

2、項目目錄相關

# 構建發生的目錄
CMAKE_BINARY_DIR
PROJECT_BINARY_DIR
<projectname>_BINARY_DIR

# 不論採用何種編譯方式,都是工程頂層目錄
CMAKE_SOURCE_DIR
PROJECT_SOURCE_DIR
<projectname>_SOURCE_DIR

PROJECT_NAME              # 返回通過PROJECT指令定義的項目名稱

CMAKE_CURRENT_SOURCE_DIR  # 當前處理的CMakeLists.txt所在的路徑

CMAKE_CURRENT_BINARY_DIR  # 內部編譯: 跟CMAKE_CURRENT_SOURCE_DIR一致
                          # 外部編譯: 指的是構建目錄
                          # add_subdirectory(src bin) 會更改它的值爲 bin

CMAKE_CURRENT_LIST_FILE   # 當前輸出所在的CMakeLists.txt的完整路徑
CMAKE_CURRENT_LIST_LINE   # 當前輸出所在的行

CMAKE_MODULE_PATH         # 模塊所在路徑
                          # SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake),然後可以用INCLUDE命令來調用自己的模塊

EXECUTABLE_OUTPUT_PATH    # 可執行文件存放目錄
LIBRARY_OUTPUT_PATH       # 庫存放目錄

CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE # 將工程提供的頭文件目錄始終置於系統頭文件目錄的前面

CMAKE_INCLUDE_PATH        # 頭文件搜索目錄

CMAKE_LIBRARY_PATH        # 庫搜索目錄

3、系統信息

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,包括OSX和cygwin
WIN32                     # 在所有的Win32平臺爲TRUE,包括cygwin

4、開關選項

CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS   # 用來控制IF ELSE語句的書寫方式
BUILD_SHARED_LIBS         # 這個開關用來控制默認的庫編譯方式: 動態庫 靜態庫
                          # 如果ADD_LIBRARY時沒有指定庫類型,那麼默認編譯生成的庫都是靜態庫
                          
CMAKE_C_FLAGS             # 設置C編譯選項
CMAKE_CXX_FLAGS           # 設置C++編譯選項
CMAKE_INCLUDE_CURRENT_DIR # 自動將每個CMakeLists.txt的所在目錄依次加入到 頭文件搜索目錄

5、編譯參數

message(STATUS "CMAKE_C_FLAGS = " ${CMAKE_C_FLAGS})
message(STATUS "CMAKE_C_FLAGS_DEBUG = " ${CMAKE_C_FLAGS_DEBUG})
message(STATUS "CMAKE_C_FLAGS_RELEASE = " ${CMAKE_C_FLAGS_RELEASE})

message(STATUS "CMAKE_CXX_FLAGS = " ${CMAKE_CXX_FLAGS})
message(STATUS "CMAKE_CXX_FLAGS_DEBUG = " ${CMAKE_CXX_FLAGS_DEBUG})
message(STATUS "CMAKE_CXX_FLAGS_RELEASE = " ${CMAKE_CXX_FLAGS_RELEASE})

message(STATUS "CMAKE_EXE_LINKER_FLAGS = " ${CMAKE_EXE_LINKER_FLAGS})
message(STATUS "CMAKE_EXE_LINKER_FLAGS_DEBUG = " ${CMAKE_EXE_LINKER_FLAGS_DEBUG})
message(STATUS "CMAKE_EXE_LINKER_FLAGS_RELEASE = " ${CMAKE_EXE_LINKER_FLAGS_RELEASE})

message(STATUS "CMAKE_SHARED_LINKER_FLAGS = " ${CMAKE_SHARED_LINKER_FLAGS})
message(STATUS "CMAKE_SHARED_LINKER_FLAGS_DEBUG = " ${CMAKE_SHARED_LINKER_FLAGS_DEBUG})
message(STATUS "CMAKE_SHARED_LINKER_FLAGS_RELEASE = " ${CMAKE_SHARED_LINKER_FLAGS_RELEASE})

message(STATUS "CMAKE_STATIC_LINKER_FLAGS = " ${CMAKE_STATIC_LINKER_FLAGS})
message(STATUS "CMAKE_STATIC_LINKER_FLAGS_DEBUG = " ${CMAKE_STATIC_LINKER_FLAGS_DEBUG})
message(STATUS "CMAKE_STATIC_LINKER_FLAGS_RELEASE = " ${CMAKE_STATIC_LINKER_FLAGS_RELEASE})

6、指令參考

1)cmake變量使用${}方式取值,但是在IF控制語句中是直接使用變量名
2) 環境變量使用$ENV{}方式取值,使用SET(ENV{VAR} VALUE)賦值
3)指令( 參數1 參數2 … )
 參數使用括弧括起,參數之間使用空格或分號分開。
 指令是大小寫無關的,參數和變量是大小寫相關的。推薦你全部使用大寫指令。

  • PROJECT(projectname [CXX] [C] [Java])
    指定工程名稱,並可指定工程支持的語言。支持語言列表可忽略,默認支持所有語言

  • SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])
    定義變量(可以定義多個VALUE,如SET(SRC_LIST main.c util.c reactor.c)

  • MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message to display" …)
    向終端輸出用戶定義的信息或變量的值
    SEND_ERROR: 產生錯誤,生成過程被跳過
    STATUS: 輸出前綴爲-的信息
    FATAL_ERROR: 立即終止所有cmake過程

  • ADD_EXECUTABLE(bin_file_name ${SRC_LIST})
    生成可執行文件

  • ADD_LIBRARY(libname [SHARED | STATIC | MODULE] [EXCLUDE_FROM_ALL] SRC_LIST)
    生成動態庫或靜態庫
    SHARED 動態庫
    STATIC 靜態庫
    MODULE 在使用dyld的系統有效,若不支持dyld,等同於SHARED
    EXCLUDE_FROM_ALL 表示該庫不會被默認構建

  • SET_TARGET_PROPERTIES
    設置輸出的名稱,設置動態庫的版本和API版本

  • CMAKE_MINIMUM_REQUIRED(VERSION version_number [FATAL_ERROR])
    聲明CMake的版本要求

  • ADD_SUBDIRECTORY(src_dir [binary_dir] [EXCLUDE_FROM_ALL])
    向當前工程添加存放源文件的子目錄,並可以指定中間二進制和目標二進制的存放位置
    EXCLUDE_FROM_ALL含義:將這個目錄從編譯過程中排除

  • SUBDIRS
    deprecated,不再推薦使用
    SUBDIRS(hello sample)相當於分別寫ADD_SUBDIRECTORY(hello),ADD_SUBDIRECTORY(sample)

  • INCLUDE_DIRECTORIES([AFTER | BEFORE] [SYSTEM] dir1 dir2 … )
    向工程添加多個特定的頭文件搜索路徑,路徑之間用空格分隔如果路徑包含空格,可以使用雙引號將它括起來,默認的行爲爲追加到當前頭文件搜索路徑的後面。
    有如下兩種方式可以控制搜索路徑添加的位置:
    CMAKE_INCLUDE_DIRECTORIES_BEFORE,通過SET這個cmake變量爲on,可以將添加的頭文件搜索路徑放在已有路徑的前面,通過AFTERBEFORE參數,也可以控制是追加還是置前。

  • LINK_DIRECTORIES(dir1 dir2 …)
    添加非標準的共享庫搜索路徑

  • LINK_LIBRARIES(library1 <debug|optimized> library2 ...)
    用在add_executable之前,用來鏈接靜態庫

  • TARGET_LINK_LIBRARIES(target lib1 lib2 …)
    用在add_executable之後,用來鏈接動態庫

  • ADD_DEFINITIONS
    向C/C++編譯器添加-D定義
    ADD_DEFINITIONS(-DENABLE_DEBUG -DABC)參數之間用空格分隔

  • ADD_DEPENDENCIES(target-name depend-target1 depend-target2 …)
    定義target依賴的其他target,確保target在構建之前,其依賴的target已經構建完畢

  • AUX_SOURCE_DIRECTORY(dir VAR)
    發現一個目錄下所有的源代碼文件並將列表存儲在一個變量中

  • EXEC_PROGRAM(Executable [dir where to run] [ARGS <args>][OUTPUT_VARIABLE <var>] [RETURN_VALUE <value>])
    用於在指定目錄運行某個程序(默認爲當前CMakeLists.txt所在目錄),通過ARGS添加參數,通過OUTPUT_VARIABLERETURN_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)
  • INCLUDE(file [OPTIONAL]) 用來載入CMakeLists.txt文件

  • INCLUDE(module [OPTIONAL])用來載入預定義的cmake模塊
    文件不存在也不會產生錯誤
    可以載入一個文件,也可以載入預定義模塊(模塊會在CMAKE_MODULE_PATH指定的路徑進行搜索)
    載入的內容將在處理到INCLUDE語句時直接執行

  • FIND_FILE(<VAR> name path1 path2 …)
    VAR變量代表找到的文件全路徑,包含文件名

  • FIND_LIBRARY(<VAR> name path1 path2 …)
    VAR變量代表找到的庫全路徑,包含庫文件名
    案例:

 FIND_LIBRARY(libX X11 /usr/lib)
 IF (NOT libx)
    MESSAGE(FATAL_ERROR "libX not found")
 ENDIF(NOT libX)
  • FIND_PATH(<VAR> name path1 path2 …)
    VAR變量代表包含這個文件的路徑

  • FIND_PROGRAM(<VAR> name 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)將其放入工程的某個目錄供工程使用

5.3 IF
語法:

IF (expression)
    COMMAND1(ARGS ...)
    COMMAND2(ARGS ...)
    ...
ELSE (expression)
    COMMAND1(ARGS ...)
    COMMAND2(ARGS ...)
    ...
ENDIF (expression) # 一定要有ENDIF與IF對應

7、控制流結構

IF

1)常規用法

IF (expression), expression不爲:空,0,N,NO,OFF,FALSE,NOTFOUND或<var>_NOTFOUND,爲真
IF (not exp), 與上面相反
IF (var1 AND var2)
IF (var1 OR var2)
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)

2)表達式是數字類型

IF (variable LESS number)
IF (string LESS number)
IF (variable GREATER number)
IF (string GREATER number)
IF (variable EQUAL number)
IF (string EQUAL number)

3)表達式是字母

IF (variable STRLESS string)
IF (string STRLESS string)
IF (variable STRGREATER string)
IF (string STRGREATER string)
IF (variable STREQUAL string)
IF (string STREQUAL string)

Notice…Get a Surprise:SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)

WHILE

語法

WHILE(condition)
    COMMAND1(ARGS ...)
    COMMAND2(ARGS ...)
    ...
ENDWHILE(condition)

FOREACH

語法1:常規表示法

FOREACH(loop_var arg1 arg2 ...)
     COMMAND1(ARGS ...)
     COMMAND2(ARGS ...)
 ...
ENDFOREACH(loop_var)

案例:

FOREACH(loop_var ${SRC_LIST})
  MESSAGE(${loop_var})
ENDFOREACH(loop_var)

語法2:範圍

FOREACH(loop_var RANGE total)
    COMMAND1(ARGS ...)
    COMMAND2(ARGS ...)
    ...
ENDFOREACH(loop_var)

案例:

FOREACH(var RANGE 10)
  MESSAGE(${var})
ENDFOREACH(var)

語法3:範圍和步長

FOREACH(loop_var RANGE start stop [step])
    COMMAND1(ARGS ...)
    COMMAND2(ARGS ...)
    ...
ENDFOREACH(loop_var)

例:

FOREACH(var RANGE 5 15 3)
  MESSAGE(${var})
ENDFOREACH(var)

macro

macro( [arg1 [arg2 [arg3 ...]]])
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
endmacro()

function

function(<name> [arg1 [arg2 [arg3 ...]]])
  COMMAND1(ARGS ...)
  COMMAND2(ARGS ...)
  ...
endfunction(<name>)
變量名 意義
ARGC 參數個數
ARGV 參數列表
ARGV0 參數0
ARGV1 參數1
ARGV2 參數2
ARGN 超出最後一個預期參數的參數列表

list

list(LENGTH <list> <output variable>) //獲得list長度
list(GET <list> <element index> [<element index> ...]
     <output variable>) //獲得list的某個位置元素
list(APPEND <list> [<element> ...])//add
list(FILTER <list> <INCLUDE|EXCLUDE> REGEX <regular_expression>)//清理
list(FIND <list> <value> <output variable>) //查找
list(INSERT <list> <element_index> <element> [<element> ...])
list(REMOVE_ITEM <list> <value> [<value> ...])
list(REMOVE_AT <list> <index> [<index> ...])
list(REMOVE_DUPLICATES <list>)
list(REVERSE <list>)
list(SORT <list>)

綜合示例:

function(Foo arg)
    MESSAGE(STATUS "ARGV=${ARGV}")
    MESSAGE(STATUS "ARGC=${ARGC}")
    MESSAGE(STATUS "ARGV0=${ARGV0}")
    MESSAGE(STATUS "ARGV1=${ARGV1}")
    MESSAGE(STATUS "ARGV2=${ARGV2}")
    MESSAGE(STATUS "ARGN=${ARGN}")
    LIST(LENGTH ARGV argv_len)
    MESSAGE(STATUS "length of argv_len=${argv_len}")
    SET (i 0)
    WHILE (i LESS ${argv_len})
        LIST(GET ARGV ${i} argv_value)
        MESSAGE(STATUS "argv[${i}]=${argv_value}")
        MATH(EXPR i "${i} + 1")
    ENDWHILE()
endfunction()
Foo(arg0 arg1 arg2 arg3)

輸出:
-- ARGV=arg0;arg1;arg2;arg3
-- ARGC=4
-- ARGV0=arg0
-- ARGV1=arg1
-- ARGV2=arg2
-- ARGN=arg1;arg2;arg3
-- length of argv_len=4
-- argv[0]=arg0
-- argv[1]=arg1
-- argv[2]=arg2
-- argv[3]=arg3
發佈了30 篇原創文章 · 獲贊 4 · 訪問量 4443
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章