CMake

理論上來說,任意一個(gè)c++程序都可以使用g++來編譯,但當(dāng)程序規(guī)模越來越大時(shí),一個(gè)工程可能有許多的文件夾和源文件,這時(shí)輸入的編譯命令將會(huì)越來越長(zhǎng)。因此,對(duì)于C++使用一些工程管理工具會(huì)更加高效。這里我們使用CMake。
在一個(gè)CMake工程中,我們會(huì)使用cmake命令生成一個(gè)Makefile文件,然后,用make命令根據(jù)這個(gè) makefile文件的內(nèi)容來編譯整個(gè)工程。

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

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

編譯項(xiàng)目

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

cmake .

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

多個(gè)源文件

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

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

這個(gè)時(shí)候,CMakeLists.txt 可以改成如下的形式:

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

唯一的改動(dòng)只是在 add_executable命令中增加了一個(gè) MathFunctions.cc源文件。這樣寫當(dāng)然沒什么問題,但是如果源文件很多,把所有源文件的名字都加進(jìn)去將是一件煩人的工作。更省事的方法是使用aux_source_directory命令,該命令會(huì)查找指定目錄下的所有源文件,然后將結(jié)果存進(jìn)指定變量名。其語法如下:

aux_source_directory(<dir> <variable>)

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

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

這樣,CMake 會(huì)將當(dāng)前目錄所有源文件的文件名賦值給變量DIR_SRCS ,再指示變量 DIR_SRCS中的源文件需要編譯成一個(gè)名稱為Demo 的可執(zhí)行文件。

多個(gè)目錄,多個(gè)源文件

現(xiàn)在進(jìn)一步將 MathFunctions.hMathFunctions.cc文件移動(dòng)到 math 目錄下。

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

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

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

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

子目錄中的 CMakeLists.txt:

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

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

自定義編譯選項(xiàng)

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

例如,可以將 MathFunctions 庫(kù)設(shè)為一個(gè)可選的庫(kù),如果該選項(xiàng)為 ON ,就使用該庫(kù)定義的數(shù)學(xué)函數(shù)來進(jìn)行運(yùn)算。否則就調(diào)用標(biāo)準(zhǔn)庫(kù)中的數(shù)學(xué)函數(shù)庫(kù)。
修改 CMakeLists 文件
第一步是在頂層的 CMakeLists.txt 文件中添加該選項(xiàng):

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

其中:

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

修改 main.cc文件

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

#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行,這里引用了一個(gè) config.h 文件,這個(gè)文件預(yù)定義了 USE_MYMATH 的值。但我們并不直接編寫這個(gè)文件,為了方便從 CMakeLists.txt 中導(dǎo)入配置,我們編寫一個(gè) config.h.in文件,內(nèi)容如下:

#cmakedefine USE_MYMATH

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

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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • CMake學(xué)習(xí) 本篇分享一下有關(guān)CMake的一些學(xué)習(xí)心得以及相關(guān)使用。 本文目錄如下: [1、CMake介紹] [...
    AlphaGL閱讀 12,441評(píng)論 11 79
  • 搬運(yùn)自本人 CSDN 博客:https://blog.csdn.net/ajianyingxiaoqinghan/...
    琦小蝦閱讀 15,660評(píng)論 0 11
  • CMake 全稱“cross platform make”,是開源、跨平臺(tái)的自動(dòng)化構(gòu)建系統(tǒng)。CMake 由 Kit...
    神齊閱讀 4,300評(píng)論 0 6
  • 已是初夏的天,悶熱讓沉睡一年的風(fēng)扇咯吱咯吱的開始轉(zhuǎn)動(dòng)。就連窗外的風(fēng)都帶著火,開窗能感覺到臉龐上的灼燒痛。 天空感覺...
    風(fēng)向南飛fly閱讀 384評(píng)論 0 3
  • 清明假期,又逢霧霾,外出和相聚最好,城市中的春天已逝,郊外正當(dāng)時(shí)。 養(yǎng)蜂人更早知道春天的腳步,早在這里,說明我的方...
    sampan2003閱讀 316評(píng)論 0 0

友情鏈接更多精彩內(nèi)容