CMake


友情提示,下面一大段都是廢話,可以直接跳到后面的部分...

工作以來(lái),一直從事的是基于Windows的C/C++開發(fā)工作枫疆。當(dāng)然,使用最多的當(dāng)數(shù)號(hào)稱宇宙第一IDE的Visual Studio集成開發(fā)環(huán)境蛾洛,依稀還記得大學(xué)時(shí)候用的那個(gè)Visual C++ 6.0,對(duì)于一個(gè)剛剛上了兩節(jié)C++課的懵懂少年來(lái)說(shuō),難以想象居然還有如此強(qiáng)大的軟件轧膘,點(diǎn)兩下鼠標(biāo)就能運(yùn)行一個(gè)Hello World程序钞螟,簡(jiǎn)直牛逼!后來(lái)逐漸接觸了VS05谎碍、08等鳞滨,最近兩年主要使用的版本是2015,也自認(rèn)為還是有一定了解的蟆淀。

也是在大學(xué)的時(shí)候拯啦,曾經(jīng)有半年的時(shí)間瘋狂的迷上了折騰各種各樣的操作系統(tǒng),Windows從2000到8.1的各個(gè)本版熔任,幾乎所有的常見Linux發(fā)行版褒链,甚至還安裝過(guò)蘋果的X OS系統(tǒng)(解決過(guò)經(jīng)典的“五國(guó)語(yǔ)言”錯(cuò)誤,后來(lái)折騰到勉強(qiáng)能開機(jī)疑苔,但是后來(lái)還是因?yàn)楦鞣N硬件驅(qū)動(dòng)問(wèn)題甫匹,最終放棄),以上的各種折騰都是在實(shí)體機(jī)上面做的惦费,因?yàn)楫?dāng)時(shí)的筆記本性能低下(什么酷睿2雙核處理器兵迅,內(nèi)存2G,硬盤256GB)薪贫,虛擬機(jī)運(yùn)行的體驗(yàn)極差恍箭。經(jīng)歷了各種艱難的抉擇之后,最終選定了CentOS作為筆記本上唯一的一個(gè)操作系統(tǒng)日常使用了將近兩個(gè)月的時(shí)間(后面由于坑爹的舍友強(qiáng)烈要求玩DOTA又安裝回了Windows XP)瞧省。

扯遠(yuǎn)了扯夭,回過(guò)頭來(lái)介紹CMake。我們知道在Windows平臺(tái)下構(gòu)建一個(gè)稍微復(fù)雜一些的C/C++項(xiàng)目臀突,我們可以利用Visual Studia直接創(chuàng)建一個(gè)工程勉抓,在幾乎完全的圖形化界面下對(duì)我們的項(xiàng)目進(jìn)行配置管理,然后進(jìn)行構(gòu)建之后就可以生成我們的可執(zhí)行文件了候学。這樣看起來(lái)非常方便藕筋,對(duì)于程序開發(fā)人員可以將更多的精力放在程序的邏輯和需求上去∈崧耄可是隐圾,我們雖然很好的完成了任務(wù),但卻會(huì)對(duì)IDE形成很大的依賴掰茶,而且這種依賴會(huì)越來(lái)越大暇藏。一旦有一天離開這些IDE,你會(huì)發(fā)現(xiàn)工作起來(lái)會(huì)及其的痛苦濒蒋。那么在Linux這樣甚至沒有圖形界面的平臺(tái)上我們?nèi)绾蝿?chuàng)建一個(gè)復(fù)雜的工程呢盐碱,答案就是使用CMake工具(當(dāng)然還有一些其他的方法把兔,比如直接編寫makefile)。


下面將列出我自己在編寫CMakeLists.txt文件的時(shí)候遇到的各種問(wèn)題并給出解答瓮顽,希望能夠幫到你县好。

  1. 一些基本的東西
    • CMake工具的配置文件名稱為CMakeLists.txt,錯(cuò)一個(gè)字符都不行暖混,哪怕只是大小寫不符缕贡;
    • 腳本語(yǔ)言預(yù)留了一些長(zhǎng)得像函數(shù)一樣的關(guān)鍵字稱為命令,比如cmake_minimum_required()拣播,奇怪的是命令卻是大小寫不敏感的你可以寫成CMakE_MinimUM_ReqUirED()(如果你高興的話)晾咪,個(gè)人習(xí)慣能小寫的盡量小寫;
    • 使用#進(jìn)行注釋贮配,就像C++中的//一樣谍倦;
    • 一般命令可以接收不確定個(gè)數(shù)的參數(shù),就像這樣add_executable(ABC A.cpp B.cpp C.cpp)牧嫉,不幸的是多個(gè)參數(shù)之間并不是像我們習(xí)以為常的一樣使用逗號(hào)進(jìn)行分割剂跟,而是空格。一般的參數(shù)你可以使用引號(hào)引起來(lái)酣藻,當(dāng)然也可以不加引號(hào)曹洽,除非你的參數(shù)中本身就包含空格;
    • 一個(gè)CMakeLists.txt總是以這樣一個(gè)命令開頭:cmake_minimum_required(VERSION 2.8)辽剧,正如你看到的VERSION這個(gè)單詞只能大寫 :-( 送淆,該命令指定了運(yùn)行本配置文件所需的CMake最低版本(我們?cè)趺床拍苤雷畹桶姹臼嵌嗌倌兀课姨孛匆膊恢琅陆危汶S便寫一個(gè)吧偷崩!╮( ̄▽  ̄)╭);
    • 還有一行的最后是不需要分號(hào)的撞羽。
  2. 設(shè)置項(xiàng)目名稱
    • project ("your project name")
    • 給你的項(xiàng)目取一個(gè)優(yōu)雅或者霸氣的名字阐斜;
  3. 打印信息
    • message("your messages")
    • 在執(zhí)行cmake命令是會(huì)在終端打印指定的信息。如果你遇到了問(wèn)題诀紊,希望看一下某個(gè)環(huán)境變量或自定義變量的值谒出,那么你可以使用該命令,例如:message(${CMAKE_CXX_FLAGS})
  4. 設(shè)置變量
    • set(KCBP_PATH e:/SVN/kbsskcbp)
    • 可以定義自定義變量邻奠,也可以用來(lái)修改CMake的預(yù)定義變量笤喳,例如設(shè)置編譯是Debug還是Release版本set(CMAKE_BUILD_TYPE Release),使用變量的方式是${YOUR_VARIABLE}
  5. 指定頭文件目錄
    • include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])
    • target_include_directories(<target> [SYSTEM] [BEFORE] <INTERFACE|PUBLIC|PRIVATE> [items1...] [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
    • 以上兩個(gè)命令都可以用于添加包含目錄碌宴,第一個(gè)命令設(shè)置的包含目錄作用域是當(dāng)前CMakeLists.txt文件杀狡,而第二個(gè)命令可以指定為生成的某個(gè)可執(zhí)行文件或庫(kù)文件單獨(dú)設(shè)置包含目錄。
    • 幾個(gè)參數(shù):
      • [BEFORE]:官方的解釋“If BEFORE is specified, the content will be prepended to the property instead of being appended”贰镣,翻譯一下“如果[BEFORE]參數(shù)被指定呜象,包含目錄將被預(yù)先設(shè)置為屬性而非追加”膳凝;
      • [SYSTEM]:指定該參數(shù),編譯器將被告知該包含目錄為系統(tǒng)的包含目錄恭陡;
      • <INTERFACE|PUBLIC|PRIVATE>:指定包含目錄的作用范圍鸠项,不同的組合會(huì)修改不同的項(xiàng)目屬性字段。
  6. 指定鏈接庫(kù)目錄
    • link_directories(directory1 directory2 ...)
    • 很好理解子姜,沒有可說(shuō)的,但是官方文檔有一句話 “Note that this command is rarely necessary”楼入。
  7. 鏈接庫(kù)文件
    • link_libraries([item1 [item2 [...]]] [[debug|optimized|general] <item>] ...)
    • target_link_libraries(<target> ... <item>... ...)
    • 以上兩個(gè)命令都可以實(shí)現(xiàn)鏈接指定的庫(kù)文件哥捕,link_libraries沒有指定具體鏈接到哪一個(gè)目標(biāo),因此它適用于鏈接那些基礎(chǔ)公共的嘉熊,在項(xiàng)目中每個(gè)生成項(xiàng)目中都會(huì)被使用到的庫(kù)遥赚;target_link_libraries可以指定具體將庫(kù)鏈接給哪一個(gè)目標(biāo),因此它適用于僅在某個(gè)生成項(xiàng)目中使用到的庫(kù)阐肤,另外還應(yīng)該注意官方文檔中有這樣一句話“The target_link_libraries() command should be preferred whenever possible. Library dependencies are chained automatically, so directory-wide specification of link libraries is rarely needed.”凫佛,因此更加推薦使用target_link_libraries
    • 參數(shù)[debug|optimized|general]指定在那些配置下該鏈接項(xiàng)目生效孕惜。另外愧薛,該命令也支持PRIVATE|PUBLIC|INTERFACE參數(shù)。
  8. 生成可執(zhí)行文件
    • add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] [source1] [source2 ...])
    • 命令比較簡(jiǎn)單衫画,添加一個(gè)名稱為<name>的毫炉,由一個(gè)或多個(gè)源文件編譯鏈接而成的可執(zhí)行文件。中間的三個(gè)可選參數(shù)可以理解為在生成時(shí)設(shè)置了相應(yīng)的屬性削罩。
    • add_executable(<name> IMPORTED [GLOBAL])該命令導(dǎo)入一個(gè)當(dāng)前項(xiàng)目以外的目標(biāo)瞄勾,以使其在邏輯上屬于當(dāng)前項(xiàng)目,因此也就實(shí)現(xiàn)了引用當(dāng)前項(xiàng)目以外資源的功能弥激。需要注意的是进陡,該命令僅僅是引入一個(gè)外部目標(biāo),并不會(huì)構(gòu)建一個(gè)新的目標(biāo)微服。舉例:
      add_executable(generator IMPORTED)  
      set_property(TARGET generator PROPERTY IMPORTED_LOCATION "/path/to/some_generator")
      set(GENERATED_SRC ${CMAKE_CURRENT_BINARY_DIR}/generated.c)
      add_custom_command(OUTPUT ${GENERATED_SRC} COMMAND generator ${GENERATED_SRC})
      add_executable(myexe src1.c src2.c ${GENERATED_SRC})
      
    • add_executable(<name> ALIAS <target>)該命令用于為指定目標(biāo)創(chuàng)建一個(gè)別名趾疚。按照個(gè)人的理解應(yīng)該是類似于我們編程開發(fā)當(dāng)中的引用的概念吧。具體還沒有使用過(guò)职辨,如果理解有誤盗蟆,萬(wàn)望指正。
  9. 生成庫(kù)文件
    • add_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] [source1] [source2 ...])
    • 可選參數(shù)STATIC生成靜態(tài)庫(kù)舒裤、SHARED生成動(dòng)態(tài)庫(kù)喳资、MODULE庫(kù)是不會(huì)被鏈接到其他庫(kù),但可以在運(yùn)行時(shí)通過(guò)dlopen-like函數(shù)動(dòng)態(tài)加載的插件腾供;EXCLUDE_FROM_ALL參數(shù)指定在構(gòu)建是會(huì)添加相應(yīng)的屬性仆邓。
  10. 指定生成Debug還是Release版本
    • CMAKE_BUILD_TYPE該變量可被設(shè)置為Debug Release RelWithDebInfo MinSizeRel之一鲜滩。當(dāng)這個(gè)變量值為Debug時(shí)CMake 會(huì)使用變量CMAKE_CXX_FLAGS_DEBUGCMAKE_C_FLAGS_DEBUG中的字符串作為編譯選項(xiàng),當(dāng)這個(gè)變量值為Release時(shí)节值,工程會(huì)使用變量CMAKE_CXX_FLAGS_RELEASECMAKE_C_FLAGS_RELEASE作為編譯選項(xiàng)徙硅。
  11. 指定編譯選項(xiàng)
    • 設(shè)置變量CMAKE_<LANG>_FLAGS_<CONFIG>的值,可以指定語(yǔ)言以及配置搞疗。
  12. 增加預(yù)處理定義
    • add_definitions(-DFOO -DBAR ...)注意預(yù)處理定義需要以 -D開頭嗓蘑。
    • 事實(shí)上add_definitions可以用來(lái)添加任何標(biāo)志,比如包含目錄和編譯選項(xiàng)匿乃,功能應(yīng)該類似于Visual Studio項(xiàng)目配置中的命令行功能桩皿,但通常習(xí)慣上只用它來(lái)增加預(yù)處理定義。
    • CMake文檔中建議使用另外三個(gè)命令來(lái)替代add_definitions
      • Use add_compile_definitions()to add preprocessor definitions
      • Use include_directories()to add include directories
      • Use add_compile_options()to add other options
  13. 添加子目錄
    • add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
    • 可選參數(shù)binary_dir指定子目錄生成的目標(biāo)的存放位置幢炸,指定EXCLUDE_FROM_ALL參數(shù)意味著子目錄的生成目標(biāo)將默認(rèn)不被包含在父目錄所生成的目標(biāo)當(dāng)中泄隔,并且從IDE工程文件中排除。
    • 當(dāng)然并非僅僅使用add_subdirectory命令就可以添加子目錄了宛徊,你還必須為子目錄編寫一個(gè)CMakeLists.txt腳本文件并放置在子目錄中才可以佛嬉。
  14. 獲取文件列表
    • aux_source_directory(<dir> <variable>)獲取dir目錄當(dāng)中的所有源文件名稱并保存在自定義變量variable當(dāng)中,該命令的主要作用是避免手動(dòng)寫出一堆的文件名稱闸天。例如我們需要使用100個(gè)源文件構(gòu)建成一個(gè)庫(kù)文件或可執(zhí)行文件暖呕,我們只需要將所有源文件放在一個(gè)目錄中并使用該命令獲取到文件列表,然后將該列表傳遞給add_libraryadd_executable即可苞氮。
  15. 流程控制

CMake是一個(gè)龐大的項(xiàng)目,包含非常多的內(nèi)容赞厕,本文僅僅是介紹了自己在項(xiàng)目當(dāng)中使用到的一部分艳狐,對(duì)于CMake個(gè)人也是處于不斷學(xué)習(xí)和自我糾正的過(guò)程中,如果文檔有錯(cuò)誤或不妥之處皿桑,還希望大家能給予批評(píng)指正毫目,我將不勝感激。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末诲侮,一起剝皮案震驚了整個(gè)濱河市镀虐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌沟绪,老刑警劉巖刮便,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異绽慈,居然都是意外死亡恨旱,警方通過(guò)查閱死者的電腦和手機(jī)辈毯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)搜贤,“玉大人谆沃,你說(shuō)我怎么就攤上這事∫敲ⅲ” “怎么了唁影?”我有些...
    開封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)掂名。 經(jīng)常有香客問(wèn)我夭咬,道長(zhǎng),這世上最難降的妖魔是什么铆隘? 我笑而不...
    開封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮南用,結(jié)果婚禮上膀钠,老公的妹妹穿的比我還像新娘。我一直安慰自己裹虫,他們只是感情好肿嘲,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著筑公,像睡著了一般雳窟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上匣屡,一...
    開封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天封救,我揣著相機(jī)與錄音,去河邊找鬼捣作。 笑死誉结,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的券躁。 我是一名探鬼主播惩坑,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼也拜!你這毒婦竟也來(lái)了以舒?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤慢哈,失蹤者是張志新(化名)和其女友劉穎蔓钟,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體卵贱,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡奋刽,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年瓦侮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片佣谐。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡肚吏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出狭魂,到底是詐尸還是另有隱情罚攀,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布雌澄,位于F島的核電站斋泄,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏镐牺。R本人自食惡果不足惜炫掐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望睬涧。 院中可真熱鬧募胃,春花似錦、人聲如沸畦浓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)讶请。三九已至祷嘶,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間夺溢,已是汗流浹背论巍。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留风响,地道東北人环壤。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像钞诡,于是被迫代替她去往敵國(guó)和親郑现。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

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