cmake 常用指令入門指南



本博客記錄:在使用cmake進行構建工程時,寫CMakeLists.txt 文件時,常使用到的命令與變量, 不斷補充更新中。

相關鏈接

官方地址: https://cmake.org/cmake/help/
git上很好實踐教程: https://github.com/ttroy50/cmake-examples

CMKAE中腳本相關的命令

cmake_minimum_required 命令

語法與參數介紹

語法: cmake_minimum_required(VERSION min[...policy_max] [FATAL_ERROR])

  • min 指定了編譯當前的cmake需要的最old的版本號,如果cmake版本號小於指定的版本號時,運行cmake 就報錯。

    舉例:當前有cmake版本號為3.10.2, 運行如下的CMakeLists.txt 文件時, 就會報錯:

    cmake_minimum_required(VERSION 3.12)
    

    運行cmake命令,報錯如下:提示運行版本小於要求的最小版本。

    CMake Error at CMakeLists.txt:1 (cmake_minimum_required):
    CMake 3.10.3 or higher is required.  You are running version 3.10.2
    
    
    -- Configuring incomplete, errors occurred!
    
  • ... 表示min或max版本號之間的連接符。

  • policy_max 參數與cmake的policy setting相關,當指定了【policy_max】參數(要大於等於min版本號)時, 所有【小於等於 policy_max版本 或者 小於等於當前運行版本(誰小取誰)】中的已經的policy都設置為NEW.

    policy 可以理解為版本之間的變更,例如語法新增加、約束變嚴等, policy使用CMPXXXX格式的編號,例如:CMP0000表示cmake文件中必須指定要求的最低版本號,CMP0002表示....等。
    在新的版本中,如果要指定policy的新的規定, 語法為: cmake_policy(SET CMPXXXX NEW), 有時候為了新版本兼容之前寫的CMakeLists.txt文件, 則可以使用原來的policy, 語法為:cmake_policy(SET CMPXXXX OLD).
    可以使用cmake_policy(VERSION min[...max])指定policy的要求min與max版本號:
    - 當不指定max版本號時,cmake會把min版本以及之前的版本引入的所有policy設置為NEW, 大於min版本號引入的policy默認不設置。
    - 當指定max版本號時, cmake會把 【max版本或者當前運行的版本號(誰小取誰)】以及之前的版本號引入的的所有polixy設置為NEW, 超過的版本引入的policy默認不設置。
    當使用cmake_minimum_required(VERSION)命令時,會隱式地調用cmake_policy(VERSION)命令用於設置policy相關的版本要求。

舉例: 下面的cmake命令:

cmake_mini_mum_required(VERSION 3.12...3.15)

# 上面命令會隱示地調用下面這條命令
cmake_policy(VERSION 3.12...3.15)
  • FATAL_ERROR
    該選項在2.6涉及2.6版本以下有用, 當指定該選項時,如果當前支行的版本號小於要求的版本號,就會報錯;如果不指定該選項時,只會報warning. 2.6版本之后,都是報錯了,所以用不着該選項了。

引入的變量

  • CMAKE_MINIMUM_REQUIRED_VERSION : 設置該變量的值為 min.

file 命令

file 命令專門用於訪問文件系統對文件與路徑進行操作的。

讀相關

寫相關

文件系統相關

file(GLOB variable 通配符表達式)

語法與參數

使用語法為: file(GLOB <variable> [LIST_DIRECTORIES true|false] [RELATIVE <path>] [CONFIGURE_DEPENDS] [<globbing-expressions>...])
含義: GLOB, 就是globbing的縮寫, 該命令查找所有在當前目錄(CMakeLists.txt所在目錄,即CMAKE_CURRENT_SOURCE_DIR變量)下所有滿足匹配通配符表達式的文件,並保存到給定的變量中。

  • GLOB: 是關鍵字。
  • variable: 保存文件名的變量
  • LIST_DIRECTORIES true| false : 表示是否要保存文件的路徑,默認保存。 (試了一下,置為false為什么不管用呢?)
  • RELATIVE path: 給定該參數時,保存的路徑中是相對於給定path的路徑名。
  • globbing-expressions: 通配符表達式。

使用舉例

file(GLOB source_list "src/*.cpp")

注意事項

不建議使用該命令搜索源文件名,原因是:如果CMakeLists.txt文件沒有變化,但是你增加了源文件, 此時給的結果不一樣正確。(我試了一下,ubuntu下可以給出正確結果)

路徑轉換相關

set命令

設置普通的命令

使用語法:set(<variable> <value>... [PARENT_SCOPE]), 設置一個變量的值。 如果不給定值,就表示取消該變量的設置。

  • PARENT_SCOPE: 表示在上層作用域內設置變量的值。

使用舉例

set(SOURCE_LIST 1.c 2.c 3.c)

設置cache 變量

使用語法與參數含義

語法:set(<variable> <value>... CACHE <type> <docstring> [FORCE]), 該命令會設置的cache變量會被保存到CMakeCache.txt 文檔中, 可以打開看看的。

  • CACHE 是關鍵字。
  • type 表示變量的類型, 包含: BOOL、FILEPATH、PATH、STRING、INTERNAL。
  • docstring: 類型注釋,表明該參數的含義。
  • FORCE: 默認情況下,如果該cache 變量已經設置過了,再次執行該變量就不會被寫入,如果使用了FORCE關鍵字的話,只要命令被執行,就會對變量進行寫入的。

使用舉例

set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE)

set_property 命令

使用語法與參數含義

該命令用於設置一個對象的屬性信息, 它的使用語法如下所示:

set_property(<GLOBAL                      |
              DIRECTORY [<dir>]           |
              TARGET    [<target1> ...]   |
              SOURCE    [<src1> ...]
                        [DIRECTORY <dirs> ...] |
                        [TARGET_DIRECTORY <targets> ...]
              INSTALL   [<file1> ...]     |
              TEST      [<test1> ...]     |
              CACHE     [<entry1> ...]    >
             [APPEND] [APPEND_STRING]
             PROPERTY <name> [<value1> ...])
  • [對象類型] [對象名稱]: 指定了對象的類型以及要設置的對象名稱, 包含: GLOBAL, DIRECTORY, TARGET, SOURCE 等。例如TARGET hello_main.
  • PROPERTY 屬性名: 指定了要設置的屬性名以及屬性值。

使用舉例

cmake_minimum_required(VERSION 3.10.2)
project(hello_main)
add_executable(hello_main main.cpp)
set_property(TARGET hello_main PROPERTY CXX_STANDARD 11)

include 命令

** 語法與參數說明**

該命令用於導入文件或模塊中的CMAKE代碼, 類似於c語言中的include 功能。 使用語法為:

include(<file|module> [OPTIONAL] [RESULT_VARIABLE <var>]
                      [NO_POLICY_SCOPE])
  • file | module: 指定的包含CMKE指定的文件 或者 模塊名。模塊名其實就是安裝cmake時已經提供的***.cmake文件(例如/usr/share/cmake-3.10/Modules/目錄下好多模塊)
  • OPTIONAL: 如果指定了該選項,當cmake查找不到指定文件時,不會報錯, 因為它是可選的嘛。
  • RESULT_VARIABLE var: 用於保存查找到的文件路徑(查找成功時) 或者保存失敗結果NOTFOUND(失敗時)

舉例說明

cmake_minimum_required(VERSION 2.8)
project (hello_cpp11)

#這里導入CheckCXXCompilerFlag模塊, 並運行該模塊內的CHECK_CXX_COMPILER_FLAG命令。
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)

message 命令

該命令是用於記錄log消息的,使用語法為:message([<mode>] "message text" ...)。 其中,mode 關鍵字用於表示要記錄的log的類型,常用的有:

  • FATAL_ERROR: cmake errer, 遇到該錯誤,cmake 直接停止處理。
  • WARNING: 警告信息, 但是cmake會繼續執行下去的。
  • STATUS: 用於記錄一些cmake 運行過程中的有用的信息。

例如:

message(STATUS "hello, world.")
set(NAME xiaoming)
messaeg(STATUS "hello, ${NAME}")

CMAKE中project相關命令

project 命令

語法與參數

使用語法為:project(項目名字, [VERSION 版本號] [DESCRIPTION 描述字符串] ), 例如:

project(myproject, VERSION 1.0.0 DESCRIPTION "my first project" )
  • 項目名字, 即指定一個項目名字
  • VERSION, 指定項目的版本號, 可選字段, 一般不用不着它,不學習,不介紹
  • DESCRIPTION, 項目的描述, 可選字段,一般也不需要用它,不學習,不介紹
  • 還有其它的可選參數,例如HOMEPAGE_URL, LANGUAGES, 用不着,不介紹

隱式引入的變量

  • PROJECT_NAME: 它的值為 最近調用的project()命令設置的項目名, 例如你的子目錄中調用了project()命令,那么該變量名在子目錄中的值就是新設置的項目名。
  • CMAKE_PROJECT_NAME: 它的值為 最top 層的 project 設置的項目名
  • PROJECT_SOURCE_DIR: 最近 調用project() 命令定義的項目所在的源文件的絕對路徑。
    例如:在根目錄中定義的CMakeLists.txt文件中調用了project()命令, 在該作用域內, 該變量的值就是定義該CMakeLists.txt的絕對路徑。
    如果在子目錄中定義的CMakeLists.txt文件中也調用了project()命令, 在子目錄中CMakeLists.txt的作用域內,該變量的值就是子目錄的絕對路徑。
  • PROJECT_BINARY_DIR: 最近調用project()命令定義的項目的binary的絕對路徑。 與調用cmake命令的位置有關, 通常會在build 目錄下調用cmake, 所以該binary目錄都在build 目錄內。
  • <PROJECT-NAME>_SOURCE_DIR: 首先不推薦使用它,如果你修改的項目名字,該變量名也需要適配。 它的值與PROJECT_SOURCE_DIR變量的值相同。
  • <PROJECT-NAME>_BINARY_DIR: 不推薦使用, 與PROJECT_BINARY_DIR的值相同。

add _executable 命令

普通的可執行文件

語法與參數說明

使用語法為:add_executable(name [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] [source1] [source2] ...). 例如:

cmake_minimum_required(VERSION 3.12)
add_executable(myMain 1.c 2.c)
  • name : 即可執行文件的名字。windows平台下實際產生的可執行文件名為name.exe, linux平台下產生的可執行文件名就是name.

  • WIN32關鍵字: 用不着,不學習,跳過。

  • MACOSX_BUNDLE: 用不着,不學習,跳過。

  • source1: 源文件列表, 多個源文件使用空格分開,說明如下:

    1. 從3.1版本開始, 可以使用“generator expressions"語法表示($<...>)依賴的源文件列表。
    2. 在該命令中可以暫時不寫依賴的源文件列表, 后續由target_sources() 再添加源文件列表。
  • EXCLUDE_FROM_ALL:當指定該參數時,要構建的target 就會被排除在all target 列表之外, 這樣當執行makemake all時, 該target 不會被編譯。

相關變量

  • CMAKE_RUNTIME_OUTPUT_DIRECTORY: 該變量指定了生成的可執行文件的保存路徑.

import可執行文件

用到的時候補。

alias可執行文件

使用語法:add_library(<name> ALIAS <target>), 為給定的target添加一個別名name. 例如:

add_library(other_name ALIAS mylib)

add_library 命令

Normal Libraries

語法與參數說明

使用語法:add_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] [<source>...]) , 該命令用於添加一個庫文件的target, 包含靜態庫、動態庫等。

  • name: target的名字。
  • [STATIC | SHARED | MODULE]: STATIC 表示靜態庫,SHARED 表示動態庫,MODULE表示模塊庫,可以在運行時使用 dlopen 之類的命令動態加載的插件。
  • EXCLUDE_FROM_ALL: 與add_executable命令中的參數相同,當指定該參數時,要構建的target 就會被排除在all target 列表之外。
  • source: 源文件列表。

例如舉例

add_library(hello_library STATIC src/Hello.cpp)

相關變量

  • ARCHIVE_OUTPUT_DIRECTORY: 修改靜態庫的輸出路徑。
  • LIBRARY_OUTPUT_DIRECTORY: 修改動態庫的輸出路徑。
  • ARCHIVE_OUTPUT_NAME: 修改靜態庫的輸出路徑。
  • LIBRARY_OUTPUT_NAME: 修改動態庫的輸出路徑。

target_include_directories 命令

語法與參數說明

語法:target_include_directories(<target> [SYSTEM] [AFTER|BEFORE] <INTERFACE|PUBLIC|PRIVATE> [items1...] [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])

當編譯給定target時,該命令用於指令要包含的路徑名。 當使用 gcc 編譯器編譯目標時,就會使用-I選項指定該命令添加的路徑, 使用-I directory/include.

  • target: 要編譯的目標文件
  • SYSTEM: 感覺用不到,跳過。
  • AFTER 或 BEFORE: 控制把需要添加的路徑append 還是 prepend 到已有的路徑列表中。
  • INTERFACE/PUBLIC/PRIVATE: 這幾個關鍵字很有用。
    • 從內部實現上講: 當使用PRIVATEPUBLIC 指定路徑名時, 會把路徑名添加到target的INCLUDE_DIRECTORIES屬性中; 當使用PUBLICINTERFACE指定路徑名時, 會把路徑名添加到target的INTERFACE_INCLUDE_DIRECTORIES的屬性中。
    • 從外部表現上講:使用PRIVATE關鍵字時,添加的路徑只會在編譯當前target時使用到。 當使用INTERFACE關鍵字時,添加的路徑只會在編譯任何鏈接到當前target的目標文件時使用到。 使用PUBLIC關鍵字時,會包含以兩種使用。 因此,通常情況下,如果target是可執行文件,建議使用PRIVATE, 如果target是動態或靜態庫, 建議使用PUBLIC,比較方便。

命令舉例

target_include_directories(mylib PUBLIC include/1.h PUBLIC ${PROJECT_SOURCE_DIR}/include)
target_include_directories(mytarget PRIVATE ${PROJECT_SOURCE_DIR}/include)

語法及參數含義

使用語法: target_link_libraries(<target> <PRIVATE|PUBLIC|INTERFACE> <item>...[<PRIVATE|PUBLIC|INTERFACE> <item>...]...)
該命令的用於指定一個target的鏈接階段的依賴庫。 它還可以 propagate any include directories with PUBLIC or INTERFACE scope from the linked library target.

PRIVATE|PUBLIC|INTERFACE的作用

暫時不太明白。

使用舉例

target_link_libraries( hello_binary PRIVATE hello_library)

install 命令

Installing Target

語法與參數

該命令用於安裝指定的target到指定目錄內。 全量的使用語法為:

install(TARGETS targets ... [EXPORT <export-name>]
        [RUNTIME_DEPENDENCIES args...|RUNTIME_DEPENDENCY_SET <set-name>]
        [[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDLE|
          PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE]
         [DESTINATION <dir>]
         [PERMISSIONS permissions...]
         [CONFIGURATIONS [Debug|Release|...]]
         [COMPONENT <component>]
         [NAMELINK_COMPONENT <component>]
         [OPTIONAL] [EXCLUDE_FROM_ALL]
         [NAMELINK_ONLY|NAMELINK_SKIP]
        ] [...]
        [INCLUDES DESTINATION [<dir> ...]]
        )
  • TARGET targets: 指明了要安裝的target.
  • ARCHIVE|LIBRARY|RUNTIME等: 指明了target的類型。
  • DESTINATION dir: 指明了要安裝到的路徑。當使用相對路徑時,是相對於變量CMAKE_INSTALL_PREFIX的, 該變量默認為/usr/local/, 也可以在CMakeLists.txt文件中指定,也可以在運行CMAKE命令時指定,例如:cmake .. -DCMAKE_INSTALL_PREFIX=/install/location

使用舉例

install(TARGETS mylib LIBRARY DESTINATION lib)
install(TARGETS mybin RUNTIME DESTINATION bin)

Installing Directories

該命令用於安裝指定的目錄(包含目錄內的文件)到指定目錄。

使用語法與參數說明

install(DIRECTORY dirs...
        TYPE <type> | DESTINATION <dir>
        [FILE_PERMISSIONS permissions...]
        [DIRECTORY_PERMISSIONS permissions...]
        [USE_SOURCE_PERMISSIONS] [OPTIONAL] [MESSAGE_NEVER]
        [CONFIGURATIONS [Debug|Release|...]]
        [COMPONENT <component>] [EXCLUDE_FROM_ALL]
        [FILES_MATCHING]
        [[PATTERN <pattern> | REGEX <regex>]
         [EXCLUDE] [PERMISSIONS permissions...]] [...])
  • DIRECTORY dirs: 要安裝的頭文件的目錄路徑,默認為相對於當前的路徑。 注意:如果路徑以/結尾時, 會把路徑里面的內容復制到給定路徑,如果沒有以/結尾,則也會復制該層目錄的。
  • DESTINATION: 要安裝到的目錄路徑。

使用舉例

install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/ DESTINATION include)

Installing Files

使用語法與參數介紹

該命令用於安裝指定的文件到指定目錄:

install(<FILES|PROGRAMS> files...
        TYPE <type> | DESTINATION <dir>
        [PERMISSIONS permissions...]
        [CONFIGURATIONS [Debug|Release|...]]
        [COMPONENT <component>]
        [RENAME <name>] [OPTIONAL] [EXCLUDE_FROM_ALL])
  • FILES files: 指定要安裝的文件。
  • DESTINATION dir: 指定要安裝的路徑。

使用舉例

install(FILES cmake.config DESTINATION etc)

target_compile_definitions

使用語法與參數定義

該命令用於指定指定編譯給定的target時,要定義的宏名稱:

target_compile_definitions(<target>
  <INTERFACE|PUBLIC|PRIVATE> [items1...]
  [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])

  • target: 要指定編譯的target。
  • INTERFACE/PUBLIC/PRIVATE: 與之前介紹的類似, 從內部實現是講: 當使用INTERFACEPUBLIC時,會把宏定義指定賦值給INTERFACE_COMPILE_DEFINITIONS變量, 當使用PUBLICPRIVATE時,會把宏定義內容賦值給COMPILE_DEFINITIONS變量。從外部表現上講, 當使用INTERFACEPUBLIC時,表示編譯任何鏈接到該target(當target是一個庫時)的目標文件時,都增加了該宏定義。當使用PUBLICPRIVATE時,表示編譯當前target時,才使用該宏定義。
  • items1: 表示要定義的宏名字。

其它方法:1. 修改變量CMAKE_CXX_FLAGS(c++) 或者CMAKE_C_FLAGS(C代碼),也可以實現該效果,但是建議使用target_compile_definitions命令。
2. 在執行cmake 命令時,也可以通過參數指定,例如:cmake .. -DCMAKE_CXX_FLAGS="-DCHINA", 它就會定義一個CHINA的宏定義。

使用舉例

main函數定義如下:

#include <iostream>
int main() {
#ifdef CHINA
	std::cout << "I Love CHINA" << std::endl;
#endif
	return 0;
}
cmake_minimum_required(VERSION 3.10.2)
add_executable(myTarget main.c)
target_compile_definations(myTarget PRIVATE CHINA)

add_subdirectory 命令

該命令用於增加一個構建的子目錄。 注意執行的數據流: cmake 命令會執行完子目錄中的CmakeLists.txt文件之后,再執行后面的命令。

使用語法與參數說明

使用語法為: add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

  • source_dir: 要添加的子目錄, 建議使用相對路徑啊(相對於當前位置)。
  • binary_dir: 用於保存輸出文件位置。 一般都不寫。
  • EXCLUDE_FROM_ALL: 該參數很熟悉了,就是編譯的時候(make 或 make all),默認不被編譯。如果想要編譯它,顯示自己執行。

舉例

cmake_minimum_required(VERSION 3.10.2)
project(example)
add_subdirectory(subdir1)
add_subdirectory(subdir2)

set_target_properties 命令

該命令用於設置給定target的一些屬性值,類似於類對象的成員變量的值。 它們會影響到該target如何被構建的。

使用語法與參數說明

使用語法為:

set_target_properties(target1 target2 ...
                      PROPERTIES prop1 value1
                      prop2 value2 ...)
  • target1... : 要設置的target的名字。
  • PROPERTIES: 后面跟要設置的屬性的名字以及它們的值。

使用舉例

cmake_minimum_required(VERSION 3.10.2)
project(hello_main)
add_executable(hello_main main.cpp)
set_target_properties(hello_main PROPERTIES CXX_STANDARD 11)

target_compile_features 命令

該命令用於 Specifies compiler features required when compiling a given target.

使用語法與參數說明

使用語法為:target_compile_features(<target> <PRIVATE|PUBLIC|INTERFACE> <feature> [...]).

  • target: 要編譯的目標文件的名稱。
  • PRIVATE | PUBLIC | INTERFACE : 這個關鍵字已經介紹過N次了,它指明了什么場景下生效該設置。
  • feature: 就是支持的一些feature了,例如:cxx_std_98cxx_std_11cxx_rvalue_references等。

使用舉例

cmake_minimum_required(VERSION 3.10.2)
project(hello_main)
add_executable(hello_main main.cpp)
target_compile_features(hello_main PRIVATE cxx_std_11)

cmake中的常用變量

CMAKE_SOURCE_DIR

表示:源碼的根目錄,也就是最top層 CMakeLists.txt文件存在的目錄。

CMAKE_BINARY_DIR

表示:為編譯的binary的根目錄,也就是運行CMake時的目錄,一般就是build目錄。

CMAKE_CURRENT_SOURCE_DIR

表示:當前正在運行的CMakeLists.txt文件的目錄

CMAKE_CURRENT_BINARY_DIR

表示:當前正處於的編譯目錄,例如如果正在運行src目錄下的CMakeLists.txt, 該變量通常為build/src目錄。

CMAKE_CXX_FLAGS 和 CMAKE_C_FLAGS

表示:當使用g++(或gcc)編譯文件時,用於設置compiler flags, 也就是宏定義。

CMAKE_CXX_STANDARD

表示:該變量用於編譯target時,使用的c++標准,支持98, 11, 14, 17, 20, 23. 該變量的作用原理是:用於初始化target的CXX_STANDARD屬性。

C++編譯器相關的宏命令

check_cxx_compiler_flag 命令

該宏定義在CheckCXXCompilerFlag.cmake模塊中, 可以打開該文件看它的實現的。 它的功能是用於檢測c++編譯器是否支持給定的編譯選項,並把檢測結果寫的給定變量中。

使用語法為:check_cxx_compiler_flag(<flag> <var>),

  • flag: 要檢測的c++編譯選項
  • var: 保存檢測結果的cache 變量。

使用舉例


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM