CMake
結論:用cmake即可,上古神器過於復雜。
CMake是一個跨平台的安裝(
編譯)工具,可以用簡單的語句來描述所有平台的安裝(編譯過程)。他能夠
輸出各種各樣的makefile或者project文件,能測試
編譯器所支持的C++特性,類似UNIX下的automake [上古神器]。
只是
CMake 的組態檔取名為 CMakeLists.txt。Cmake 並不直接建構出最終的軟件,而是產生標准的建構檔(如 Unix 的 Makefile 或 Windows Visual C++ 的 projects/workspaces),然后再依一般的建構方式使用。
這使得熟悉某個
集成開發環境(IDE)的開發者可以用標准的方式建構他的軟件,這種可以使用各平台的原生建構系統的能力是 CMake 和 SCons 等其他類似系統的區別之處。
From: CMake 入門實戰,以及代碼
- 編寫 CMake 配置文件 CMakeLists.txt 。
- 執行命令
cmake PATH
或者ccmake PATH
生成 Makefile。其中,PATH
是 CMakeLists.txt 所在的目錄。 - 使用
make
命令進行編譯。
單個目錄
最簡單的例子,只包含兩個文件:main.cc, MathFunctions.cc
cmake_minimum_required (VERSION 2.8) project (Demo2) add_executable(Demo main.cc MathFunctions.cc)
文件多了,就把后兩行改為:
# 查找當前目錄下的所有源文件,並將名稱保存到 DIR_SRCS 變量
aux_source_directory(. DIR_SRCS)
# 指定生成目標
add_executable(Demo ${DIR_SRCS})
在當前目錄執行 cmake .
,得到 Makefile 后再使用 make
命令編譯得到 Demo1 可執行文件。
多個目錄
在子目錄下創建一個單獨的cmake configure,子目錄編譯除了獨立的.o,在上層的需要去鏈接。
# 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)
子目錄下的配置文件:
# 查找當前目錄下的所有源文件
# 並將名稱保存到 DIR_LIB_SRCS 變量
aux_source_directory(. DIR_LIB_SRCS)
# 生成鏈接庫
add_library (MathFunctions ${DIR_LIB_SRCS})
生成了靜態鏈接庫。
安裝和測試
math/CMakeLists.txt 文件里添加下面兩行:
# 查找當前目錄下的所有源文件 # 並將名稱保存到 DIR_LIB_SRCS 變量 aux_source_directory(. DIR_LIB_SRCS) # 指定生成 MathFunctions 鏈接庫 add_library (MathFunctions ${DIR_LIB_SRCS}) # 指定 MathFunctions 庫的安裝路徑 install (TARGETS MathFunctions DESTINATION lib) install (FILES MathFunctions.h DESTINATION include)
主目錄下的CMakeLists.txt 文件:
# CMake 最低版本號要求 cmake_minimum_required (VERSION 2.8) # 項目信息 project (Demo5) set (CMAKE_INCLUDE_CURRENT_DIR ON) # 加入一個配置頭文件,用於處理 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}) # 指定安裝路徑 install (TARGETS Demo DESTINATION bin) install (FILES "${PROJECT_BINARY_DIR}/config.h" DESTINATION include)
自定義配置
用自己的,還是系統本身的?
關於config.h.in,非常類似對宏的控制。
#cmakedefine USE_MYMATH
代碼中添加了宏。
#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 文件,預定義相關的宏變量。
// does the platform provide pow function? #cmakedefine HAVE_POW
檢查系統是否支持 pow 函數
include (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake) check_function_exists (pow HAVE_POW)
在代碼中使用宏和函數
#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
添加版本號
代碼文件
#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; }
cmake文件
set (Demo_VERSION_MAJOR 1) set (Demo_VERSION_MINOR 0)
config.h.in將兩者聯系起來
// the configured options and settings for Tutorial #define Demo_VERSION_MAJOR @Demo_VERSION_MAJOR@ #define Demo_VERSION_MINOR @Demo_VERSION_MINOR@
生成安裝包
CPack 由 CMake 提供的一個工具,專門用於打包。
在頂層的 CMakeLists.txt 文件尾部添加下面幾行:
# 構建一個 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)
上面的代碼做了以下幾個工作:
- 導入 InstallRequiredSystemLibraries 模塊,以便之后導入 CPack 模塊;
- 設置一些 CPack 相關變量,包括版權信息和版本信息,其中版本信息用了上一節定義的版本號;
- 導入 CPack 模塊。
接下來的工作是像往常一樣構建工程,並執行 cpack
命令
# 生成二進制安裝包: cpack -C CPackConfig.cmake # 生成源碼安裝包 cpack -C CPackSourceConfig.cmake
在該目錄下創建 3 個不同格式的二進制包文件:
Demo8-1.0.1-Linux.sh Demo8-1.0.1-Linux.tar.gz Demo8-1.0.1-Linux.tar.Z
End.