第一篇:最詳盡,最初心的的CMake技術(shù)文檔

CMake簡述

CMake旨在成為一個跨平臺的構(gòu)建流程管理器况木,因此它定義了它自己的腳本語言奋隶,具有一定的語法和內(nèi)置功能饵骨。 CMake本身是一個軟件程序陶贼,因此應(yīng)該使用腳本文件調(diào)用它來解釋和生成實際的構(gòu)建文件啤贩。
開發(fā)人員可以使用CMake語言為項目編寫簡單或復(fù)雜的構(gòu)建腳本。

使用CMake語言構(gòu)建邏輯和定義可以在CMakeLists.txt中編寫拜秧,也可以使用<project_name> .cmake編寫痹屹。 但作為最佳實踐,主腳本命名為CMakeLists.txt而不是cmake枉氮。

  • CMakeLists.txt文件位于要構(gòu)建的項目的源文件志衍。
  • CMakeLists.txt一般放置在整個工程項目文件夾的根目錄下。
  • 如果有多個模塊聊替,并且每個模塊可以單獨編譯和構(gòu)建楼肪,則可以將CMakeLists.txt插入到子文件夾中(本文僅提及單個CMakeLists.txt的示例)。
  • cmake文件可以用作腳本佃牛,它運行cmake命令來準(zhǔn)備環(huán)境預(yù)處理或拆分任務(wù)淹辞,這些任務(wù)可以在CMakeLists.txt之外編寫
  • cmake文件還可以為項目定義模塊 ,這些項目可以和庫程序文件分離構(gòu)建,也可以是復(fù)雜的多模塊項目的額外方法俘侠。

編寫Makefile可能比編寫CMake腳本更難象缀。 通過語法和邏輯的CMake腳本與高級語言具有相似性,因此開發(fā)人員可以更輕松地創(chuàng)建他們的cmake腳本爷速,而不會在Makefile中迷失央星。

常用的命令:

下文的示例會盡量用到這些命令

  • message:打印給定消息
  • cmake_minimum_required:設(shè)置要使用的最低的cmake版本
  • add_executable:添加具有給定名稱的可執(zhí)行目標(biāo)
  • add_library:從列出的源文件中添加要構(gòu)建的庫目標(biāo)
  • add_subdirectory:添加一個子目錄來構(gòu)建

還有一些命令可以讓開發(fā)人員編寫條件語句,循環(huán)惫东,迭代列表莉给,分配:

  • if, endif
  • elif, endif
  • while, endwhile
  • foreach, endforeach
  • list
  • return
  • set_property(分配值給變量)

縮寫不是強制性的毙石,但在編寫CMake腳本時建議使用。 CMake不使用';'來理解陳述的結(jié)尾颓遏。所有條件語句都應(yīng)該以相應(yīng)的結(jié)束命令結(jié)束(endif徐矩,endwhile,endforeach)CMake的所有這些屬性可幫助開發(fā)人員編寫復(fù)雜的構(gòu)建過程叁幢,包括多個模塊滤灯,庫和平臺。

CMake環(huán)境變量

環(huán)境變量用于配置編譯器標(biāo)志曼玩,鏈接器標(biāo)志鳞骤,常規(guī)構(gòu)建過程的測試配置。 必須引導(dǎo)編譯器搜索庫的給定目錄黍判。
從以下URL可以看到環(huán)境變量的詳細(xì)列表,可以參見一下鏈接:
https://cmake.org/cmake/help/latest/manual/cmake-env-variables.7.html

某些環(huán)境變量被預(yù)定義的CMake變量覆蓋豫尽。 例如 定義CMAKE_CXX_FLAGS時,CXXFLAGS將被覆蓋顷帖。

下面是一個示例用例美旧,當(dāng)您想在編譯過程中啟用所有警告時,您可以編寫-Wall to build命令窟她。 如果使用CMake構(gòu)建代碼陈症,可以使用set命令添加-Wall標(biāo)志。

set(CMAKE_CXX_FLAGS,"-Wall")
defined flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")

CMake變量

CMake包括預(yù)定義變量震糖,這些變量默認(rèn)設(shè)置為源樹和系統(tǒng)組件的位置。
變量區(qū)分大小寫趴腋,而不是命令吊说。 在變量的定義中,您只能使用字母數(shù)字字符和下劃線优炬,短劃線(_颁井, - )。
您可以在以下URL中找到有關(guān)CMake變量的更多詳細(xì)信息
https://cmake.org/cmake/help/v3.5/manual/cmake-language.7.html#variables

一些變量是根據(jù)根文件夾預(yù)定義的:

  • CMAKE_BINARY_DIR:構(gòu)建樹和二進(jìn)制輸出文件夾頂級的完整路徑蠢护,默認(rèn)情況下雅宾,它定義為構(gòu)建樹的頂級。
  • CMAKE_HOME_DIRECTORY:HOME目錄頂部的路徑
  • CMAKE_SOURCE_DIR:源文件目錄頂級的完整路徑葵硕。
  • CMAKE_INCLUDE_PATH:用于查找文件眉抬,路徑的路徑

可以使用$ {<variable_name>}訪問變量值

message("CXX Standard: ${CMAKE_CXX_STANDARD}")
set(CMAKE_CXX_STANDARD 14)

就像上面的變量一樣,您可以定義自己的變量懈凹。 您可以調(diào)用set命令將值設(shè)置為新變量或更改現(xiàn)有變量的值蜀变,如下所示:

set("APP_VERSION","1.0.1")
message("${APP_VERSION}")

CMake 列表

CMake中的所有值都存儲為字符串,但在某些上下文中可以將字符串視為列表介评。

通過連接由半列';'分隔的元素表示為字符串的元素列表

set(files a.txt b.txt c.txt)
# sets files to "a.txt;b.txt;c.txt"

要訪問值列表库北,您可以使用CMake的foreach命令爬舰,如下所示:

foreach(file ${files})
    message("Filename: ${file}")
endforeach()

完整的表達(dá)式列表可以看這里
https://cmake.org/cmake/help/v3.8/manual/cmake-generator-expressions.7.html

使用CMake構(gòu)建C ++項目

在前面的部分中,我們介紹了編寫CMake腳本的核心原則寒瓦。 現(xiàn)在情屹,我們可以構(gòu)建一個基本的鏈表為示例。

如圖所示:


vs-code示例

很明顯杂腰,對于這樣一個小項目來說垃你,使用CMake是多余的,但是當(dāng)事情變得復(fù)雜時颈墅,它會有很大幫助蜡镶。

為了構(gòu)建main.cpp,在項目的根目錄下創(chuàng)建一個CMakeLists.txt,并且寫入如下代,然后執(zhí)行cmake命令

/**/
cmake_minimum_required(VERSION 3.9.1)
/*設(shè)定項目的名稱*/
project(cmake_tor)
/*我們編譯的目標(biāo)文件*/
add_executable(cmake_tor main.cpp)

然后在vscode終端中使用運行cmake命令,CMake會生成如下文件和目錄

  • Makefile腳本,這個是我們執(zhí)行對編譯后的程序,執(zhí)行tarball安裝方式的 時候需要用到make腳本恤筛。
  • CMakeCache.txt:這個是CMake會根據(jù)你的開發(fā)環(huán)境自動生成一些腳本的預(yù)設(shè)配置官还。如果當(dāng)前的預(yù)設(shè)配置不符合你的要求,從該文件拷貝相關(guān)的配置條目到CMakeLists.txt,修改配置選項后,重新執(zhí)行一次cmake即可生成符合你需求的配置。
  • CMakeFiles目錄:里面包含日志文件和一些臨時的二進(jìn)制文件,一般我們是不用理會的.


問題導(dǎo)入

我們的目的是生成一個二進(jìn)制文件毒坛,但我們這里首先看一下剛才配置有哪些不足之處望伦?

  • 首先,我們希望cmake生成的文件放到一個指定的目錄里面,這樣我們的項目不至于雜亂無章。
  • 其次,我希望能夠使用自己指定的C/C++編譯器,而不是cmake預(yù)定義的操作系統(tǒng)默認(rèn)的編譯器煎殷。
  • 最后,希望執(zhí)行make命令的時候,編譯后的可執(zhí)行程序和庫文件存放到一個有別于其他cmake文件夾的特殊目錄屯伞。

下面先看看我們之后改進(jìn)的項目目錄結(jié)構(gòu),如下圖,這是更符合我們實際開發(fā)工作中的一個目錄結(jié)構(gòu)。


屏幕快照 2019-08-24 上午11.53.59.png

那么豪直,我們帶著這三個問題定制自己的CMake配置方案吧劣摇!

首先,我們在項目的根目錄先手動創(chuàng)建一個build的文件夾,在VSCode的終端重定向到build目錄之下.

$ mkdir build
$ cd build

然后,在CMakeLists.txt使用以下cmake腳本,每個腳本的語句,代碼中有注解

cmake_minimum_required(VERSION 3.1.0)
#設(shè)定c編譯器和c++編譯器,必須放在整個腳本的開頭
set(CMAKE_C_COMPILER /usr/local/bin/gcc)
set(CMAKE_CXX_COMPILER /usr/local/bin/g++)

#工程項目的名稱
project(cmake_tor)

#包含headers和source目錄
include_directories(
    "${PROJECT_SOURCE_DIR}/headers"
    "${PROJECT_SOURCE_DIR}/source"
)

# 修正在macOS下CMAKE_CXX_STANDARD判斷C++編譯器標(biāo)準(zhǔn)的
#出錯的bug,如果你用到是Windows/Linux系統(tǒng),可以忽略這條語句
if (POLICY CMP0025)
  cmake_policy(SET CMP0025 NEW)
endif ()

#讓CMake自動檢測gcc的支持的c++標(biāo)準(zhǔn),
#根據(jù)CMake的版本號判斷它所支持c++標(biāo)準(zhǔn)
if(CMAKE_VERSION VERSION_LESS "3.8")
    set(CMAKE_CXX_STANDARD 14)
    message("The compile ${CMAKE_CXX_COMPILER} use C++14 standard!!")
elseif(CMAKE_VERSION VERSION_LESS "3.11")
    set(CMAKE_CXX_STANDARD 17)
    message("The compile ${CMAKE_CXX_COMPILER} use C++17 standard!!")
else()
    set(CMAKE_CXX_STANDARD 20)
    message("The compile ${CMAKE_CXX_COMPILER} use C++20 standard!!")
endif()
set(CMAKE_CXX_EXTENSIONS OFF)

#構(gòu)建自己的軟件系統(tǒng)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/app)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/libs)

add_executable(main "${PROJECT_SOURCE_DIR}/source/main.cpp")
add_library(shape SHARED "${PROJECT_SOURCE_DIR}/source/shape.c")

最后執(zhí)行cmake和make弓乙,我們會發(fā)現(xiàn)如下圖,正如我們所愿在指定的目錄下生成了一個可執(zhí)行文件和共享對象文件

$ cmake
$ make

結(jié)束語:
第一次接觸CMake的同學(xué),可能覺得無從入手,單獨花上一段時間去完全掌握它得不償失,本文是對以前遇到的一些典型問題做成一個易懂的教程末融。

帶著問題去stackflow尋找一些相關(guān)問題的答案是很好的學(xué)習(xí)方法之一,至少你在碰壁的時候,不會為了某個方面迷失了自我,然后自己去根據(jù)前人提供的建議去實踐并歸納到一個文件里,這樣就變成你自己已經(jīng)掌握的技能了。

技術(shù)文~~分享至此,希望你喜歡暇韧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末勾习,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子懈玻,更是在濱河造成了極大的恐慌巧婶,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件涂乌,死亡現(xiàn)場離奇詭異艺栈,居然都是意外死亡,警方通過查閱死者的電腦和手機骂倘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進(jìn)店門眼滤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人历涝,你說我怎么就攤上這事诅需⊙Γ” “怎么了?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵堰塌,是天一觀的道長赵刑。 經(jīng)常有香客問我,道長场刑,這世上最難降的妖魔是什么般此? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮牵现,結(jié)果婚禮上铐懊,老公的妹妹穿的比我還像新娘。我一直安慰自己瞎疼,他們只是感情好科乎,可當(dāng)我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著贼急,像睡著了一般茅茂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上太抓,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天空闲,我揣著相機與錄音,去河邊找鬼走敌。 笑死碴倾,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的掉丽。 我是一名探鬼主播影斑,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼机打!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起片迅,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤残邀,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后柑蛇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體芥挣,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年耻台,在試婚紗的時候發(fā)現(xiàn)自己被綠了空免。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡盆耽,死狀恐怖蹋砚,靈堂內(nèi)的尸體忽然破棺而出扼菠,到底是詐尸還是另有隱情,我是刑警寧澤坝咐,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布循榆,位于F島的核電站,受9級特大地震影響墨坚,放射性物質(zhì)發(fā)生泄漏秧饮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一泽篮、第九天 我趴在偏房一處隱蔽的房頂上張望盗尸。 院中可真熱鬧,春花似錦帽撑、人聲如沸泼各。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽历恐。三九已至,卻和暖如春专筷,著一層夾襖步出監(jiān)牢的瞬間弱贼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工磷蛹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留吮旅,地道東北人。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓味咳,卻偏偏與公主長得像庇勃,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子槽驶,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,941評論 2 355

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