CMake 命令筆記

CMake 全稱(chēng)“cross platform make”费坊,是開(kāi)源、跨平臺(tái)的自動(dòng)化構(gòu)建系統(tǒng)。CMake 由 Kitware 開(kāi)發(fā)與維護(hù)喷鸽,來(lái)自使用者的貢獻(xiàn)使得 CMake 快速成長(zhǎng)。

CMake 并不直接建構(gòu)出最終的軟件灸拍,而是依照平臺(tái)做祝、編譯器產(chǎn)生標(biāo)準(zhǔn)的建構(gòu)檔(如 Unix Makefile 或 Visual Studio 的 projects/workspaces),然后再依一般的生成方式使用鸡岗。和標(biāo)準(zhǔn)的 GNU 開(kāi)發(fā)工具相比混槐,CMake 的角色比 Make 更高階,比較接近 Autotools轩性,而且支持多種不同的平臺(tái)與編譯器声登。

雖然跨平臺(tái)是 CMake 的重要特色,但由于 CMake 的簡(jiǎn)單與彈性揣苏,在單一平臺(tái)上使用也很便利捌刮。

前言

  • 每一個(gè)需要進(jìn)行 CMake 操作的目錄下面,都必須存在文件 CMakeLists.txt 舒岸。
  • CMake 命令不區(qū)分大小寫(xiě)绅作。習(xí)慣上,CMake 命令全小寫(xiě)蛾派,預(yù)定義變量全大寫(xiě)俄认。
  • 變量使用 ${} 方式取值,但是在 if 控制語(yǔ)句中是直接使用變量名洪乍。
  • command(parameter1 parameter2 …)眯杏,參數(shù)使用括號(hào)括起,參數(shù)之間使用空格或分號(hào)分開(kāi)壳澳。

常用預(yù)定義變量

CMake 的預(yù)定義變量

  • PROJECT_SOURCE_DIR:工程根目錄岂贩;
  • PROJECT_BINARY_DIR:運(yùn)行 CMake 命令的目錄。建議定義為 ${PROJECT_SOURCE_DIR}/build 下巷波;
  • CMAKE_INCLUDE_PATH:環(huán)境變量萎津,非 CMake 變量;
  • CMAKE_LIBRARY_PATH:環(huán)境變量抹镊;
  • CMAKE_CURRENT_SOURCE_DIR:當(dāng)前處理的 CMakeLists.txt 文件所在路徑锉屈;
  • CMAKE_CURRENT_BINARY_DIR:target 編譯目錄;
    • 使用 add_subdirectory 命令可以更改該變量的值垮耳;
    • set(EXECUTABLE_OUTPUT_PATH <dir>) 命令不會(huì)對(duì)該變量有影響颈渊,但改變了最終目標(biāo)文件的存儲(chǔ)路徑遂黍。
  • CMAKE_CURRENT_LIST_FILE:輸出調(diào)用該變量的 CMakeLists.txt 的完整路徑;
  • CMAKE_CURRENT_LIST_LINE:輸出該變量所在的行俊嗽;
  • CMAKE_MODULE_PATH:定義自己的 CMake 模塊所在路徑雾家;
  • EXECUTABLE_OUTPUT_PATH:重新定義目標(biāo)二進(jìn)制可執(zhí)行文件的存放位置;
  • LIBRARY_OUTPUT_PATH:重新定義目標(biāo)鏈接庫(kù)文件的存放位置绍豁;
  • PROJECT_NAME:返回由 project 命令定義的項(xiàng)目名稱(chēng)榜贴;
  • CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS:用來(lái)控制 if…else… 語(yǔ)句的書(shū)寫(xiě)方式。

系統(tǒng)信息預(yù)定義變量

  • CMAKE_MAJOR_VERSION:CMake 主版本號(hào)妹田,如 3.12.0 中的 3;
  • CMAKE_MINOR_VERSION:CMake 次版本號(hào)鹃共,如 3.12.0 中的 12鬼佣;
  • CMAKE_PATCH_VERSION:CMake 補(bǔ)丁等級(jí),如 3.12.0 中的 0霜浴;
  • CMAKE_SYSTEM:系統(tǒng)名稱(chēng)晶衷,例如 Windows-10.0.17134;
  • CMAKE_SYSTEM_NAME:不包含版本號(hào)的系統(tǒng)名阴孟,如 Windows晌纫;
  • CMAKE_SYSTEM_VERSION:系統(tǒng)版本號(hào),如 10.0.17134永丝;
  • CMAKE_SYSTEM_PROCESSOR:處理器架構(gòu)锹漱,如 AMD64;
  • UNIX:在所有的類(lèi) UNIX 平臺(tái)為 true慕嚷,包括 macOS 和 Cygwin哥牍;
  • WIN32:在所有的 Win32 平臺(tái)為 true,包括 Cygwin喝检。

開(kāi)關(guān)選項(xiàng)

  • BUILD_SHARED_LIBS:控制默認(rèn)的庫(kù)編譯方式嗅辣;
    • 如果未進(jìn)行設(shè)置,使用 add_library 時(shí)又沒(méi)有指定庫(kù)類(lèi)型挠说,默認(rèn)編譯生成的庫(kù)都是靜態(tài)庫(kù)澡谭。
  • CMAKE_C_FLAGS:設(shè)置 C 編譯選項(xiàng);
  • CMAKE_CXX_FLAGS:設(shè)置 C++ 編譯選項(xiàng)损俭。

常用命令

cmake_minimum_required

該語(yǔ)句一般放置在 CMakeLists.txt 的開(kāi)頭蛙奖,用于說(shuō)明 CMake 最低版本要求。

cmake_minimum_required(VERSION 3.5)

上述示例指 CMake 的版本號(hào)最低為 3.5杆兵。

project

project(<PROJECT-NAME>)
  • <PROJECT-NAME> 指工程名稱(chēng)外永。

該命令一般緊跟 cmake_minimum_required 命令之后,定義了工程的名稱(chēng)拧咳。但項(xiàng)目最終編譯生成的可執(zhí)行文件并不一定是這個(gè)項(xiàng)目名稱(chēng)伯顶,而是由另一條命令確定的,后面會(huì)介紹。

執(zhí)行了該命令之后祭衩,將會(huì)自動(dòng)創(chuàng)建兩個(gè)變量:

  • <PROJECT-NAME>_BINARY_DIR:二進(jìn)制文件保存路徑灶体;
  • <PROJECT-NAME>_SOURCE_DIR:源代碼路徑。
project(Lab)

執(zhí)行了上一條指令掐暮,即定義了一個(gè)項(xiàng)目名稱(chēng) Lab蝎抽,相應(yīng)的會(huì)生成兩個(gè)變量:Lab_BINARY_DIRLab_SOURCE_DIR路克。

CMake 中預(yù)定義了兩個(gè)變量:PROJECT_BINARY_DIRPROJECT_SOURCE_DIR樟结。

在這個(gè)例子中:

  • PROJECT_BINARY_DIR 等價(jià)于 Lab_BINARY_DIR
  • PROJECT_SOURCE_DIR 等價(jià)于 Lab_SOURCE_DIR精算。

建議直接使用 PROJECT_BINARY_DIRPROJECT_SOURCE_DIR瓢宦,這樣即使項(xiàng)目名稱(chēng)發(fā)生了變化,也不會(huì)影響 CMakeLists.txt 文件灰羽。

關(guān)于 PROJECT_BINARY_DIRPROJECT_SOURCE_DIR 這兩個(gè)變量是否相同的問(wèn)題驮履,涉及到編譯方法是內(nèi)部編譯還是外部編譯。如果是內(nèi)部編譯廉嚼,則這兩個(gè)變量相同玫镐;如果是外部編譯,則兩個(gè)變量不同怠噪。此處對(duì)內(nèi)部編譯與外部編譯做出介紹:

外部構(gòu)建與內(nèi)部構(gòu)建

假設(shè)此時(shí)已經(jīng)完成了 CMakeLists.txt 的編寫(xiě)恐似,在 CMakeLists.txt 所在目錄下,有兩種執(zhí)行 CMake 的方法:

cmake .\\
make

以及

mkdir build
cd .\\build
cmake ..\\
make

第一種方法是內(nèi)部構(gòu)建傍念,第二種方法是外部構(gòu)建蹂喻。上述兩種方法中,最大不同在于 CMake 與 Make 的工作路徑不同捂寿。

內(nèi)部構(gòu)建方法中口四,CMake 生成的中間文件和可執(zhí)行文件都會(huì)存放在項(xiàng)目目錄中;外部構(gòu)建方法中秦陋,中間文件與可執(zhí)行文件都存放在 build 目錄中蔓彩。

建議使用外部構(gòu)建方法。優(yōu)點(diǎn)顯而易見(jiàn):最大限度地保持了代碼目錄的整潔驳概,生成赤嚼、編譯與安裝是不同于項(xiàng)目目錄的其他目錄中,在外部構(gòu)建方法下顺又,PROJECT_SOURCE_DIR 指向目錄與內(nèi)部構(gòu)建相同更卒,為 CMakeLists.txt 所在根目錄;而 PROJECT_BINARY_DIR 不同稚照,它指向 CMakeLists.txt 所在根目錄下的 build 目錄蹂空。

set

set(<variable> <value>… CACHE <type> <docstring> [FORCE])

示例:

set(CMAKE_INSTALL_PREFIX C:\\Program Files\\${PROJECT_NAME})

該示例顯式地將 CMAKE_INSTALL_PREFIX 的值定義為 C:\\Program Files\\${PROJECT_NAME}俯萌。如此,在外部構(gòu)建情況下執(zhí)行 make install 命令時(shí)上枕,Make 會(huì)將生成的可執(zhí)行文件拷貝到 C:\\Program Files\\${PROJECT_NAME}\\bin 目錄下咐熙。

當(dāng)然,可執(zhí)行文件的安裝路徑 CMAKE_INSTALL_PREFIX 也可以在執(zhí)行 cmake 命令的時(shí)候指定辨萍,cmake 參數(shù)如下:

cmake -D CMAKE_INSTALL_PREFIX="C:\\Program Files\\…"

如果 cmake 參數(shù)和 CMakeLists.txt 文件中都不指定該值的話棋恼,則該值為默認(rèn)值(Windows 下為 C:\\Program Files\\${PROJECT_NAME},UNIX 下為 /usr/local)锈玉。

add_subdirectory

add_subdirectory(source_dir [binary_dir]
                 [EXCLUDE_FROM_ALL])
  • source_dir:源文件路徑爪飘;
  • [binary_dir]:中間二進(jìn)制與目標(biāo)二進(jìn)制文件存放路徑;
  • [EXECLUDE_FROM_ALL]:將這個(gè)目錄從編譯過(guò)程中排除拉背。

這個(gè)命令用于向當(dāng)前工程添加存放源文件的子目錄师崎。

include_directories

include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 …])
  • [AFTER|BEFORE]:追加標(biāo)志,指定控制追加或預(yù)先添加去团;
  • [SYSTEM]:指定該目錄為系統(tǒng)包含目錄;
  • dir1, …, dir n:添加的一系列頭文件搜索路徑穷蛹。

向工程添加多個(gè)特定的頭文件搜索路徑土陪,路徑之間用空格分隔。類(lèi)似于 GCC 中的編譯參數(shù) -l肴熏,即指定編譯過(guò)程中編譯器搜索頭文件的路徑鬼雀。當(dāng)項(xiàng)目需要的頭文件不在系統(tǒng)默認(rèn)的搜索路徑時(shí),則指定該路徑蛙吏。

add_executable

add_executable(<name> [WIN32] [MACOSX_BUNDLE]
               [EXCLUDE_FROM_ALL]
               [source1] [source2 …])
  • name:可執(zhí)行文件名源哩;
  • source1, …, source n:生成該可執(zhí)行文件的源文件。

該命令給出源文件鸦做,并指出需要編譯出的可執(zhí)行文件名励烦。

示例 1:

add_executable(hello main.cpp)

該示例中,利用源文件 main.cpp泼诱,編譯出名為 hello 的可執(zhí)行文件坛掠。

示例 2:

set(SRC_LIST main.cc
             rpc/CRNode.cpp
             rpc/Schd_types.cpp
             task/TaskExecutor.cpp
             task/TaskMoniter.cpp
             util/Const.cpp
             util/Globals.cc
   )

add_executable(CRNode ${SRC_LIST})

該示例中,定義了該工程會(huì)生成一個(gè)名為 CRNode 的可執(zhí)行文件治筒,所依賴(lài)的源文件是變量 SRC_LIST 定義的源文件列表屉栓。

如果前面 project() 命令中定義的項(xiàng)目名稱(chēng)也是 CRNode,沒(méi)有什么問(wèn)題耸袜,兩者之間沒(méi)有任何關(guān)系友多。

add_library

add_library(<name> [STATIC|SHARED|MODULE]
            [EXCLUDE_FROM_ALL]
            [source1] [source2 …])
  • name:庫(kù)文件名稱(chēng);
  • [STATIC|SHARED|MODULE]:生成的庫(kù)的文件類(lèi)型(靜態(tài)庫(kù)/共享庫(kù))堤框;
  • [EXCLUDE_FROM_ALL]:表示該庫(kù)不會(huì)被默認(rèn)構(gòu)建域滥;
  • source1, …, sourceN:生成庫(kù)所依賴(lài)的源文件纵柿。

示例:

add_library(hello SHARED ${LIB_hello_SRC})

link_directories

link_directories(directory1 directory2 …)

該命令用于添加外部庫(kù)的搜索路徑。

target_link_libraries

target_link_libraries(<target> … <item>…)
  • target:目標(biāo)文件骗绕;
  • item:鏈接外部庫(kù)文件藐窄。

指定鏈接目標(biāo)文件時(shí)需要鏈接的外部庫(kù),效果類(lèi)似于 GCC 編譯參數(shù) -L酬土,解決外部庫(kù)依賴(lài)的問(wèn)題荆忍。

message

message([<mode>] "message to display" …)
  • mode:確定消息的類(lèi)型:

    模式 描述
    (none) 重要信息
    STATUS 附帶信息
    WARNING CMake 警告,繼續(xù)處理
    AUTHOR_WARNING CMake 警告(dev)撤缴,繼續(xù)處理
    SEND_ERROR CMake 錯(cuò)誤刹枉,繼續(xù)處理,但跳過(guò)生成過(guò)程
    FATAL_ERROR CMake 錯(cuò)誤屈呕,停止處理和生成過(guò)程
    DEPRECATION 如果分別啟用 CMAKE_ERROR_DEPRECATEDCMAKE_WARN_DEPRECATED微宝,則棄用 CMake 錯(cuò)誤或警告,否則無(wú)消息
  • "message to display":需要顯示的文字消息虎眨。

set_target_properties

set_target_properties(target1 target2 …
                      PROPERTIES prop1 value1
                      prop2 value2 …)

設(shè)置目標(biāo)的某些屬性蟋软,改變它們構(gòu)建的方式。

該指令為一個(gè)目標(biāo)設(shè)置屬性嗽桩,語(yǔ)法是列出所有用戶(hù)想要變更的文件岳守,然后提供想要設(shè)置的值。用戶(hù)可以使用任何想用的屬性與對(duì)應(yīng)的值碌冶,并在隨后的代碼中調(diào)用 GET_TARGET_PROPERTY 命令取出屬性的值湿痢。

影響目標(biāo)輸出文件的屬性PROPERTIES詳述如下:

PREFIX、SUFFIX

  • PREFIX 覆蓋了默認(rèn)的目標(biāo)名前綴(如 lib)扑庞;
  • SUFFIX 覆蓋了默認(rèn)的目標(biāo)名后綴(如 .so)譬重。

IMPORT_PREFIX、IMPORT_SUFFIX

PREFIX罐氨、SUFFIX 是等價(jià)的屬性臀规,但針對(duì)的是 DLL 導(dǎo)入庫(kù)(即共享庫(kù)目標(biāo))。

OUTPUT_NAME

構(gòu)建目標(biāo)時(shí)栅隐,OUTPUT_NAME 用來(lái)設(shè)置目標(biāo)的真實(shí)名稱(chēng)以现。

LINK_FLAGS

為一個(gè)目標(biāo)的鏈接階段添加額外標(biāo)志。

LINK_FLAGS_<CONFIG> 將為配置 <CONFIG> 添加鏈接標(biāo)志约啊,如 Debug邑遏、ReleaseRelWithDebInfo恰矩、MinSizeRel记盒。

COMPILE_FLAGS

設(shè)置附加的編譯器標(biāo)志,在構(gòu)建目標(biāo)內(nèi)的源文件時(shí)用到外傅。

LINKER_LANGUAGE

改變鏈接可執(zhí)行文件或共享庫(kù)的工具纪吮。默認(rèn)值是設(shè)置與庫(kù)中文件相匹配的語(yǔ)言俩檬。

CXX 與 C 是該屬性的公共值。

VERSION碾盟、SOVERSION

VERSION 指定構(gòu)建的版本號(hào)棚辽,SOVERSION 指定構(gòu)建的 API 版本號(hào)。

構(gòu)建或安裝時(shí)冰肴,如果平臺(tái)支持符號(hào)鏈接屈藐,且鏈接器支持 so 名稱(chēng),那么將會(huì)創(chuàng)建恰當(dāng)?shù)姆?hào)鏈接熙尉。

如果只指定兩者中的一個(gè)联逻,缺失的另一個(gè)假定為具有相同版本號(hào)。

示例 1:

set_target_properties(hello_static PROPERTIES OUTPUT_NAME "hello")

示例 2:

set_target_properties(hello PROPERTEIES VERSION 1.2 SOVERSION 1)

該命令用于控制版本检痰,VERSION 指代動(dòng)態(tài)庫(kù)版本包归,SOVERSION 指代 API 版本。

aux_source_directory

查找某個(gè)路徑下的所有源文件铅歼,并將源文件列表存儲(chǔ)到一個(gè)變量中公壤。

aux_source_directory(<dir> <variable>)

示例:

aux_source_directory(. SRC_LIST)

該指令將當(dāng)前目錄下的文件列表全部存入變量 SRC_LIST 中。

install

install 命令可以按照對(duì)象的不同分為多種類(lèi)型:目標(biāo)文件椎椰、非目標(biāo)文件厦幅、目錄。

目標(biāo)文件

install(TARGETS targets… [EXPORT <export-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> …]]
        )
  • TARGETS targetstargets 即通過(guò) add_executableadd_library 定義的目標(biāo)文件俭识,可能是可執(zhí)行二進(jìn)制文件慨削、動(dòng)態(tài)庫(kù)洞渔、靜態(tài)庫(kù)套媚;
  • DESTINATION <dir>dir 即定義的安裝路徑。安裝路徑可以是絕對(duì)/相對(duì)路徑磁椒。在絕對(duì)路徑的情況下堤瘤,CMAKE_INSTALL_PREFIX 就無(wú)效了。
    • 如果希望使用 CMAKE_INSTALL_PREFIX 定義安裝路徑浆熔,就需要使用相對(duì)路徑本辐,這時(shí)候安裝后的路徑就是 ${CMAKE_INSTALL_PREFIX}\\<dir>

非目標(biāo)文件

.sh 腳本文件医增,即為典型的非目標(biāo)文件的可執(zhí)行程序慎皱。

install(<FILES|PROGRAMS> files… DESTINATION <dir>
        [PERMISSIONS permissions…]
        [CONFIGURATIONS [Debug|Release|…]]
        [COMPONENT <component>]
        [RENAME <name>] [OPTIONAL] [EXCLUDE_FROM_ALL])

使用方法和上述目標(biāo)文件指令的 install 基本相同。唯一的區(qū)別是叶骨,安裝非目標(biāo)文件之后的權(quán)限還包括 OWNER_EXECUTE茫多、GOUP_EXECUTEWORLD_EXECUTE忽刽,即 755 權(quán)限目錄的安裝天揖。

目錄

install(DIRECTORY dirs… 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 dirsdirs 是所在源文件目錄的相對(duì)路徑夺欲。但必須注意,abcabc/ 有很大區(qū)別:
    • abc:該目錄將被安裝為目標(biāo)路徑的 abc今膊;
    • abc/:將該目錄內(nèi)容安裝到目標(biāo)路徑些阅,但不包括該目錄本身。

示例:

install(DIRECTORY icons scripts/ DESTINATION share/myproj
        PATTERN "CVS" EXCLUDE
        PATTERN "scripts/*" PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ)

該指令的執(zhí)行結(jié)果是:

  • 將 icons 目錄安裝到 <prefix>/share/myproj斑唬;
  • 將 scripts/ 中的內(nèi)容安裝到 <prefix>/share/myproj市埋;
  • 不包含目錄名為 CVS 的目錄;
  • 對(duì)于 scripts/* 文件指定權(quán)限為 OWNER_EXECUTE赖钞、OWNER_WRITE腰素、OWNER_READGROUP_EXECUT雪营、GROUP_READ弓千。

基本控制語(yǔ)法

if

if…else… 語(yǔ)法格式有些類(lèi)似于 Visual Basic .NET:

if(<expression>)
  # then section.
  COMMAND1(<ARGS> …)
  COMMAND2(<ARGS> …)
  #…
elseif(<expression2>)
  # elseif section.
  COMMAND1(<ARGS> …)
  COMMAND2(<ARGS> …)
  #…
else(<expression>)
  # else section.
  COMMAND1(<ARGS> …)
  COMMAND2(<ARGS> …)
  #…
endif(<expression>)

其中,一定要有 endif()if() 對(duì)應(yīng)献起。

if 基本用法

  • if(<expression>)expression 不為 0洋访、OFFNO谴餐、FALSE姻政、NIGNORE岂嗓、NOTFOUND汁展、空字符串,或者不含后綴 -NOTFOUND 時(shí)厌殉,為真食绿;

  • if(NOT <expression>:與上一條相反;

  • if(<expr1> AND <expr2>)

  • if(<expr1> OR <expr2>

  • if(COMMAND command-name):如果 command-name 是命令公罕、宏或函數(shù)并可調(diào)用器紧,為真;

  • if(EXISTS path-to-file-or-directory):如果給定路徑的文件或目錄存在楼眷,為真铲汪;

  • if(file1 IS_NEWER_THAN file2):當(dāng) file1 比 file2 新,或 file1/file2 中有一個(gè)不存在時(shí)為真罐柳,文件名需使用全路徑掌腰;

  • if(IS_DIRECTORY path-to-directory):當(dāng)給定路徑是目錄時(shí),為真张吉。注意使用全路徑齿梁;

  • if(DEFINED <variable>):如果變量已被定義,為真芦拿;

  • if(<variable|string> MATCHES regex):當(dāng)給定變量或字符串能匹配正則表達(dá)式 regex 時(shí)士飒,為真查邢。此處的 variable 直接使用變量名,而非 ${variable}酵幕。

    • 示例:

      if("hello" MATCHES "ell") 
      message("true") 
      endif("hello" MATCHES "ell")
      

數(shù)字比較表達(dá)式

  • if(<var> LESS <number>)
  • if(<var> GREATER <number>)
  • if(<var> EQUAL <number>)

字母表順序比較

  • if(<var1> STRLESS <var2>)
  • if(<var1> STRGREATER <var2>)
  • if(<var1> STREQUAL <var2>)

示例 1:

判斷平臺(tái)差異扰藕。

if(WIN32)
    message(STATUS "This is windows.")
else(WIN32)
    message(STATUS "This is not windows.")
endif(WIN32)

上述代碼可以控制不同平臺(tái)進(jìn)行不同控制。

也許 else(WIN32) 之類(lèi)的語(yǔ)句閱讀起來(lái)很不舒服芳撒,這時(shí)候可以加上語(yǔ)句:

set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)

這時(shí)候上述結(jié)構(gòu)就可以寫(xiě)成:

if(WIN32)
    message(STATUS "This is windows.")
else()
    message(STATUS "This is not windows.")
endif()

示例 2:

if(WIN32)
    #do something related to WIN32
elseif(UNIX)
    #do something related to UNIX
elseif(APPLE)
    #do something related to APPLE
endif(WIN32)

while

while(<condition>)
  COMMAND1(<ARGS> …)
  COMMAND2(<ARGS> …)
  …
endwhile(<condition>)

類(lèi)似于 endif邓深,while() 也需要 endwhile() 匹配。

真假判斷條件可以參考 if 指令笔刹。

foreach

foreach 有多種使用形式的語(yǔ)法芥备,且每個(gè) foreach() 都需要一個(gè) endforeach() 與之匹配。

列表語(yǔ)法

foreach(<loop_var> <arg1> <arg2> …)
  COMMAND1(<ARGS> …)
  COMMAND2(<ARGS> …)
  …
endforeach(<loop_var>)

示例:

aux_source_directory(. SRC_LIST)
foreach(F ${SRC_LIST})
     message(${F})
endforeach(F)

該示例中舌菜,先將當(dāng)前路徑下的所有源文件列表賦值給變量 SRC_LIST萌壳,然后遍歷 SRC_LIST 中的文件,并持續(xù)輸出信息日月,信息內(nèi)容是當(dāng)前路徑下所有源文件的名稱(chēng)袱瓮。

范圍語(yǔ)法

foreach(<loop_var> RANGE <total>)
  COMMAND1(<ARGS> …)
  COMMAND2(<ARGS> …)
  …
endforeach(<loop_var>)

示例:

foreach(v RANGE 10)
    message(${v})
endforeach(v)

該示例從 0 到 total(此處為 10),以 1 為步進(jìn)爱咬。此處輸出為:012345678910尺借。

范圍步進(jìn)語(yǔ)法

foreach(<loop_var> RANGE <start> <stop> [<step>])
  COMMAND1(<ARGS> …)
  COMMAND2(<ARGS> …)
  …
endforeach(<loop_var>)

start 開(kāi)始,到 stop 結(jié)束精拟,以 step 為步進(jìn)燎斩。

示例:

foreach(a RANGE 5 15 3)
    message(${a})
endforeach(a)

此處輸出為 581114

迭代語(yǔ)法

foreach 還可以循環(huán)訪問(wèn)生成的數(shù)字范圍蜂绎。這種迭代有三種類(lèi)型:

  • 指定單個(gè)數(shù)字時(shí)栅表,范圍將包含元素 [0, …, total](包括 total);
  • 指定兩個(gè)數(shù)字時(shí)荡碾,范圍將包含從第一個(gè)數(shù)字到第二個(gè)數(shù)字(包括)的元素谨读;
  • 第三個(gè)可選數(shù)字是用于從第一個(gè)數(shù)字迭代到第二個(gè)數(shù)字(包括)的增量局装。
foreach(<loop_var> IN [LISTS [<list1> …]]
                      [ITEMS [<item1> …]])
  COMMAND1(<ARGS> …)
  COMMAND2(<ARGS> …)
  …
endforeach(<loop_var>)

foreach 循環(huán)訪問(wèn)一個(gè)精確的項(xiàng)列表:

  • LISTS:給要遍歷的列表值變量命名坛吁,包括空元素(空字符串是零長(zhǎng)度列表)。注意宏參數(shù)不是變量铐尚。
  • ITEMS:結(jié)束參數(shù)解析并包含迭代中它后面的所有參數(shù)拨脉。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市宣增,隨后出現(xiàn)的幾起案子玫膀,更是在濱河造成了極大的恐慌,老刑警劉巖爹脾,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件帖旨,死亡現(xiàn)場(chǎng)離奇詭異箕昭,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)解阅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)落竹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人货抄,你說(shuō)我怎么就攤上這事述召。” “怎么了蟹地?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵积暖,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我怪与,道長(zhǎng)夺刑,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任分别,我火速辦了婚禮性誉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘茎杂。我一直安慰自己错览,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布煌往。 她就那樣靜靜地躺著倾哺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪刽脖。 梳的紋絲不亂的頭發(fā)上羞海,一...
    開(kāi)封第一講書(shū)人閱讀 49,031評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音曲管,去河邊找鬼却邓。 笑死,一個(gè)胖子當(dāng)著我的面吹牛院水,可吹牛的內(nèi)容都是我干的腊徙。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼檬某,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼撬腾!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起恢恼,我...
    開(kāi)封第一講書(shū)人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤民傻,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體漓踢,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡牵署,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了喧半。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片碟刺。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖薯酝,靈堂內(nèi)的尸體忽然破棺而出半沽,到底是詐尸還是另有隱情,我是刑警寧澤吴菠,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布者填,位于F島的核電站,受9級(jí)特大地震影響做葵,放射性物質(zhì)發(fā)生泄漏占哟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一酿矢、第九天 我趴在偏房一處隱蔽的房頂上張望榨乎。 院中可真熱鬧,春花似錦瘫筐、人聲如沸蜜暑。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)肛捍。三九已至,卻和暖如春之众,著一層夾襖步出監(jiān)牢的瞬間拙毫,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工棺禾, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留缀蹄,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓膘婶,卻偏偏與公主長(zhǎng)得像缺前,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子竣付,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容