modern cmake Doc文檔

 

Modern CMake文檔python

  • 安裝
    • Windows安裝
    • macOS安裝
      • 網址:https://cmake.org/download/,下載CMake,並正常安裝
      • 安裝完成以後,使用如下指令建立/usr/local/bin下的CMake的軟鏈接
      • 從新打開Terminal,便可正常使用 CMake 的各類指令了,也能夠在應用程序列表中使用帶 GUI 的 CMake 工具。
    • Linux安裝
      • 網址:https://cmake.org/download/,下載對應版本的CMake(32位或者64位)
      • 將下載的安裝包上傳到Linux服務器,好比:/root
      • 輸入如下命令進行解壓
        • tar -zxvf cmake-3.13.0-rc1-Linux-x86_64.tar.gz
        • 注意:後面是官網下載的對應版本的名字
      • 把解壓後的目錄更名爲:cmake
        • mv cmake-3.10.0-rc4-Linux-x86_64 cmake
      • 設置環境變量
        • 使用指令「vi .bash_profile」來設置環境變量,找到PATH=$PATH:$....這一行,後面添加CMake安裝目錄裏面的bin目錄的地址
        • 若是是在/root目錄安裝的CMake,那添加的目錄就是:/root/cmake/bin
      • 安裝完畢,環境變量設置成功以後,命令行輸入:cmake --version檢測是否安裝成功
        • 輸出:cmake version 3.13,表示安裝成功
  • 使用CMake生成項目
    • 使用Windows或者Linux生成項目
      • 進入項目目錄(CMakeLists.txt所在目錄),新建一個build文件夾,由於CMake會產生不少本身的中間文件。
      • 執行 cmake ../ 就會在build目錄產生項目文件,windows下面默認產生vs的項目。
      • 若是要產生其餘編譯器的makefile,就須要使用-G指定編譯器
        • cmake -G "MinGW Makefiles" ../
      • 可使用cmake --help 來查看使用的編譯器的名字
      • 生成項目工程文件或者makefile以後,就可使用對應的編譯器來編譯項目
    • 使用macOS生成項目
      • mac下基本操做和windows、Linux相同,不過cmake命令使用的是:cmake .. (沒有右斜槓)
    • 注意:(默認已經配置好環境變量)
  • CMake命令行選項的設置
    • 指定構建系統生成器:-G
      • 使用:-G 命令能夠指定編譯器,當前平臺支持的編譯器名稱能夠經過幫助手冊查看:cmake --help,
        例如:cmake -G "Visual Studio 15 2017" ../ 使用vs2017構建工程
    • CMakeCache.txt文件
      • cmake第一次運行一個空的構建的時候,他就會建立一個CMakeCache.txt文件,文件裏面存放了一些能夠用來制定工程的設置,好比:變量、選項等
      • 對於同一個變量,若是Cache文件裏面有設置,那麼CMakeLists文件裏就會優先使用Cache文件裏面的同名變量。
      • CMakeLists裏面經過設置了一個Cache裏面沒有的變量,那就將這個變量的值寫入到Cache裏面
      • 例子:
        • SET(var 1024)
          //變量var的值被設置成1024,若是變量var在Cache中已經存在,該命令不會覆蓋cache裏面的值
        • SET(var 1024..CACHE..)
          //若是var在Cache中存在,就優先使用Cache裏面的值,若是不存在,就將該值寫入Cache裏面​
        • SET(var..CACHE..FORCE)
          //不管Cache裏面是否存在,都始終使用該值
    • 添加變量到Cache文件中:-D
      • 注意:-D後面不能有空格,例如:cmake -DCMAKE_BUILD_TYPE:STRING=Debug
    • Cache文件中刪除變量:-U
      • 此選項和-D功能相反,從Cache文件中刪除變量,支持使用*和?通配符
    • CMake命令行模式:-E
      • CMake提供了不少和平臺無關的命令,在任何平臺均可以使用:chdir, copy, copy_if_different等
      • 可使用:cmake -E help進行查詢
    • 打印運行的每一行CMake
      • 命令行選項中:--trace,將打印運行的每一行CMake,例如windows下執行: cmake --trace ..
      • 命令:--trace-source="filename"就會打印出有關filename的執行
    • 設置編譯參數
      • add_definitions(-DENABLED),當在CMake裏面添加該定義的時候,若是代碼裏面定義了#ifdef ENABLED #endif相關的片斷,此時代碼裏面這一塊代碼就會生效
      • //add_definitions( 「-Wall -ansi –pedantic –g」)
      • 該命令現已經被取代,使用: add_compile_definitions(WITH_OPENCV2)
    • 設置默認值命令:option
      • option命令能夠幫助咱們設置一個自定義的宏,以下:
      • option(MY-MESSAGE "this is my message" ON)
      • 第一個參數就是咱們要設置的默認值的名字
      • 第二個參數是對值的解釋,相似於註釋
      • 第三個值是這個默認值的值,若是沒有聲明,CMake默認的是OFF
      • 使用:設置好以後咱們在命令行去使用的時候,也能夠去給他設定值:cmake -DMY-MESSAGE=on ../
      • 注意:使用的時候咱們應該在值的前面加「D」
      • 這條命令可將MY-MESSAGE的值設置爲on,經過這個值咱們能夠去觸發相關的判斷
  • CMake基礎知識簡介
    • 最低版本
      • 每個CMake.txt的第一行都會寫:cmake_minimum_required(VERSION 3.1),該命令指定了CMake的最低版本是3.1
      • 命令名稱cmake_minimum_required不區分大小寫
      • 設置版本範圍:cmake_minimum_required(VERSION 3.1...3.12)
        該命令表示支持3.1至3.12之間的版本
      • 判斷CMake版本:
        • if(${CMAKE_VERSION} VERSION_LESS 3.12)
        • cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
        • endif()
        • 該命令表示:若是CMake版本小於3.12,則if塊將爲true,而後將設置爲當前CMake版本;若是CMake版本高於3.12,if塊爲假​,cmake_minimum_required將被正確執行
        • 注意:若是須要支持非命令行Windows版本則需在上面的if判斷加上else分支,以下:
          cmake_minimum_required(VERSION 3.1)
          if(${CMAKE_VERSION} VERSION_LESS 3.12)
          cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
          else()
          cmake_policy(VERSION 3.12)
          endif()
    • 設置生成項目名稱
      • 使用的命令:project(MyProject)
      • 表示咱們生成的工程名字叫作:MyProject
      • 命令還能夠標識項目支持的語言,寫法:project(MyProject[C] [C++]),不過一般將後面的參數省掉,由於默認支持全部語言
      • 使用該指令以後系統會自動建立兩個變量:<projectname>_BINARY_DIR:二進制文件保存路徑、<projectname>_SOURCE_DIR:源代碼路徑
      • 執行:project(MyProject),就是定義了一個項目的名稱爲:MyProject,對應的就會生成兩個變量:_BINARY_DIR和_SOURCE_DIR,可是cmake中其實已經有兩個預約義的變量:PROJECT_BINARY_DIR和PROJECT_SOURCR_DIR
      • 關於兩個變量是否相同,涉及到是內部構建仍是外部構建
        • 內部構建
          cmake ./
          make​
        • 外部構建
          mkdir build
          cd ./build
          cmake ../
          make​​​
        • 內部構建和外部構建的不一樣在於:cmake 的工做目錄不一樣。內部構建會將cmake生成的中間文件和可執行文件放在和項目同一目錄;外部構建的話,中間文件和可執行文件會放在build目錄。
        • PROJECT_SOURCE_DIR和_SOURCE_DIR不管內部構建仍是外部構建,指向的內容都是同樣的,都指向工程的根目錄
        • PROJECT_BINARY_DIR和_BINARY_DIR指向的相同內容,內部構建的時候指向CMakeLists.txt文件的目錄,外部構建的,指向target編譯的目錄
    • 生成可執行文件
      • 語法:add_executable(exename srcname)
        exename:生成的可執行文件的名字
        srcname:以來的源文件​​
      • 該命令指定生成exe的名字以及指出須要依賴的源文件的文件名
      • 獲取文件路徑中的全部源文件
        • 命令:aux_sourcr_directory(<dir> <variable>)
        • 例子:aux_sourcr_directory(. DIR_SRCS),將當前目錄下的源文件名字存放到變量DIR_SRCS裏面 ,若是源文件比較多,直接用DIR_SRCS變量便可
      • 生成可執行文件:add_executable(Demo ${DIR_SRCS}),將生成的可執行文件命名爲:Demo.exe
    • 生成lib庫
      • 命令:add_library(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL] source1 source2 ... sourceN)
        libname:生成的庫文件的名字
        ​[SHARED|STATIC|MODULE]:生成庫文件的類型(動態庫|靜態庫|模塊)
        [EXCLUDE_FROM_ALL]:有這個參數表示該庫不會被默認構建​
        source2 ... sourceN:生成庫依賴的源文件,若是源文件比較多,可使用​aux_sourcr_directory命令獲取路徑下全部源文件,具體章節參見:CMake基礎知識簡介->生成可執行文件->獲取路徑中全部源文件
      • 例子:add_library(ALib SHARE alib.cpp)
    • 添加頭文件目錄
      • 命令1:target_include_directories(<target> [SYSTEM] [BEFORE] <INTERFACE|PUBLIC|PRIVATE> [items1...] [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
        當咱們添加子項目以後還須要設置一個include路徑,例子:
        eg:​target_include_directories(RigelEditor PUBLIC ./include/rgeditor),表示給RigelEditor 這個子項目添加一個庫文件的路徑
      • 命令2:include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 …])
        參數解析:
        ​[AFTER|BEFORE]:指定了要添加路徑是添加到原有列表以前仍是以後
        [SYSTEM]​:若指定了system參數,則把被包含的路徑當作系統包含路徑來處理
        dir1 [dir2 …]​把這些路徑添加到CMakeLists及其子目錄的CMakeLists的頭文件包含項目中
        至關於g++選項中的-l的參數的做用
        ​​舉例:
        include_directories("/opt/MATLAB/R2012a/extern/include")
      • 兩條指令的做用都是講將include的目錄添加到目標區別在於include_directories是CMake編譯全部目標的目錄進行添加,target_include_directories是將CMake編譯的指定的特定目標的包含目錄進行添加
    • 添加須要連接的庫文件路徑
      • 命令1:target_link_libraries(<target> [item1 [item2 [...]]] [[debug|optimized|general] <item>] ...)
        • 做用:爲給定的目標設置連接時使用的庫(設置要連接的庫文件的名稱)
        • eg:target_link_libraries(MyProject a b.a c.so)   //將若干庫文件連接到hello中,target_link_libraries裏的庫文件的順序符合gcc/g++連接順序規則,即:被依賴的庫放在依賴他的庫的後面,若是順序有錯,連接將會報錯
        • 關鍵字:debug對應於調試配置
        • 關鍵字:optimized對應於全部其餘的配置類型
        • 關鍵字:general對應於全部的配置(該屬性是默認值)
      • 命令2:link_libraries
        • 做用:給當前工程連接須要的庫文件(全路徑)
        • eg:link_libraries(("/opt/MATLAB/R2012a/bin/glnxa64/libeng.so")//必須添加帶名字的全路徑
      • 區別:link_libraries和target_link_libraries命令的區別:target_link_libraries能夠給工程或者庫文件設置其須要連接的庫文件,並且不須要填寫全路徑,可是link_libraries只能給工程添加依賴的庫,並且必須添加全路徑
      • 添加須要連接的庫文件目錄
        • 命令:link_directories(添加須要連接的庫文件目錄)
        • 語法:link_directories(directory1 directory2 ...)
        • 例子:link_directories("/opt/MATLAB/R2012a/bin/glnxa64")
      • 指令的區別:指令的前綴帶target,表示針對某一個目標進行設置,必須指明設置的目標;include_directories是在編譯時用,指明.h文件的路徑;link_directoeies是在連接時用的,指明連接庫的路徑;target_link_libraries是指明連接庫的名字,也就是具體誰連接到哪一個庫。link_libraries不經常使用,由於必須指明帶文件名全路徑
    • 控制目標屬性
      • 以上的幾條命令的區分都是:是否帶target前綴,在CMake裏面,一個target有本身的屬性集,若是咱們沒有顯示的設置這些target的屬性的話,CMake默認是由相關的全局屬性來填充target的屬性,咱們若是須要單獨的設置target的屬性,須要使用命令:set_target_properties()
      • 命令格式
        格式:
        ​set_target_properties(target1 target2 ...
        PROPERTIES
        屬性名稱1 值
        屬性名稱2 值
        ...
        )
      • 控制編譯選項的屬性是:COMPILE_FLAGS
      • 控制連接選項的屬性是:LINK_FLAGS
      • 控制輸出路徑的屬性:EXECUTABLE_OUTPUT_PATH(exe的輸出路徑)、LIBRARY_OUTPUT_PATH(庫文件的輸出路徑)
      • 舉例:
        命令:
        ​set_target_properties(exe
        PROPERTIES
        LINK_FLAGS -static
        LINK_FLAGS_RELEASE -s
        )
      • 這條指令會使得exe這個目標在全部的狀況下都採用-static選項,並且在release build的時候 -static -s 選項。可是這個屬性僅僅在exe這個target上面有效
  • 變量和緩存
    • 局部變量
      • CMakeLists.txt至關於一個函數,第一個執行的CMakeLists.txt至關於主函數,正常設置的變量不能跨越CMakeLists.txt文件,至關於局部變量只在當前函數域裏面做用同樣,
      • 設置變量:set(MY_VARIABLE "value")
      • 變量的名稱一般大寫
      • 訪問變量:${MY_VARIABLE}
    • 緩存變量
      • 緩存變量就是cache變量,至關於全局變量,都是在第一個執行的CMakeLists.txt裏面被設置的,不過在子項目的CMakeLists.txt文件裏面也是能夠修改這個變量的,此時會影響父目錄的CMakeLists.txt,這些變量用來配置整個工程,配置好以後對整個工程使用。
      • 設置緩存變量:set(MY_CACHE_VALUE "cache_value" CACHE INTERNAL "THIS IS MY CACHE VALUE")
        //THIS IS MY CACHE VALUE,這個字符串至關於對變量的描述說明,不能省略,但能夠本身隨便定義
    • 環境變量
      • 設置環境變量:set(ENV{variable_name} value)
      • 獲取環境變量:$ENV{variable_name}
    • 內置變量
      • CMake裏面包含大量的內置變量,和自定義的變量相同,經常使用的有如下:
      • CMAKE_C_COMPILER:指定C編譯器
      • CMAKE_CXX_COMPILER:指定C++編譯器
      • EXECUTABLE_OUTPUT_PATH:指定可執行文件的存放路徑
      • LIBRARY_OUTPUT_PATH:指定庫文件的放置路徑
      • CMAKE_CURRENT_SOURCE_DIR:當前處理的CMakeLists.txt所在的路徑
      • CMAKE_BUILD_TYPE:控制構建的時候是Debug仍是Release
        命令:set(CMAKE_BUILD_TYPE Debug)
      • CMAKE_SOURCR_DIR:不管外部構建仍是內部構建,都指的是工程的頂層目錄(參考project命令執行以後,生成的_SOURCR_DIR以及CMake預約義的變量PROJECT_SOURCE_DIR)
      • CMAKE_BINARY_DIR:內部構建指的是工程頂層目錄,外部構建指的是工程發生編譯的目錄(參考project命令執行以後,生成的_BINARY_DIR以及CMake預約義的變量PROJECT_BINARY_DIR)
      • CMAKE_CURRENT_LIST_LINE:輸出這個內置變量所在的行
    • 緩存
      • 緩存就是以前提到的CMakeCache文件,參見:CMake命令行選項的設置->CMakeCache.txt文件
  • CMake基本控制語法
    • If
      • 基本語法
        if (expression)
            COMMAND1(ARGS ...)
            COMMAND2(ARGS ...)
            ...
        else (expression)
            COMMAND1(ARGS ...)
            COMMAND2(ARGS ...)
            ...
        endif (expression)
        注意:ENDIF要和IF對應​
        • if (expression),expression不爲:空,0,N,NO,OFF,FALSE,NOTFOUND或< var >_NOTFOUND,爲真
        • IF (not exp),與上面相反
        • if (var1 AND var2),var1且var2都爲真,條件成立
        • if (var1 OR var2),var1或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 (string MATCHES regex) 當給定變量或字符串能匹配正則表達式regex時,爲真
          例:
          IF ("hello" MATCHES "ell") 
          MESSAGE("true") 
          ENDIF ("hello" MATCHES "ell")
      • 數字表達式
        • if (var LESS number),var小於number爲真
        • if (var GREATER number),var大於number爲真
        • if (var EQUAL number),var等於number爲真
      • 字母表順序比較
        • IF (var1 STRLESS var2),var1字母順序小於var2爲真
        • IF (var1 STRGREATER var2),var1字母順序大於var2爲真
        • IF (var1 STREQUAL var2),var1和var2字母順序相等爲真
    • While
      • 語法結構
        WHILE(condition)
        COMMAND1(ARGS ...)
        COMMAND2(ARGS ...)
        ...
        ENDWHILE(condition)
      • 真假條件的判斷參考if
    • Foreach
      • FOREACH有三種使用形式的語法,且每一個FOREACH都須要一個ENDFOREACH()與之匹配。
      • 列表循環
        • 語法
          FOREACH(loop_var arg1 arg2 ...)
          COMMAND1(ARGS ...)
          COMMAND2(ARGS ...)
          ...
          ENDFOREACH(loop_var)​
        • 例子
          eg:
          ​AUX_SOURCE_DIRECTORY(. SRC_LIST)
          FOREACH(F ${SRC_LIST})
          MESSAGE(${F})
          ENDFOREACH(F)
        • 例子中,先將當前路徑的源文件名放到變量SRC_LIST裏面,而後遍歷輸出文件名
      • 範圍循環
        • 語法
          FOREACH(loop_var RANGE total)
          COMMAND1(ARGS ...)
          COMMAND2(ARGS ...)
          ...
          ENDFOREACH(loop_var)
        • 例子
          eg:
          ​FOREACH(VAR RANGE 100)
          MESSAGE(${VAR})
          ENDFOREACH(VAR)
          ​​
        • 例子中默認起點爲0,步進爲1,做用就是輸出:0~100
      • 範圍步進循環
        • 語法
          FOREACH(loop_var RANGE start stop [step])
          COMMAND1(ARGS ...)
          COMMAND2(ARGS ...)
          ...
          ENDFOREACH(loop_var)
        • 例子
          eg:
          FOREACH(A RANGE 0 100 10)
          MESSAGE(${A})
          ENDFOREACH(A)​
        • 例子中,起點是0,終點是100,步進是10,輸出:0,10,20,30,40,50,60,70,80,90,100
  • 構建規範以及構建屬性//
    • 用於指定構建規則以及程序使用要求的指令:target_include_directories(), target_compile_definitions(), target_compile_options()
    • 指令格式
      • target_include_directories(<target> [SYSTEM] [BEFORE]<INTERFACE|PUBLIC|PRIVATE> [items1...] [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
        Include的頭文件的查找目錄,也就是Gcc的[-Idir...]選項
      • target_compile_definitions(<target> <INTERFACE|PUBLIC|PRIVATE> [items1...][<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
        經過命令行定義的宏變量
      • target_compile_options(<target> [BEFORE] <INTERFACE|PUBLIC|PRIVATE> [items1...] [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...]
        gcc其餘的一些編譯選項指定,好比-fPIC
        ​​
      • -fPIC選項說明
        說明:-fPIC 做用於編譯階段,告訴編譯器產生與位置無關代碼(Position-Independent Code),
          則產生的代碼中,沒有絕對地址,所有使用相對地址,故而代碼能夠被加載器加載到內存的任意
          位置,均可以正確的執行。這正是共享庫所要求的,共享庫被加載時,在內存的位置不是固定的。
      • -ldir選項說明
        說明:在你是用 #include "file" 的時候, gcc/g++ 會先在當前目錄查找你所制定的頭文件, 若是沒有找到, 他會到缺省的頭文件目錄找, 若是使用 -I 制定了目錄,他會先在你所制定的目錄查找, 而後再按常規的順序去找。
    • 以上的額三個命令會生成INCLUDE_DIRECTORIES, COMPILE_DEFINITIONS, COMPILE_OPTIONS變量的值,。或者 INTERFACE_INCLUDE_DIRECTORIES,INTERFACE_COMPILE_DEFINITIONS, INTERFACE_COMPILE_OPTIONS的值.
    • 這三個命令都有三種可選模式: PRIVATE, PUBLIC。 INTERFACE. PRIVATE模式僅填充不是接口的目標屬性; INTERFACE模式僅填充接口目標的屬性.PUBLIC模式填充這兩種的目標屬性。
  • 宏和函數
    • CMake裏面能夠定義本身的函數(function)和宏(macro)
    • 區別1:範圍。函數是有範圍的,而宏沒有。若是但願函數設置的變量在函數的外部也能夠看見,就須要使用PARENT_SCOPE來修飾,可是函數對於變量的控制會比較好,不會有變量泄露
    • 例子
      • 宏(macro)
        eg:
        ​macro( [arg1 [arg2 [arg3 ...]]])
             COMMAND1(ARGS ...)
             COMMAND2(ARGS ...)
             ...
        endmacro()
      • 函數(function)
        eg:
        ​function( [arg1 [arg2 [arg3 ...]]])
             COMMAND1(ARGS ...)
             COMMAND2(ARGS ...)
             ...
        endfunction()
    • 函數和宏的區別還在於,函數很難將計算結果傳出來,使用宏就能夠將一些值簡單的傳出來
    • 例子
      eg:
      macro(macroTest)
           set(test1 "aaa")
      endmacro()

      function(funTest)
           set(test2 "bbb")
      endfunction()

      macroTest()
      message("${test1}")

      funTest()
      message("${test2}")
    • 運行上面這個代碼,就會顯示「aaa」,由於函數裏面的test1是局部的,出了這個函數就出了他的做用域
  • 和其餘文件的交互
    • 在代碼中使用CMake中定義的變量
      • 命令:configure_file
      • 做用:讓普通文件也能使用CMake中的變量。
      • 語法
        configure_file(<input> <output>
        [COPYONLY] [ESCAPE_QUOTES] [@ONLY]
        [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])​
        解釋:拷貝一個 <input>(輸入文件) 文件到 <output> (輸出文件),而且替換輸入文件中被 @VAR@ 或者 ${VAR} 引用的變量值。每個變量將被替換成當前的變量值​
      • 參數解析
        • COPYONLY:只拷貝文件,不進行任何的變量替換。這個選項在指定了 NEWLINE_STYLE 選項時不能使用(無效)。
        • ESCAPE_QUOTES:躲過任何的反斜槓(C風格)轉義。
          注:躲避轉義,好比你有個變量在CMake中是這樣的 set(FOO_STRING "\"foo\"") 那麼在沒有 ESCAPE_QUOTES 選項的狀態下,經過變量替換將變爲 ""foo"",若是指定了 ESCAPE_QUOTES 選項,變量將不變。
        • @ONLY:限制變量替換,讓其只替換被 @VAR@ 引用的變量(那麼 ${VAR} 格式的變量將不會被替換)。這在配置 ${VAR} 語法的腳本時是很是有用的。
        • NEWLINE_STYLE <style>:指定輸出文件中的新行格式。UNIX 和 LF 的新行是 \n ,DOS 和 WIN32 和 CRLF 的新行格式是 \r\n 。 這個選項在指定了 COPYONLY 選項時不能使用(無效)。
    • CMake對文件的操做
      • file命令
        • file(WRITE filename "message to write"... )
        • 解釋:WRITE選項會寫一條消息到名爲filename中,若是文件存在,則會覆蓋原文件,若是文件不存在,他將建立該文件
        • file(APPEND filename "message to write"... )
        • 解釋:APPEND選項和WRITE選項同樣,只是APPEND會寫到文件的末尾
        • file(READ filename variable [LIMIT numBytes] [OFFSET offset] [HEX])
        • 解釋:READ選項會將讀取的文件內容存放到變量variable ,讀取numBytes個字節,從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])
        • 解釋:STRINGS標誌,將會從一個文件中將ASCII字符串的list解析出來,而後儲存在variable 變量中,文件中的二進制數據將會被忽略,回車換行符會被忽略(能夠設置NO_HEX_CONVERSION選項來禁止這個功能)。LIMIT_COUNT:設定了返回字符串的最大數量;LIMIT_INPUT:設置了從輸入文件中讀取的最大字節數;LIMIT_OUTPUT:設置了在輸出變量中容許存儲的最大字節數;LENGTH_MINIMUM:設置了返回字符串的最小長度,小於該長度的字符串將會被忽略;LENGTH_MAXIMUM設置了返回字符串的最大長度,大於該長度的字符串將會被忽略;NEWLINE_CONSUME:該標誌容許新行被包含到字符串中,而不是終止他們;REGEX:指定了返回的字符串必須知足的正則表達式
        • 典型的使用方式:file(STRINGS myfile.txt myfile)
        • 該命令在變量myfile中儲存了一個list,該list每一項是myfile.txt中的一行文本
        • file(GLOB variable [RELATIVE path] [globbing expressions]...)
        • 解釋:GLOB:該選項將會爲全部匹配表達式的文件生成一個文件list,並將該list存放在variable 裏面,文件名的查詢表達式和正則表達式相似,
        • 查詢表達式的例子:①*.cpp -匹配全部後綴是.cpp的文件②*.vb? -匹配文件後綴是.vba——.vbz的文件③f[3-5].txt :匹配f3.txt,f4.txt,f5.txt文件
        • file(GLOB_RECURSE variable [RELATIVE path] [FOLLOW_SYMLINKS] [globbing expressions]...)
        • 解釋:GLOB_RECURSE會生成一個相似於一般GLOB選項的list,不過該選項能夠遞歸查找文件中的匹配項
        • 好比:/dir/*.py -就會匹配全部在/dir文件下面的python文件,
        • 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_PATH選項會肯定從direcroty參數到指定文件的相對路徑,而後存到變量variable中
        • file(TO_CMAKE_PATH path result)
        • 解釋:TO_CMAKE_PATH選項會把path轉換爲一個以unix的 / 開頭的cmake風格的路徑
        • file(TO_NATIVE_PATH path result)
        • 解釋:TO_NATIVE_PATH選項與TO_CMAKE_PATH選項很類似,可是它會把cmake風格的路徑轉換爲本地路徑風格
        • file(DOWNLOAD url file [TIMEOUT timeout] [STATUS status] [LOG log] [EXPECTED_MD5 sum] [SHOW_PROGRESS])
        • 解釋:DOWNLOAD將給定的url下載到指定的文件中,若是指定了LOG log,下載的日誌將會被輸出到log中,若是指定了STATUS status選項下載操做的狀態就會被輸出到status裏面,該狀態的返回值是一個長度爲2的list,list第一個元素是操做的返回值,是一個數字 ,第二個返回值是錯誤的字符串,錯誤信息若是是0,就表示沒有錯誤;若是指定了TIMEOUT time選項,time秒以後,操做就會推出。若是指定了EXPECTED_MD5 sum選項,下載操做會認證下載的文件的實際MD5和是否與指望值相匹配,若是不匹配,操做將返回一個錯誤;若是指定了SHOW_PROGRESS,進度信息會被打印出來,直到操做完成
      • source_group命令
        • 使用該命令能夠將文件在VS中進行分組顯示
        • source_group("Header Files" FILES ${HEADER_FILES})
        • 以上命令是將變量HEADER_FILES裏面的文件,在VS顯示的時候都顯示在「Header Files」選項下面
  • 如何構建項目
    • 工程文件結構
      • lib文件夾
        • libA.c
        • libB.c
        • CMakeLists.txt
      • include文件夾
        • includeA.h
        • inclueeB.h
        • CMakeLists.txt
      • main.c
      • CMakeLists.txt
    • 第一層CMakeLists
      內容以下:
      #項目名稱
      project(main)

      #須要的cmake最低版本
      cmake_minium_required(VERSION 2.8)

      #將當前目錄下的源文件名都賦給DIR_SRC目錄
      aux_source_directories(. DIR_SRC)

      #添加include目錄
      include_directories(include)

      #生成可執行文件
      add_executable(main ${DIR_SRC})​​​​​​​​​​​​​​

      #添加子目錄
      add_subdirectories(lib)

      #將生成的文件與動態庫相連
      target_link_libraries(main test)​​​​​​
      #test是lib目錄裏面生成的
    • lib目錄下的CMakeLists
      內容以下:
      #將當前的源文件名字都添加到DIR_LIB變量下
      ​aux_source_director(. DIR_LIB)

      ​​#生成庫文件命名爲test
      add_libraries(test ${DIR_LIB})​​
    • include目錄的CMakeLists能夠爲空,由於咱們已經將include目錄包含在第一層的文件裏面
  • 運行其餘程序
    • 在配置時運行命令
      • 指令:execute_process
        參數:
        execute_process(COMMAND <cmd1> [args1...]]
        [COMMAND <cmd2> [args2...] [...]]
        [WORKING_DIRECTORY <directory>]
        [TIMEOUT <seconds>]
        [RESULT_VARIABLE <variable>]
        [OUTPUT_VARIABLE <variable>]
        [ERROR_VARIABLE <variable>]
        [INPUT_FILE <file>]
        [OUTPUT_FILE <file>]
        [ERROR_FILE <file>]
        [OUTPUT_QUIET]
        [ERROR_QUIET]
        [OUTPUT_STRIP_TRAILING_WHITESPACE]
        [ERROR_STRIP_TRAILING_WHITESPACE])​
      • 做用:這條指令能夠執行系統命令,將輸出保存到cmake變量或文件中去,運行一個或多個給定的命令序列,每個進程的標準輸出經過管道流向下一個進程的標準輸入。
      • 參數解析
        • COMMAND:子進程的命令行,CMake使用操做系統的API直接執行子進程,全部的參數逐字傳輸,沒有中間腳本參與,像「>」的輸出重定向也會被直接的傳輸到子進程裏面,當作普通的參數進行處理。
        • WORKING_DIRECTORY:指定的工做目錄將會設置爲子進程的工做目錄
        • TIMEOUT:子進程若是在指定的秒數以內沒有結束就會被中斷
        • RESULT_VARIABLE:變量被設置爲包含子進程的運算結果,也就是命令執行的最後結果將會保存在這個變量之中,返回碼將是來自最後一個子進程的整數或者一個錯誤描述字符串
        • OUTPUT_VARIABLE、ERROR_VARIABLE:輸出變量和錯誤變量//
        • INPUT_FILE、OUTPUT_FILE、ERROR_FILE:輸入文件、輸出文件、錯誤文件//
        • OUTPUT_QUIET、ERROR_QUIET:輸出忽略、錯誤忽略,標準輸出和標準錯誤的結果將被默認忽略
        • 例子
          eg:
          ​set(MAKE_CMD "/src/bin/make.bat")
          MESSAGE("COMMAND: ${MAKE_CMD}")
          execute_process(COMMAND "${MAKE_CMD}"
          RESULT_VARIABLE CMD_ERROR
          OUTPUT_FILE CMD_OUTPUT)
          MESSAGE( STATUS "CMD_ERROR:" ${CMD_ERROR})
          MESSAGE( STATUS "CMD_OUTPUT:" ${CMD_OUTPUT})
          輸出:
          ​​COMMAND:/src/bin/make.bat
          CMD_ERROR:​No such file or directory
          CMD_OUTPUT:​
          (由於這個路徑下面沒有這個文件)
    • 在構建的時運行命令
      https://www.jianshu.com/p/0fc0e1613587
      • 例子(調用python腳本生成頭文件):
        find_package(PythonInterp REQUIRED)
        add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/include/Generated.hpp"
        COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/scripts/GenerateHeader.py" --argument
        DEPENDS some_target)
        add_custom_target(generate_header ALL
        DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/include/Generated.hpp")
        install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/Generated.hpp DESTINATION include)
      • find_package:查找連接庫
        若是編譯的過程使用了外部的庫,事先並不知道其頭文件和連接庫的位置,得在編譯命令中加上包含外部庫的查找路徑,CMake中使用find_package方法
        • find_package()命令查找***.cmake的順序
          • 介紹這個命令以前,首先得介紹一個變量:CMAKE_MODULE_PATH
            • 工程比較大的時候,咱們會建立本身的cmake模塊,咱們須要告訴cmake這個模塊在哪裏,CMake就是經過CMAKE_MODULE_PATH這個變量來獲取模塊路徑的
            • 咱們使用set來設置模塊的路徑:set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
            • 若是上面的沒有找到,就會在../.cmake/packages或者../uesr/local/share/中的包目錄中查找:<庫名字大寫>Config.cmake或者<庫名字小寫>-config.cmake。這種查找模式稱做Config模式。
            • 若是找到這個包,則能夠經過在工程的頂層目錄中的CMakeLists.txt中添加:include_directories(<Name>_INCLUDE_DIRS)來包含庫的頭文件,使用命令:target_link_libraries(源文件 <NAME>_LIBRARIES)將源文件以及庫文件連接起來
            • 不管哪種方式,只要找到***.cmake文件,***.cmake裏面都會定義下面這些變量
              <NAME>_FOUND
              <NAME>_INCLUDE_DIRS or <NAME>_INCLUDES
              <NAME>_LIBRARIES or <NAME>_LIBRARIES or <NAME>_LIBS
              <NAME>_DEFINITIONS
              注:<NAME>就是庫名​
            • CMake中使用:cmake --help-module-list命令來查看當前CMake中有哪些支持的模塊
          • find_package(<Name>)命令首先會在模塊路徑,也就是剛纔咱們介紹的CMAKE_MODULE_PATH變量裏面存放的路徑中查找Find<Name>.cmake。查找路徑依次爲:變量${CMAKE_MODULE_PATH}中的全部目錄,這種查找模式被稱爲Module模式。
          • find_package
            • 命令參數
            • FIND_PACKAGE( <name> [version] [EXACT] [QUIET] [NO_MODULE] [ [ REQUIRED | COMPONENTS ] [ componets... ] ] )
            • version:須要一個版本號,給出這個參數而沒有給出EXACT,那個就是找到和給出的這個版本號相互兼容就符合條件
            • EXACT:要求版本號必須和version給出的精確匹配。
            • QUIET:會禁掉查找的包沒有被發現的警告信息。對應於Find<Name>.cmake模塊裏面的的NAME_FIND_QUIETLY變量。
            • NO_MODULE:給出該指令以後,cmake將直接跳過Module模式的查找,直接使用Config模式查找。查找模式詳見下方
            • REQUIRED:該選項表示若是沒有找到須要的包就會中止而且報錯
            • COMPONENTS:在REQUIRED選項以後,或者若是沒有指定REQUIRED選項可是指定了COMPONENTS選項,在COMPONENTS後面就能夠列出一些與包相關部分組件的清單
            • 搜索原理
            • Cmake能夠支持不少外部內部的庫,經過命令能夠查看當前cmake支持的模塊有哪些: cmake --help-module-list 。或者直接查看模塊路徑。Windosw的路徑在cmak的安裝目錄:..\share\cmake-3.13\Modules
            • cmake自己是不提供任何搜索庫的便捷方法,全部搜索庫並給變量賦值的操做必須由cmake代碼完成
            • find_psckage的搜索模式:
            • Module模式:搜索CMAKE_MODULE_PATH指定路徑下的FindXXX.cmake文件(XXX就是咱們要搜索的庫的名字),這個CMAKE_MODULE_PATH變量是cmake預先定義,可是沒有值,咱們一旦給這個變量賦值以後,cmake就會最高優先級的在這個變量裏面去查找,沒有找到就在本身的安裝庫裏面去找有沒有FindXXX.cmake模塊,找到以後,執行該文件從而找到XXX庫,其中具體查找庫並給XXX_INCLUDE_DIR和XXX_LIBRARIES這兩個變量賦值的操做有FindXXX.cmake模塊完成
            • Config模式:若是Module模式沒有找到,則啓用Config模式查找,搜索XXX_DIR路徑下的XXXConfig.cmake文件,執行該文件從而找到XXX庫,其中查找庫以及給XXX_INCLUDE_DIR和XXX_LIBRARY賦值的操做都是由XXXConfig.cmake模塊完成
            • cmake默認採起的時Module模式,若是Module模式沒有找到,纔會使用Config模式查找,
            • ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
              • version選項和EXACT

 

  • -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  • COMPONENTS選項,有些庫不是一個總體好比Qt,其中還包含QtOpenGL和QtXml組件,當咱們須要使用庫的組件的時候,就使用COMPONENTS這個選項
  • find_package(Qt COMPONENTS QtOpenGL QtXml REQUIRED)
  • -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  • 找到以後給一些預約義的變量賦值
  • 不管哪種查找模式,只要找到包以後,就會給如下變量賦值:<NAME>_FOUND,<NAME>_INCLUDE_DIRS或者<NAME>_INCLUDES,<NAME>_LIBRARIES,<NAME>_DEFINITIONS。這些變量都在Find<NAME>.cmake文件中。
  • 咱們能夠在CMakeLists.txt中使用<NAME>_FOUND變量來檢測擺包是否被找到,
  • -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  • find_package的本質是執行一個.cmake文件,至關於cmake的內置的腳本,這個腳本將設置咱們以前提到的相關的變量,至關於根據傳進來的參數來使用一個查找模塊,每個經常使用的庫在cmake裏面就有一個對應的查找模塊。
  • ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  • find模塊的編寫流程:
  • 首先使用:find_path和find_library查找模塊的頭文件以及庫文件,而後將結果放到<NAME>_INCLUDE_DIR和<NAME>_LIBRARY裏面
    • find_path():
    • find_path(<VAR> name1 [path1 path2 ...])
    • 該命令搜索包含某個文件的路徑,用於給定名字的文件所在路徑,
    • 一條名爲:<VAR>的變量的Cache將會被建立。
    • 若是在某個文件下面發現了該文件,路徑就會被儲存到變量裏面,除非變量被清除,不然搜搜將不會進行。
    • 若是沒有發現該文件,<VAR>裏面儲存的就是<VAR>-NOTFOUND
    • find_library():
    • find_library(<VAR> name1 [path1 path2 ...])
    • 查找一個庫文件
    • 設置:<NAME>_INCLUDE_DIRS爲<NAME>_INCLUDE_DIR<dependency1>_INCLUDE_DIRS ...
    • 設置 <name>_LIBRARIES 爲 <name>_LIBRARY <dependency1>_LIBRARIES ...
    • 調用宏 find_package_handle_standard_args() 設置 <name>_FOUND 並打印或失敗信息
    • ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    • 咱們以Cmake裏面自帶的bzip2庫爲例,Cmake的module目錄裏面有一個:FindBZip.cmake模塊,咱們使用find_package(BZip2),而後CMake就會給相關的變量賦值,咱們就能夠調用這個模塊,就可使用模塊裏面的變量,模塊裏面的變量有哪些,咱們可使用命令: cmake --help-module FindBZip2來查看,最後面的參數就是帶上Find前綴以後的模塊的名字。
      • 假如一個程序須要使用BZip2庫,編譯器須要知道bzlib.h的位置,連接器須要知道bzip2庫(動態連接:.so或者.dll)

 

  • 添加庫的指令:find_package(BZip2 REQUIRED)
  • CMake裏面又不少內置的庫,當咱們使用find_package查找包的時候CMake首先會去CMAKE_MODULE_PATH這個變量存放的路徑裏面去尋找
  • 注意:CMAKE_MODULE_PATH的路徑設置須要在頂層的CMakeLists.txt裏面去設置。
  • find_package以後,變量:BZIP_INCLUDE_DIRS以及BZIP2_LIBRARIES就會被設置,而後咱們使用include_directories以及target_link_libraries來使用便可
  • ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  • 使用一個cmake裏面沒有帶的庫
  • cmake的/share/cmake-X.XX/Modules裏面帶的都是一些經常使用的庫,若是咱們如今須要使用一個cmake裏面沒有提供給咱們find模塊的庫,作法以下:
  • 首先模擬生成一個生成lib文件
    • 建立工程,名爲:ThirdLIB
    • 生成一個lib文件,名爲:ThirdDLL.lib
    • lib文件裏面只提供了一個求和的add函數,返回兩個int值的和
      • CMakeLists.txt裏面設置CMAKE_MODULE_PATH,這裏設置的是本地的路徑,這個路徑存放的find模塊

 

  • 編寫本身的find模塊
    • 注意:cmake使用find_package查找使用的庫,當咱們把庫名字傳進去以後,cmake會在按照指定的模式查找一個:Find<NAME>.cmake的文件,經常使用的庫,cmake都會提供對應的.cmake文件,可是如今咱們使用的是本身編寫的庫,因此cmake是沒有提供的,須要本身編寫
    • 編寫大體流程已經給出,咱們編寫的文件名必須是:Find<Name>.cmake,如今就是「FindThidrDLL.cmake」
      • FindThirDLL.cmake內容以下

 

  • 修改CMakeLists.txt文件,在裏面使用find_package命令添加模塊、

 

  • 完成以後,打開生成的工程,查看工程的依賴項,就會有ThirdLIB.lib的選項

 

    • ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    • 當咱們在CMake裏面使用一個庫時候,如何在網上查找,好比如今須要查找:apr庫,在goole裏面搜索:find package apr cmake,就能夠直接找到對應的CMake腳本。而後複製粘貼,建立.cmake文件,放在工程根目錄下面的modules目錄,沒有則建立之
    • ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    • add_custom_command:(1)爲某一個工程添加一個自定義的命令
      add_custom_command(TARGET target
      PRE_BUILD | PRE_LINK| POST_BUILD
      COMMAND command1[ARGS] [args1...]
      [COMMAND command2[ARGS] [args2...] ...]
      [WORKING_DIRECTORYdir]
      [COMMENT comment][VERBATIM])
      做者:drybeans
      連接:https://www.jianshu.com/p/66df9650a9e2
      來源:簡書
      簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。
      • 執行命令的時間由第二個參數決定
        1.PRE_BUILD - 命令將會在其餘依賴項執行前執行
        2.PRE_LINK - 命令將會在其餘依賴項執行完後執行
        3.POST_BUILD - 命令將會在目標構建完後執行。
      • 例子1:
        add_custom_command (
        TARGET ${PROJECT_NAME}
        POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E sleep 5
        )
        #目標就是TARGET後面跟的工程​當PROJECT_NAME被生成的時候就會執行COMMAND後面的命令
      • 例子2:
        add_custom_command(TARGET test_elf
        ​PRE_BUILD
        COMMAND
        move E:/cfg/start.o ${CMAKE_BINARY_DIR}/. &&
        )
        #在test_el執行依賴以前,將start.o文件複製到編譯目錄
      • add_custom_command:(2)添加自定義命令來產生一個輸出
         add_custom_command(OUTPUT output1 [output2 ...]
                             COMMAND command1[ARGS] [args1...]
                             [COMMAND command2 [ARGS] [args2...] ...]
                             [MAIN_DEPENDENCYdepend]
                             [DEPENDS[depends...]]
                             [IMPLICIT_DEPENDS<lang1> depend1 ...]
                             [WORKING_DIRECTORYdir]
                             [COMMENT comment] [VERBATIM] [APPEND])
        • 其中ARGS選項 是爲了向後兼容,MAIN_DEPENDENCY選項是針對Visual Studio給出一個建議,這兩選項能夠忽略
        • COMMAND:指定一些在構建階段執行的命令。若是指定了多於一條的命令,他會按照順序去執行。若是指定了一個可執行目標的名字(被add_executable()命令建立),他會自動被在構建階段建立的可執行文件的路徑替換,
        • DEPENDS:指定目標依賴的文件,若是依賴的文件是和CMakeLists.txt相同目錄的文件,則命令就會在CMakeLists.txt文件的,目錄執行。若是沒有指定DEPENDS,則只要缺乏OUTPUT,該命令就會執行。若是指定的位置和CMAkeLists.txt不是同一位置,會先去建立依賴關係,先去將依賴的目標或者命令先去編譯。
        • WORKING_DIRECTORY:使用給定的當前目錄執行命令,若是是相對路徑,則相對於當前源目錄對應的目錄結構進行解析
        • 例子
          #首先生成creator的可執行文件
          ​add_executable(creator creator.cxx)

          #獲取EXE_LOC的LOCATION屬性存放到creator裏面​​
          get_target_property(creator EXE_LOC LOCATION)

          #生成created.c文件
          add_custom_command (
          OUTPUT ${PROJECT_BINARY_DIR}/created.c
          DEPENDS creator
          COMMAND ${EXE_LOC}
          ARGS ${PROJECT_BINARY_DIR}/created.c
          )

          #使用上一步生成的created.c文件來生成Foo可執行文件​​
          add_executable(Foo ${PROJECT_BINARY_DIR}/created.c)
        • 注意:不要再多個相互獨立的文件中使用該命令產生相同的文件,防止衝突。
        • add_custom_target:增長定製目標
          add_custom_target(Name [ALL] [command1 [args1...]]
          [COMMAND command2 [args2...] ...]
          [DEPENDS depend depend depend ... ]
          [BYPRODUCTS [files...]]
          [WORKING_DIRECTORY dir]
          [COMMENT comment]
          [VERBATIM] [USES_TERMINAL]
          [SOURCES src1 [src2...]])
          • 命令 add_custom_target 能夠增長定製目標,經常用於編譯文檔、運行測試用例等。
        • add_custom_command和add_custom_target的區別
          • 命令命名裏面的區別就在於:command和target,前者是自定義命令,後者是自定義目標
          • 目標:通常來講目標是調用:add_library或者add_executable生成的exe或者庫,他們具備許多屬性集,這些就是所謂目標,而使用add_custom_target定義的叫作自定義目標,所以這些「目標」區別於正常的目標,他們不生成exe或者lib,可是仍然會具備一些正常目標相同的屬性,構建他們的時候,只是調用了爲他們設置的命令,若是自定義目標對於其餘目標有依賴,那麼就會優先生成依賴的那些目標
          • 自定義命令:自定義命令不是一個「可構建」的對象,而且沒有能夠設置的屬性,自定義命令是一個在構建依賴目標以前被調用的命令,自定義命令的依賴能夠經過add_custom_command(TARGET target …)形式顯式設置,也能夠經過add_custom_command(OUTPUT output1 …)生成文件的形式隱式設置。顯示執行的時候,每次構建目標,首先會執行自定義的命令,隱式執行的時候,若是自定義的命令依賴於其餘文件,則在構建目標的時候先去執行生成其餘文件。
    • 如何添加C++項目中的經常使用選項
      如:如何支持C++十一、如何支持IDE等
      • 如何激活C++11功能
        語法:target_compile_features(<target> <PRIVATE|PUBLIC|INTERFACE> <feature> [...])
        • target_compile_features(<project_name> PUBLIC cxx_std_11)
        • 參數target必須是由:add_executable或者add_library生成的目標
        • 另一種支持C++標準的方法
          #設置C++標準級別
          ​set(CMAKE_CXX_STANDARD 11)

          #告訴CMake使用他​它
          set(CMAKE_CXX_STANDARD_REQUIRED ON)

          #(可選)​​確保-std=C++11
          set(CMAKE_CXX_EXTENSIONS OFF)
      • CMake的過程間優化
        • 若是編譯器不支持,就會將設置的過程間優化標記爲錯誤,可使用命令:check_ipo_supported()來查看
          #檢測編譯器是否支持過程間優化
          ​check_ipo_supported(RESULT result)

          #若是不支持,判斷進不去​​
          if(result)
          #爲工程foo設置​過程間優化
          set_target_properties(foo PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
          endif()
      • CMake的option簡介
        • option命令能夠設置默認值
          option(address "this is path for value" ON)
        • 命令表示,當用戶沒有設置address的時候,默認值就是ON,當用戶顯示的設置address的時候,address裏面就是用戶設置的值
        • 注意:加入有一些變量依賴了address,可是這些變量的使用在option語句以前,此時對於這些變量來講,address仍是屬於沒有定義的。
        • 在用戶沒有提供ON或者OFF的時候,默認是OFF。若是option有改變,必定要清理CMakeCache.txt文件和CMakeFiles文件夾
        • CMake編譯選項的管理
          • 在工程的根目錄,編寫CMakeLists.txt,另外單首創建option.txt文件,專門管理編譯選項
          • CMakeLists.txt中加入:
            include option.txt​
          • option.txt中添加:
            /*USE_MYMATH 爲編譯開關,中間的字符串爲描述信息,ON/OFF 爲默認選項*/
            option (USE_MYMATH 
                    "Use tutorial provided math implementation" ON) 
          • 在編譯以前,執行ccmake . 就會彈出cmake GUI,進行配置全部的編譯開關,配置結束以後會生成一個CMakeCache.txt,配置後的編譯選項會保存在這個文件中
            https://blog.csdn.net/haima1998/article/details/23352881
      • 怎麼生成依賴於其餘option的option
        #設置optionUSE_CURL
        ​option(USE_CURL "use libcurl" ON)

        #設置optionUSE_MATH​​
        option(USE_MATH "use libm" ON)

        #設置一個option​​DEPENT_USE_CURL,第二個參數是他的說明,ON後面的參數是一個表達式,當「USE_CURL」且「USE_MATH」爲真的時候,DEPENT_USE_CURL取ON,爲假取OFF
        cmake_dependent_option(DEPENT_USE_CURL "this is dependent on USE_CURL" ON "USE_CURL;NOT USE_MATH" OFF)
      • 屬性調試模塊(CMakePrintHelpers)
        CMAKE_PRINT_PROPERTIES([TARGETS target1 .. targetN]
        [SOURCES source1 .. sourceN]
        [DIRECTORIES dir1 .. dirN]
        [TESTS test1 .. testN]
        [CACHE_ENTRIES entry1 .. entryN]
        PROPERTIES prop1 .. propN )
        • 若是要檢查foo目標的INTERFACE_INCLUDE_DIRS和LOCATION的值,則執行:
          cmake_print_properties ( TARGETS foo
          PROPERTIES
          INTERFACE_INCLUDE_DIRS
          LOCATION )
    • //CMake3.8以上叫作Modern CMake
相關文章
相關標籤/搜索