1. 程式人生 > 實用技巧 >CMake 入門實戰

CMake 入門實戰

from:https://www.hahack.com/codes/cmake/

從例項入手,講解 CMake 的常見用法。

什麼是 CMake

All problems in computer science can be solved by another level of indirection.

David Wheeler

你或許聽過好幾種 Make 工具,例如GNU Make,QT 的qmake,微軟的MS nmake,BSD Make(pmake),Makepp,等等。這些 Make 工具遵循著不同的規範和標準,所執行的 Makefile 格式也千差萬別。這樣就帶來了一個嚴峻的問題:如果軟體想跨平臺,必須要保證能夠在不同平臺編譯。而如果使用上面的 Make 工具,就得為每一種標準寫一次 Makefile ,這將是一件讓人抓狂的工作。

CMake 就是針對上面問題所設計的工具:它首先允許開發者編寫一種平臺無關的 CMakeList.txt 檔案來定製整個編譯流程,然後再根據目標使用者的平臺進一步生成所需的本地化 Makefile 和工程檔案,如 Unix 的 Makefile 或 Windows 的 Visual Studio 工程。從而做到“Write once, run everywhere”。顯然,CMake 是一個比上述幾種 make 更高階的編譯配置工具。一些使用 CMake 作為專案架構系統的知名開源專案有VTKITKKDEOpenCVOSG[1]

在 linux 平臺下使用 CMake 生成 Makefile 並編譯的流程如下:

  1. 編寫 CMake 配置檔案 CMakeLists.txt 。
  2. 執行命令cmake PATH或者ccmake PATH生成 Makefile(ccmakecmake的區別在於前者提供了一個互動式的介面)。其中,PATH是 CMakeLists.txt 所在的目錄。
  3. 使用make命令進行編譯。

本文將從例項入手,一步步講解 CMake 的常見用法,文中所有的例項程式碼可以在這裡找到。如果你讀完仍覺得意猶未盡,可以繼續學習我在文章末尾提供的其他資源。

入門案例:單個原始檔

本節對應的原始碼所在目錄:Demo1

對於簡單的專案,只需要寫幾行程式碼就可以了。例如,假設現在我們的專案中只有一個原始檔

main.cc,該程式的用途是計算一個數的指數冪。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <stdio.h>
#include <stdlib.h>

/**
* power - Calculate the power of number.
* @param base: Base value.
* @param exponent: Exponent value.
*
* @return base raised to the power exponent.
*/
double power(double base, int exponent)
{
int result = base;
int i;

if (exponent == 0) {
return 1;
}

for(i = 1; i < exponent; ++i){
result = result * base;
}

return result;
}

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]);
double result = power(base, exponent);
printf("%g ^ %d is %g\n", base, exponent, result);
return 0;
}

編寫 CMakeLists.txt

首先編寫 CMakeLists.txt 檔案,並儲存在與main.cc原始檔同個目錄下:

1
2
3
4
5
6
7
8
# CMake 最低版本號要求
cmake_minimum_required (VERSION 2.8)

# 專案資訊
project (Demo1)

# 指定生成目標
add_executable(Demo main.cc)

CMakeLists.txt 的語法比較簡單,由命令、註釋和空格組成,其中命令是不區分大小寫的。符號#後面的內容被認為是註釋。命令由命令名稱、小括號和引數組成,引數之間使用空格進行間隔。

對於上面的 CMakeLists.txt 檔案,依次出現了幾個命令:

  1. cmake_minimum_required:指定執行此配置檔案所需的 CMake 的最低版本;
  2. project:引數值是Demo1,該命令表示專案的名稱是Demo1
  3. add_executable: 將名為main.cc的原始檔編譯成一個名稱為 Demo 的可執行檔案。

編譯專案

之後,在當前目錄執行cmake .,得到 Makefile 後再使用make命令編譯得到 Demo1 可執行檔案。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[ehome@xman Demo1]$ cmake .
-- The C compiler identification is GNU 4.8.2
-- The CXX compiler identification is GNU 4.8.2
-- Check for working C compiler: /usr/sbin/cc
-- Check for working C compiler: /usr/sbin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/sbin/c++
-- Check for working CXX compiler: /usr/sbin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/ehome/Documents/programming/C/power/Demo1
[ehome@xman Demo1]$ make
Scanning dependencies of target Demo
[100%] Building C object CMakeFiles/Demo.dir/main.cc.o
Linking C executable Demo
[100%] Built target Demo
[ehome@xman Demo1]$ ./Demo 5 4
5 ^ 4 is 625
[ehome@xman Demo1]$ ./Demo 7 3
7 ^ 3 is 343
[ehome@xman Demo1]$ ./Demo 2 10
2 ^ 10 is 1024

多個原始檔

同一目錄,多個原始檔

本小節對應的原始碼所在目錄:Demo2

上面的例子只有單個原始檔。現在假如把power函式單獨寫進一個名為MathFunctions.c的原始檔裡,使得這個工程變成如下的形式:

1
2
3
4
5
6
7
./Demo2
|
+--- main.cc
|
+--- MathFunctions.cc
|
+--- MathFunctions.h

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

1
2
3
4
5
6
7
8
# CMake 最低版本號要求
cmake_minimum_required (VERSION 2.8)

# 專案資訊
project (Demo2)

# 指定生成目標
add_executable(Demo main.cc MathFunctions.cc)

唯一的改動只是在add_executable命令中增加了一個MathFunctions.cc原始檔。這樣寫當然沒什麼問題,但是如果原始檔很多,把所有原始檔的名字都加進去將是一件煩人的工作。更省事的方法是使用aux_source_directory命令,該命令會查詢指定目錄下的所有原始檔,然後將結果存進指定變數名。其語法如下:

1
aux_source_directory(<dir> <variable>)

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

1
2
3
4
5
6
7
8
9
10
11
12
# 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 的可執行檔案。

多個目錄,多個原始檔

本小節對應的原始碼所在目錄:Demo3

現在進一步將 MathFunctions.h 和MathFunctions.cc檔案移動到 math 目錄下。

1
2
3
4
5
6
7
8
9
./Demo3
|
+--- main.cc
|
+--- math/
|
+--- MathFunctions.cc
|
+--- MathFunctions.h

對於這種情況,需要分別在專案根目錄 Demo3 和 math 目錄裡各編寫一個 CMakeLists.txt 檔案。為了方便,我們可以先將 math 目錄裡的檔案編譯成靜態庫再由 main 函式呼叫。

根目錄中的 CMakeLists.txt :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 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)

該檔案添加了下面的內容: 第3行,使用命令add_subdirectory指明本專案包含一個子目錄 math,這樣 math 目錄下的 CMakeLists.txt 檔案和原始碼也會被處理 。第6行,使用命令target_link_libraries指明可執行檔案 main 需要連線一個名為 MathFunctions 的連結庫 。

子目錄中的 CMakeLists.txt:

1
2
3
4
5
6
# 查詢當前目錄下的所有原始檔
# 並將名稱儲存到 DIR_LIB_SRCS 變數
aux_source_directory(. DIR_LIB_SRCS)

# 生成連結庫
add_library (MathFunctions ${DIR_LIB_SRCS})

在該檔案中使用命令add_library將 src 目錄中的原始檔編譯為靜態連結庫。

自定義編譯選項

本節對應的原始碼所在目錄:Demo4

CMake 允許為專案增加編譯選項,從而可以根據使用者的環境和需求選擇最合適的編譯方案。

例如,可以將 MathFunctions 庫設為一個可選的庫,如果該選項為ON,就使用該庫定義的數學函式來進行運算。否則就呼叫標準庫中的數學函式庫。

修改 CMakeLists 檔案

我們要做的第一步是在頂層的 CMakeLists.txt 檔案中新增該選項:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# CMake 最低版本號要求
cmake_minimum_required (VERSION 2.8)

# 專案資訊
project (Demo4)

# 加入一個配置標頭檔案,用於處理 CMake 對原始碼的設定
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生成,通過這樣的機制,將可以通過預定義一些引數和變數來控制程式碼的生成。
  2. 第13行的option命令添加了一個USE_MYMATH選項,並且預設值為ON
  3. 第17行根據USE_MYMATH變數的值來決定是否使用我們自己編寫的 MathFunctions 庫。

修改main.cc檔案

之後修改main.cc檔案,讓其根據USE_MYMATH的預定義值來決定是否呼叫標準庫還是 MathFunctions 庫:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdio.h>
#include <stdlib.h>
#include "config.h"

#ifdef USE_MYMATH
#include "math/MathFunctions.h"
#else
#include <math.h>
#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 檔案,這個檔案預定義了USE_MYMATH的值。但我們並不直接編寫這個檔案,為了方便從 CMakeLists.txt 中匯入配置,我們編寫一個config.h.in檔案,內容如下:

1
#cmakedefine USE_MYMATH

這樣 CMake 會自動根據 CMakeLists 配置檔案中的設定自動生成 config.h 檔案。

編譯專案

現在編譯一下這個專案,為了便於互動式的選擇該變數的值,可以使用ccmake命令(也可以使用cmake -i命令,該命令會提供一個會話式的互動式配置介面):

CMake的互動式配置介面

從中可以找到剛剛定義的USE_MYMATH選項,按鍵盤的方向鍵可以在不同的選項視窗間跳轉,按下enter鍵可以修改該選項。修改完成後可以按下c選項完成配置,之後再按g鍵確認生成 Makefile 。ccmake 的其他操作可以參考視窗下方給出的指令提示。

我們可以試試分別將USE_MYMATH設為ONOFF得到的結果:

USE_MYMATH 為 ON

執行結果:

1
2
3
4
5
[ehome@xman Demo4]$ ./Demo
Now we use our own MathFunctions library.
7 ^ 3 = 343.000000
10 ^ 5 = 100000.000000
2 ^ 10 = 1024.000000

此時 config.h 的內容為:

1
#define USE_MYMATH
USE_MYMATH 為 OFF

執行結果:

1
2
3
4
5
[ehome@xman Demo4]$ ./Demo
Now we use the standard library.
7 ^ 3 = 343.000000
10 ^ 5 = 100000.000000
2 ^ 10 = 1024.000000

此時 config.h 的內容為:

1
/* #undef USE_MYMATH */

安裝和測試

本節對應的原始碼所在目錄:Demo5

CMake 也可以指定安裝規則,以及新增測試。這兩個功能分別可以通過在產生 Makefile 後使用make installmake test來執行。在以前的 GNU Makefile 裡,你可能需要為此編寫installtest兩個偽目標和相應的規則,但在 CMake 裡,這樣的工作同樣只需要簡單的呼叫幾條命令。

定製安裝規則

首先先在 math/CMakeLists.txt 檔案裡新增下面兩行:

1
2
3
# 指定 MathFunctions 庫的安裝路徑
install (TARGETS MathFunctions DESTINATION bin)
install (FILES MathFunctions.h DESTINATION include)

指明 MathFunctions 庫的安裝路徑。之後同樣修改根目錄的 CMakeLists 檔案,在末尾新增下面幾行:

1
2
3
4
# 指定安裝路徑
install (TARGETS Demo DESTINATION bin)
install (FILES "${PROJECT_BINARY_DIR}/config.h"
DESTINATION include)

通過上面的定製,生成的 Demo 檔案和 MathFunctions 函式庫 libMathFunctions.o 檔案將會被複制到/usr/local/bin中,而 MathFunctions.h 和生成的 config.h 檔案則會被複制到/usr/local/include中。我們可以驗證一下(順帶一提的是,這裡的/usr/local/是預設安裝到的根目錄,可以通過修改CMAKE_INSTALL_PREFIX變數的值來指定這些檔案應該拷貝到哪個根目錄):

1
2
3
4
5
6
7
8
9
10
11
12
13
[ehome@xman Demo5]$ sudo make install
[ 50%] Built target MathFunctions
[100%] Built target Demo
Install the project...
-- Install configuration: ""
-- Installing: /usr/local/bin/Demo
-- Installing: /usr/local/include/config.h
-- Installing: /usr/local/bin/libMathFunctions.a
-- Up-to-date: /usr/local/include/MathFunctions.h
[ehome@xman Demo5]$ ls /usr/local/bin
Demo libMathFunctions.a
[ehome@xman Demo5]$ ls /usr/local/include
config.h MathFunctions.h

為工程新增測試

新增測試同樣很簡單。CMake 提供了一個稱為 CTest 的測試工具。我們要做的只是在專案根目錄的 CMakeLists 檔案中呼叫一系列的add_test命令。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 啟用測試
enable_testing()

# 測試程式是否成功執行
add_test (test_run Demo 5 2)

# 測試幫助資訊是否可以正常提示
add_test (test_usage Demo)
set_tests_properties (test_usage
PROPERTIES PASS_REGULAR_EXPRESSION "Usage: .* base exponent")

# 測試 5 的平方
add_test (test_5_2 Demo 5 2)

set_tests_properties (test_5_2
PROPERTIES PASS_REGULAR_EXPRESSION "is 25")

# 測試 10 的 5 次方
add_test (test_10_5 Demo 10 5)

set_tests_properties (test_10_5
PROPERTIES PASS_REGULAR_EXPRESSION "is 100000")

# 測試 2 的 10 次方
add_test (test_2_10 Demo 2 10)

set_tests_properties (test_2_10
PROPERTIES PASS_REGULAR_EXPRESSION "is 1024")

上面的程式碼包含了四個測試。第一個測試test_run用來測試程式是否成功執行並返回 0 值。剩下的三個測試分別用來測試 5 的 平方、10 的 5 次方、2 的 10 次方是否都能得到正確的結果。其中PASS_REGULAR_EXPRESSION用來測試輸出是否包含後面跟著的字串。

讓我們看看測試的結果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[ehome@xman Demo5]$ make test
Running tests...
Test project /home/ehome/Documents/programming/C/power/Demo5
Start 1: test_run
1/4 Test #1: test_run ......................... Passed 0.00 sec
Start 2: test_5_2
2/4 Test #2: test_5_2 ......................... Passed 0.00 sec
Start 3: test_10_5
3/4 Test #3: test_10_5 ........................ Passed 0.00 sec
Start 4: test_2_10
4/4 Test #4: test_2_10 ........................ Passed 0.00 sec

100% tests passed, 0 tests failed out of 4

Total Test time (real) = 0.01 sec

如果要測試更多的輸入資料,像上面那樣一個個寫測試用例未免太繁瑣。這時可以通過編寫巨集來實現:

1
2
3
4
5
6
7
8
9
10
11
# 定義一個巨集,用來簡化測試工作
macro (do_test arg1 arg2 result)
add_test (test_${arg1}_${arg2} Demo ${arg1} ${arg2})
set_tests_properties (test_${arg1}_${arg2}
PROPERTIES PASS_REGULAR_EXPRESSION ${result})
endmacro (do_test)

# 使用該巨集進行一系列的資料測試
do_test (5 2 "is 25")
do_test (10 5 "is 100000")
do_test (2 10 "is 1024")

關於 CTest 的更詳細的用法可以通過man 1 ctest參考 CTest 的文件。

支援 gdb

讓 CMake 支援 gdb 的設定也很容易,只需要指定Debug模式下開啟-g選項:

1
2
3
set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")

之後可以直接對生成的程式使用 gdb 來除錯。

新增環境檢查

本節對應的原始碼所在目錄:Demo6

有時候可能要對系統環境做點檢查,例如要使用一個平臺相關的特性的時候。在這個例子中,我們檢查系統是否自帶 pow 函式。如果帶有 pow 函式,就使用它;否則使用我們定義的 power 函式。

新增 CheckFunctionExists 巨集

首先在頂層 CMakeLists 檔案中新增 CheckFunctionExists.cmake 巨集,並呼叫check_function_exists命令測試連結器是否能夠在連結階段找到pow函式。

1
2
3
# 檢查系統是否支援 pow 函式
include (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake)
check_function_exists (pow HAVE_POW)

將上面這段程式碼放在configure_file命令前。

預定義相關巨集變數

接下來修改config.h.in檔案,預定義相關的巨集變數。

1
2
// does the platform provide pow function?
#cmakedefine HAVE_POW

在程式碼中使用巨集和函式

最後一步是修改main.cc,在程式碼中使用巨集和函式:

1
2
3
4
5
6
7
#ifdef HAVE_POW
printf("Now we use the standard library. \n");
double result = pow(base, exponent);
#else
printf("Now we use our own Math library. \n");
double result = power(base, exponent);
#endif

新增版本號

本節對應的原始碼所在目錄:Demo7

給專案新增和維護版本號是一個好習慣,這樣有利於使用者瞭解每個版本的維護情況,並及時瞭解當前所用的版本是否過時,或是否可能出現不相容的情況。

首先修改頂層 CMakeLists 檔案,在project命令之後加入如下兩行:

1
2
set (Demo_VERSION_MAJOR 1)
set (Demo_VERSION_MINOR 0)

分別指定當前的專案的主版本號和副版本號。

之後,為了在程式碼中獲取版本資訊,我們可以修改config.h.in檔案,新增兩個預定義變數:

1
2
3
// the configured options and settings for Tutorial
#define Demo_VERSION_MAJOR @Demo_VERSION_MAJOR@
#define Demo_VERSION_MINOR @Demo_VERSION_MINOR@

這樣就可以直接在程式碼中列印版本資訊了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "config.h"
#include "math/MathFunctions.h"

int main(int argc, char *argv[])
{
if (argc < 3){
// print version info
printf("%s Version %d.%d\n",
argv[0],
Demo_VERSION_MAJOR,
Demo_VERSION_MINOR);
printf("Usage: %s base exponent \n", argv[0]);
return 1;
}
double base = atof(argv[1]);
int exponent = atoi(argv[2]);

#if defined (HAVE_POW)
printf("Now we use the standard library. \n");
double result = pow(base, exponent);
#else
printf("Now we use our own Math library. \n");
double result = power(base, exponent);
#endif

printf("%g ^ %d is %g\n", base, exponent, result);
return 0;
}

生成安裝包

本節對應的原始碼所在目錄:Demo8

本節將學習如何配置生成各種平臺上的安裝包,包括二進位制安裝包和原始碼安裝包。為了完成這個任務,我們需要用到 CPack ,它同樣也是由 CMake 提供的一個工具,專門用於打包。

首先在頂層的 CMakeLists.txt 檔案尾部新增下面幾行:

1
2
3
4
5
6
7
# 構建一個 CPack 安裝包
include (InstallRequiredSystemLibraries)
set (CPACK_RESOURCE_FILE_LICENSE
"${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
set (CPACK_PACKAGE_VERSION_MAJOR "${Demo_VERSION_MAJOR}")
set (CPACK_PACKAGE_VERSION_MINOR "${Demo_VERSION_MINOR}")
include (CPack)

上面的程式碼做了以下幾個工作:

  1. 匯入 InstallRequiredSystemLibraries 模組,以便之後匯入 CPack 模組;
  2. 設定一些 CPack 相關變數,包括版權資訊和版本資訊,其中版本資訊用了上一節定義的版本號;
  3. 匯入 CPack 模組。

接下來的工作是像往常一樣構建工程,並執行cpack命令。

  • 生成二進位制安裝包:
1
cpack -C CPackConfig.cmake
  • 生成原始碼安裝包
1
cpack -C CPackSourceConfig.cmake

我們可以試一下。在生成專案後,執行cpack -C CPackConfig.cmake命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[ehome@xman Demo8]$ cpack -C CPackSourceConfig.cmake
CPack: Create package using STGZ
CPack: Install projects
CPack: - Run preinstall target for: Demo8
CPack: - Install project: Demo8
CPack: Create package
CPack: - package: /home/ehome/Documents/programming/C/power/Demo8/Demo8-1.0.1-Linux.sh generated.
CPack: Create package using TGZ
CPack: Install projects
CPack: - Run preinstall target for: Demo8
CPack: - Install project: Demo8
CPack: Create package
CPack: - package: /home/ehome/Documents/programming/C/power/Demo8/Demo8-1.0.1-Linux.tar.gz generated.
CPack: Create package using TZ
CPack: Install projects
CPack: - Run preinstall target for: Demo8
CPack: - Install project: Demo8
CPack: Create package
CPack: - package: /home/ehome/Documents/programming/C/power/Demo8/Demo8-1.0.1-Linux.tar.Z generated.

此時會在該目錄下建立 3 個不同格式的二進位制包檔案:

1
2
[ehome@xman Demo8]$ ls Demo8-*
Demo8-1.0.1-Linux.sh Demo8-1.0.1-Linux.tar.gz Demo8-1.0.1-Linux.tar.Z

這 3 個二進位制包檔案所包含的內容是完全相同的。我們可以執行其中一個。此時會出現一個由 CPack 自動生成的互動式安裝介面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
[ehome@xman Demo8]$ sh Demo8-1.0.1-Linux.sh 
Demo8 Installer Version: 1.0.1, Copyright (c) Humanity
This is a self-extracting archive.
The archive will be extracted to: /home/ehome/Documents/programming/C/power/Demo8

If you want to stop extracting, please press <ctrl-C>.
The MIT License (MIT)

Copyright (c) 2013 Joseph Pan(http://hahack.com)

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


Do you accept the license? [yN]:
y
By default the Demo8 will be installed in:
"/home/ehome/Documents/programming/C/power/Demo8/Demo8-1.0.1-Linux"
Do you want to include the subdirectory Demo8-1.0.1-Linux?
Saying no will install in: "/home/ehome/Documents/programming/C/power/Demo8" [Yn]:
y

Using target directory: /home/ehome/Documents/programming/C/power/Demo8/Demo8-1.0.1-Linux
Extracting, please wait...

Unpacking finished successfully

完成後提示安裝到了 Demo8-1.0.1-Linux 子目錄中,我們可以進去執行該程式:

1
2
3
[ehome@xman Demo8]$ ./Demo8-1.0.1-Linux/bin/Demo 5 2
Now we use our own Math library.
5 ^ 2 is 25

關於 CPack 的更詳細的用法可以通過man 1 cpack參考 CPack 的文件。

將其他平臺的專案遷移到 CMake

CMake 可以很輕鬆地構建出在適合各個平臺執行的工程環境。而如果當前的工程環境不是 CMake ,而是基於某個特定的平臺,是否可以遷移到 CMake 呢?答案是可能的。下面針對幾個常用的平臺,列出了它們對應的遷移方案。

autotools

qmake

Visual Studio

  • vcproj2cmake.rb可以根據 Visual Studio 的工程檔案(字尾名是.vcproj.vcxproj)生成 CMakeLists.txt 檔案。
  • vcproj2cmake.ps1vcproj2cmake 的 PowerShell 版本。
  • folders4cmake根據 Visual Studio 專案檔案生成相應的 “source_group” 資訊,這些資訊可以很方便的在 CMake 指令碼中使用。支援 Visual Studio 9/10 工程檔案。

CMakeLists.txt 自動推導

  • gencmake根據現有檔案推導 CMakeLists.txt 檔案。
  • CMakeListGenerator應用一套檔案和目錄分析創建出完整的 CMakeLists.txt 檔案。僅支援 Win32 平臺。

相關連結

  1. 官方主頁
  2. 官方文件
  3. 官方教程
  4. Wiki
  5. FAQ
  6. bug tracker
  7. 郵件列表:
  8. 其他推薦文章

類似工具

  • SCons:Eric S. Raymond、Timothee Besset、Zed A. Shaw 等大神力薦的專案架構工具。和 CMake 的最大區別是使用 Python 作為執行指令碼。

  1. 這個頁面詳細羅列了使用 CMake 的知名專案↩︎