CMake

理論上來說,任意一個c++程序都可以使用g++來編譯捞蚂,但當程序規(guī)模越來越大時跷究,一個工程可能有許多的文件夾和源文件,這時輸入的編譯命令將會越來越長。因此潭袱,對于C++使用一些工程管理工具會更加高效锋恬。這里我們使用CMake。
在一個CMake工程中彤悔,我們會使用cmake命令生成一個Makefile文件索守,然后,用make命令根據(jù)這個 makefile文件的內(nèi)容來編譯整個工程杨赤。

入門案例:單個源文件
  1. 編寫 CMakeLists.txt
    首先編寫 CMakeLists.txt 文件,并保存在與 main.cc 源文件同個目錄下:
# 聲明要求的cmake最低版本
cmake_minimum_required (VERSION 2.8)
# 聲明一個cmake工程
project (HelloSLAM)
# 添加一個可執(zhí)行程序
#語法 :add_executable(程序名 源代碼文件)
add_executable(Demo main.cc)

CMakeLists.txt 文件用于告訴cmake我們要對這個目錄下的文件做什么事情植捎,CmakeLists.txt 文件的內(nèi)容需要遵守cmake的語法阳柔。

編譯項目

在當前目錄執(zhí)行 cmake . ,得到 Makefile 后再使用 make 命令編譯得到 Demo1 可執(zhí)行文件济锄。

cmake .

得到Makefile后再使用make命令編譯得到Demo1可執(zhí)行文件

多個源文件

上面的例子只有單個源文件拟淮,現(xiàn)在假如把power函數(shù)單獨寫進一個名為MathFunctions的源文件里谴忧,使得這個工程變成如下形式:

./Demo2
    |
    +--- main.cc
    |
    +--- MathFunctions.cc
    |
    +--- MathFunctions.h

這個時候,CMakeLists.txt 可以改成如下的形式:

# CMake 最低版本號要求
cmake_minimum_required (VERSION 2.8)
# 項目信息
project (Demo2)
# 指定生成目標
add_executable(Demo main.cc MathFunctions.cc)

唯一的改動只是在 add_executable命令中增加了一個 MathFunctions.cc源文件委造。這樣寫當然沒什么問題昏兆,但是如果源文件很多妇穴,把所有源文件的名字都加進去將是一件煩人的工作。更省事的方法是使用aux_source_directory命令跑筝,該命令會查找指定目錄下的所有源文件瞒滴,然后將結(jié)果存進指定變量名妓忍。其語法如下:

aux_source_directory(<dir> <variable>)

因此,可以修改 CMakeLists.txt 如下:

# CMake 最低版本號要求
cmake_minimum_required (VERSION 2.8)
# 項目信息
project (Demo2)
# 查找當前目錄下的所有源文件
# 并將名稱保存到 DIR_SRCS 變量
aux_source_directory(. DIR_SRCS)
# 指定生成目標
add_executable(Demo ${DIR_SRCS})

這樣定罢,CMake 會將當前目錄所有源文件的文件名賦值給變量DIR_SRCS 旁瘫,再指示變量 DIR_SRCS中的源文件需要編譯成一個名稱為Demo 的可執(zhí)行文件耕皮。

多個目錄凌停,多個源文件

現(xiàn)在進一步將 MathFunctions.hMathFunctions.cc文件移動到 math 目錄下罚拟。

./Demo3
    |
    +--- main.cc
    |
    +--- math/
          |
          +--- MathFunctions.cc
          |
          +--- MathFunctions.h

對于這種情況完箩,需要分別在項目根目錄 Demo3 和 math 目錄里各編寫一個 CMakeLists.txt 文件。為了方便阻逮,我們可以先將 math 目錄里的文件編譯成靜態(tài)庫再由 main 函數(shù)調(diào)用秩彤。
根目錄中的 CMakeLists.txt :

# CMake 最低版本號要求
cmake_minimum_required (VERSION 2.8)
# 項目信息
project(Demo3)
# 查找當前目錄下的所有源文件
# 并將名稱保存到 DIR_SRCS 變量
aux_source_directory(.DIR_SRCS)
# 添加 math 子目錄
add_subdirectory(math)
# 指定生成目標 
add_executable(Demo main.cc)
# 添加鏈接庫
target_link_libraries(Demo MathFunctions)

該文件添加了下面的內(nèi)容: 第3行漫雷,使用命令 add_subdirectory指明本項目包含一個子目錄 math,這樣 math 目錄下的CMakeLists.txt文件和源代碼也會被處理 与柑。第6行蓄坏,使用命令 target_link_libraries 指明可執(zhí)行文件 main 需要連接一個名為 MathFunctions 的鏈接庫 。

子目錄中的 CMakeLists.txt:

# 查找當前目錄下的所有源文件
# 并將名稱保存到 DIR_LIB_SRCS 變量
aux_source_directory(. DIR_LIB_SRCS)
# 生成鏈接庫
add_library (MathFunctions ${DIR_LIB_SRCS})

在該文件中使用命令 add_librarysrc 目錄中的源文件編譯為靜態(tài)鏈接庫干旧。

自定義編譯選項

CMake 允許為項目增加編譯選項,從而可以根據(jù)用戶的環(huán)境和需求選擇最合適的編譯方案挠将。

例如,可以將 MathFunctions 庫設(shè)為一個可選的庫乳丰,如果該選項為 ON 内贮,就使用該庫定義的數(shù)學(xué)函數(shù)來進行運算汞斧。否則就調(diào)用標準庫中的數(shù)學(xué)函數(shù)庫粘勒。
修改 CMakeLists 文件
第一步是在頂層的 CMakeLists.txt 文件中添加該選項:

# CMake 最低版本號要求
cmake_minimum_required (VERSION 2.8)
# 項目信息
project (Demo4)
# 加入一個配置頭文件庙睡,用于處理 CMake 對源碼的設(shè)置
configure_file (
  "${PROJECT_SOURCE_DIR}/config.h.in"
  "${PROJECT_BINARY_DIR}/config.h"
  )
# 是否使用自己的 MathFunctions 庫
option (USE_MYMATH
       "Use provided math implementation" ON)
# 是否加入 MathFunctions 庫
if (USE_MYMATH)
  include_directories ("${PROJECT_SOURCE_DIR}/math")
  add_subdirectory (math)  
  set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
endif (USE_MYMATH)
# 查找當前目錄下的所有源文件
# 并將名稱保存到 DIR_SRCS 變量
aux_source_directory(. DIR_SRCS)
# 指定生成目標
add_executable(Demo ${DIR_SRCS})
target_link_libraries (Demo  ${EXTRA_LIBS})

其中:

  1. 第7行的 configure_file 命令用于加入一個配置頭文件 config.h 技俐,這個文件由 CMake 從 config.h.in 生成,通過這樣的機制啡邑,將可以通過預(yù)定義一些參數(shù)和變量來控制代碼的生成井赌。
  2. 第13行的 option 命令添加了一個 USE_MYMATH 選項族展,并且默認值為 ON
  3. 第17行根據(jù) USE_MYMATH 變量的值來決定是否使用我們自己編寫的 MathFunctions 庫贵涵。

修改 main.cc文件

之后修改 main.cc]文件恰画,讓其根據(jù) USE_MYMATH 的預(yù)定義值來決定是否調(diào)用標準庫還是 MathFunctions 庫:

#include 
#include 
#include "config.h"
#ifdef USE_MYMATH
  #include "math/MathFunctions.h"
#else
  #include 
#endif
int main(int argc, char *argv[])
{
    if (argc < 3){
        printf("Usage: %s base exponent \n", argv[0]);
        return 1;
    }
    double base = atof(argv[1]);
    int exponent = atoi(argv[2]);
    
#ifdef USE_MYMATH
    printf("Now we use our own Math library. \n");
    double result = power(base, exponent);
#else
    printf("Now we use the standard library. \n");
    double result = pow(base, exponent);
#endif
    printf("%g ^ %d is %g\n", base, exponent, result);
    return 0;
}

編寫 config.h.in 文件

上面的程序值得注意的是第2行拴还,這里引用了一個 config.h 文件,這個文件預(yù)定義了 USE_MYMATH 的值端盆。但我們并不直接編寫這個文件费封,為了方便從 CMakeLists.txt 中導(dǎo)入配置,我們編寫一個 config.h.in文件焚鹊,內(nèi)容如下:

#cmakedefine USE_MYMATH

這樣 CMake 會自動根據(jù) CMakeLists 配置文件中的設(shè)置自動生成 config.h 文件

編譯項目
現(xiàn)在編譯一下這個項目韧献,為了便于交互式的選擇該變量的值研叫,可以使用 ccmake 命令

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嚷炉,一起剝皮案震驚了整個濱河市渤昌,隨后出現(xiàn)的幾起案子走搁,更是在濱河造成了極大的恐慌,老刑警劉巖忌栅,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件曲稼,死亡現(xiàn)場離奇詭異,居然都是意外死亡瑞驱,警方通過查閱死者的電腦和手機窄坦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進店門鸭津,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人盏阶,你說我怎么就攤上這事闻书。” “怎么了砰盐?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵杆融,是天一觀的道長脾歇。 經(jīng)常有香客問我,道長藕各,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任作彤,我火速辦了婚禮乌逐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘浙踢。我一直安慰自己,他們只是感情好洛波,可當我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布蹬挤。 她就那樣靜靜地躺著,像睡著了一般倦零。 火紅的嫁衣襯著肌膚如雪蓝翰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天诞帐,我揣著相機與錄音爆雹,去河邊找鬼。 笑死慧起,一個胖子當著我的面吹牛册倒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼估灿,長吁一口氣:“原來是場噩夢啊……” “哼馅袁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起汗销,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤抵窒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后钦奋,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體疙赠,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡圃阳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了富寿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锣夹。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡银萍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出贴唇,到底是詐尸還是另有隱情,我是刑警寧澤戳气,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布瓶您,位于F島的核電站纲仍,受9級特大地震影響贸毕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一击蹲、第九天 我趴在偏房一處隱蔽的房頂上張望婉宰。 院中可真熱鬧歌豺,春花似錦心包、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至堕虹,卻和暖如春芬首,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背郁稍。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留昼钻,地道東北人封寞。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓狈究,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子碎罚,可洞房花燭夜當晚...
    茶點故事閱讀 45,047評論 2 355

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