CMake實戰

本文不介紹cmake命令使用方法,也不講CMakeLists.txt的語法,有需要的讀者可以看我另外相關的文章即可(此為實戰篇)。

本文核心講解添加版本支持、添加編譯庫支持、添加編譯選項支持、添加庫版本信息、添加多文件支持、添加安裝路勁支持、添加測試驗證支持、添加依賴函數與頭文件與庫文件支持、添加三方庫依賴搜索支持、添加生成中間文件支持、添加生成發行版本安裝包支持等功能

本文共分14章,為了便于學習,內容組織如下:

  • 前面1~7章為基本常用方法,可滿足大部分項目需求;

  • 接下來三(8~10)章節非常簡單,用于支持依賴的檢測,便于學習人員歇口氣;

  • 后面的11~14章為高級功能,可以查詢未知依賴、生成中間依賴文件,還可以制作標準的安裝包。

廢話少說,直接上主菜(復雜的解釋也略過了)。有需要的,可以聯系我獲取每章節的實例。

一、基本工程

最簡單的工程是編譯一個源文件,并生成一個可執行文件。CMakeLists.txt僅僅只需要3行:


cmake_minimum_required(VERSION 2.8)

project(Tutorial)

add_executable(Tutorial tutorial.cxx)

對應的tutorial.cxx源碼用于計算輸入數據的平方根:


// A simple program that computes the suqare root of a number

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

int main(int argc, char *argv[])

{

if (argc < 2)

{

fprintf(stdout, "Usage: %s number\n", argv[0]);

return 1;

}

double inputValue = atof(argv[1]);

double outputValue = sqrt(inputValue);

fprintf(stdout, "The square root of %g is %g\n", inputValue, outputValue);

return 0;

}

將tutorial.cxx與CMakeLists.txt放在同一目錄,創建build目錄,并編譯、運行,結果如下:


$ mkdir build

$ ls

build  CMakeLists.txt  tutorial.cxx

$ cd build/

$ cmake ..

-- The C compiler identification is GNU 4.8.5

-- The CXX compiler identification is GNU 4.8.5

-- Check for working C compiler: /usr/bin/cc

-- Check for working C compiler: /usr/bin/cc -- works

-- Detecting C compiler ABI info

-- Detecting C compiler ABI info - done

-- Detecting C compile features

-- Detecting C compile features - done

-- Check for working CXX compiler: /usr/bin/c++

-- Check for working CXX compiler: /usr/bin/c++ -- works

-- Detecting CXX compiler ABI info

-- Detecting CXX compiler ABI info - done

-- Detecting CXX compile features

-- Detecting CXX compile features - done

-- Configuring done

-- Generating done

-- Build files have been written to: /work/study/Studied_Module/Module/cmake/basic_point/build

$ make

Scanning dependencies of target Tutorial

[ 50%] Building CXX object CMakeFiles/Tutorial.dir/tutorial.cxx.o

[100%] Linking CXX executable Tutorial

[100%] Built target Tutorial

$ ./Tutorial

Usage: ./Tutorial number

$ ./Tutorial 9

The square root of 9 is 3

二、添加配置頭文件

有時候我們需要為我們的代碼添加版本信息,或者其他相關的配置信息。我們當然可以通過直接添加配置的頭文件來實現,不過通過CMakeLists.txt來實現會更加的靈活。下面是基于前面例子實現添加版本信息的CMakeLists.txt:


cmake_minimum_required(VERSION 2.8)

project(Tutorial)

# The version number

set (Tutorial_VERSION_MAJOR 1)

set (Tutorial_VERSION_MINOR 0)

# configure a header file to pass some of the CMake settings

# to the source code

configure_file (

"${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"

"${PROJECT_BINARY_DIR}/TutorialConfig.h"

)

# add the binary tree to the search path for include files

# so that we will find TutorialConfig.h

include_directories("${PROJECT_BINARY_DIR}")

# add the executable

add_executable(Tutorial tutorial.cxx)

上面指定TutorialConfig.h由TutorialConfig.h.in文件生成。TutorialConfig.h.in的內容如下:


// the configured options and settings for Tutorial

#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@

#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@

當CMake配置這個頭文件時,@Tutorial_VERSION_MAJOR@和@Tutorial_VERSION_MINOR@的值將被CMakeLists.txt文件中的值替換(注意兩邊的名字要一致)。

接下來我們修改tutorial.cxx源碼,看是如何使用CMakeLists.txt定義的版本的:


// A simple program that computes the suqare root of a number

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

#include "TutorialConfig.h"

int main(int argc, char *argv[])

{

if (argc < 2)

{

fprintf(stdout, "%s Version %d.%d\n", argv[0],

Tutorial_VERSION_MAJOR, Tutorial_VERSION_MINOR);

fprintf(stdout, "Usage: %s number\n", argv[0]);

return 1;

}

double inputValue = atof(argv[1]);

double outputValue = sqrt(inputValue);

fprintf(stdout, "The square root of %g is %g\n", inputValue, outputValue);

return 0;

}

建立build目錄,再次編譯結果如下:


$ mkdir build

$ ls

build  CMakeLists.txt  TutorialConfig.h.in  tutorial.cxx

$ cd build/

$ cmake ..

-- The C compiler identification is GNU 4.8.5

-- The CXX compiler identification is GNU 4.8.5

-- Check for working C compiler: /usr/bin/cc

-- Check for working C compiler: /usr/bin/cc -- works

-- Detecting C compiler ABI info

-- Detecting C compiler ABI info - done

-- Detecting C compile features

-- Detecting C compile features - done

-- Check for working CXX compiler: /usr/bin/c++

-- Check for working CXX compiler: /usr/bin/c++ -- works

-- Detecting CXX compiler ABI info

-- Detecting CXX compiler ABI info - done

-- Detecting CXX compile features

-- Detecting CXX compile features - done

-- Configuring done

-- Generating done

-- Build files have been written to: /work/study/Studied_Module/Module/cmake/basic_version/build

$ make

Scanning dependencies of target Tutorial

[ 50%] Building CXX object CMakeFiles/Tutorial.dir/tutorial.cxx.o

[100%] Linking CXX executable Tutorial

[100%] Built target Tutorial

$ ./Tutorial

./Tutorial Version 1.0

Usage: ./Tutorial number

$ ./Tutorial 16

The square root of 16 is 4

總結:添加配置頭文件的流程如下:

  1. 在CMakeLists.txt中通過set命令設置自己命名的變量;

  2. 添加配置文件說明:


configure_file (

"${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"

"${PROJECT_BINARY_DIR}/TutorialConfig.h"

)

  1. 創建配置文件*.h.in,并使用@variable@來訪問第一步在CMakeLists.txt通過set定義的變量,使用C/C++的標準#define來定義;

  2. 在C/C++源碼中通過include包含編譯生成的配置頭文件;

  3. 在C/C++源碼中直接使用#define宏定義的名稱。

三、添加一個庫

繼續基于前面的實例,我們將計算平方根的方法提取出來,做成一個mysqrt.cxx源文件庫放在MathFunctions目錄,我們提供的算法名稱為mysqrt()。源碼如下:


$ cd MathFunctions/

$ cat mysqrt.h

#ifndef MYSQRT_H__

#define MYSQRT_H__

double mysqrt(double x);

#endif

$ cat mysqrt.cxx

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

double mysqrt(double x)

{

double g = x;

while(fabs(g*g - x) > 0.000001)

{

g = (g+x/g)/2;

}

return g;

}

在MathFunctions目錄中添加子CMakeLists.txt,編譯生成庫文件:


$ cat CMakeLists.txt

cmake_minimum_required(VERSION 2.8)

project(MathFunctions)

add_library(MathFunctions SHARED mysqrt.cxx)

接下來修改頂層CMakeLists.txt,添加子目錄MathFunctions的編譯支持,添加頭文件依賴路徑,并添加依賴的庫說明:


include_directories("${PROJECT_SOURCE_DIR}/MathFunctions")

add_library(MathFuncions)

# add the executable

add_executable(Tutorial tutorial.cxx)

add_link_libraries(Tutorial MathFunctions)

最后,修改tutorial.cxx源碼,添加代碼調用我們自己的mysqrt()函數(這里同時調用,還可以驗證我們的算法是否正確):


    double inputValue = atof(argv[1]);

double outputValue = sqrt(inputValue);

fprintf(stdout, "The square root of %g is %g\n", inputValue, outputValue);

outputValue = mysqrt(inputValue);

fprintf(stdout, "The square root of %g is %g\n", inputValue, outputValue);

四、添加編譯選項

繼續接著前面的實例,我們添加了自己的mysqrt()函數,但是我們并不一定都是使用自己的mysqrt()函數,當系統提供了sqrt()時,我們肯定希望調用系統標準的函數。也就是說,我們需要根據系統情況,動態選擇調用方法。

我們當然可以通過在頭文件中添加編譯選項來實現,不過通過CMakeLists.txt來實現將更加靈活有趣。

首先,我們定義一個編譯宏USE_MYMATH(在頂層CMakeLists.txt):


# should we use our own math functions ?

option(USE_MYMATH

    "Use tutorial provided math implementation" ON)

這將告訴CMake默認打開USE_MYMATH,當然也可以通過ccmake或者編譯選項來重新配置。接下來我們在頂層CMakeLists.txt同時添加依賴庫的說明:


# add the MathFunctions library ?

#

if (USE_MYMATH)

    include_directories("${PROJECT_SOURCE_DIR}/MathFunctions")

    add_subdirectory(MathFunctions)

    set(EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)

#endif(USE_MYMATH)

# add the executable

add_executable(Tutorial tutorial.cxx)

target_link_libraries(Tutorial ${EXTRA_LIBS})

注意:上面添加的USE_MYMATH選項的option命令,必須在configure_file命令之前,否則其默認ON的配置將會無效

接下來,修改tutorial.cxx源代碼,添加條件編譯代碼:


// A simple program that computes the suqare root of a number

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

#include "TutorialConfig.h"

#ifdef USE_MYMATH

#include "mysqrt.h"

#endif

int main(int argc, char *argv[])

{

if (argc < 2)

{

fprintf(stdout, "%s Version %d.%d\n", argv[0],

Tutorial_VERSION_MAJOR, Tutorial_VERSION_MINOR);

fprintf(stdout, "Usage: %s number\n", argv[0]);

return 1;

}

double inputValue = atof(argv[1]);

#ifdef USE_MYMATH

double outputValue = mysqrt(inputValue);

fprintf(stdout, "The square root of %g is %g(use tutorial mysqrt())\n", inputValue, outputValue);

#else

double outputValue = sqrt(inputValue);

fprintf(stdout, "The square root of %g is %g(use system sqrt())\n", inputValue, outputValue);

#endif

return 0;

}

最后,在TutorialConfig.h.in中添加支持,以便在CMake命令行傳入不同的編譯選項時生成不同的TutorialConfig.h文件:


#cmakedefine USE_MYMATH

創建build目錄,并編譯驗證結果如下:

使用mysqrt():


$ mkdir build

$ ls

build  CMakeLists.txt  MathFunctions  TutorialConfig.h.in  tutorial.cxx

$ cd build/

[study@konishi build]$ cmake -DUSE_MYMATH=True ..

-- The C compiler identification is GNU 4.8.5

-- The CXX compiler identification is GNU 4.8.5

-- Check for working C compiler: /usr/bin/cc

-- Check for working C compiler: /usr/bin/cc -- works

-- Detecting C compiler ABI info

-- Detecting C compiler ABI info - done

-- Detecting C compile features

-- Detecting C compile features - done

-- Check for working CXX compiler: /usr/bin/c++

-- Check for working CXX compiler: /usr/bin/c++ -- works

-- Detecting CXX compiler ABI info

-- Detecting CXX compiler ABI info - done

-- Detecting CXX compile features

-- Detecting CXX compile features - done

-- Configuring done

-- Generating done

-- Build files have been written to: /work/study/Studied_Module/Module/cmake/04_basic_options/build

$ make

Scanning dependencies of target MathFunctions

[ 25%] Building CXX object MathFunctions/CMakeFiles/MathFunctions.dir/mysqrt.cxx.o

[ 50%] Linking CXX shared library libMathFunctions.so

[ 50%] Built target MathFunctions

Scanning dependencies of target Tutorial

[ 75%] Building CXX object CMakeFiles/Tutorial.dir/tutorial.cxx.o

[100%] Linking CXX executable Tutorial

[100%] Built target Tutorial

$ ./Tutorial

./Tutorial Version 1.0

Usage: ./Tutorial number

$ ./Tutorial  12

The square root of 12 is 3.4641(use tutorial mysqrt())

使用系統的sqrt():


$ mkdir build

$ ls

build  CMakeLists.txt  MathFunctions  TutorialConfig.h.in  tutorial.cxx

$ cd build/

$ cmake -DUSE_MYMATH=False ..

-- The C compiler identification is GNU 4.8.5

-- The CXX compiler identification is GNU 4.8.5

-- Check for working C compiler: /usr/bin/cc

-- Check for working C compiler: /usr/bin/cc -- works

-- Detecting C compiler ABI info

-- Detecting C compiler ABI info - done

-- Detecting C compile features

-- Detecting C compile features - done

-- Check for working CXX compiler: /usr/bin/c++

-- Check for working CXX compiler: /usr/bin/c++ -- works

-- Detecting CXX compiler ABI info

-- Detecting CXX compiler ABI info - done

-- Detecting CXX compile features

-- Detecting CXX compile features - done

-- Configuring done

-- Generating done

-- Build files have been written to: /work/study/Studied_Module/Module/cmake/04_basic_options/build

$ make

Scanning dependencies of target Tutorial

[ 50%] Building CXX object CMakeFiles/Tutorial.dir/tutorial.cxx.o

[100%] Linking CXX executable Tutorial

[100%] Built target Tutorial

[study@konishi build]$ ./Tutorial

./Tutorial Version 1.0

Usage: ./Tutorial number

$ ./Tutorial 13

The square root of 13 is 3.60555(use system sqrt())

總結:添加配置選項的流程如下:

還有 69% 的精彩內容
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
支付 ¥1.68 繼續閱讀
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,237評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,957評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,248評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,356評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,081評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,485評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,534評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,720評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,263評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,025評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,204評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,787評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,461評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,874評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,105評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,945評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,205評論 2 375

推薦閱讀更多精彩內容