[c++] CMake to build project


CMake 

cmake與autoconf+automake的對比

C++構建系統的選擇

結論:用cmake即可,上古神器過於復雜。

 
CMake是一個跨平台的安裝( 編譯)工具,可以用簡單的語句來描述所有平台的安裝(編譯過程)。他能夠 輸出各種各樣的makefile或者project文件,能測試 編譯器所支持的C++特性,類似UNIX下的automake [上古神器]。
只是 CMake 的組態檔取名為 CMakeLists.txt。Cmake 並不直接建構出最終的軟件,而是產生標准的建構檔(如 Unix 的 Makefile 或 Windows Visual C++ 的 projects/workspaces),然后再依一般的建構方式使用。
這使得熟悉某個 集成開發環境(IDE)的開發者可以用標准的方式建構他的軟件,這種可以使用各平台的原生建構系統的能力是 CMake 和 SCons 等其他類似系統的區別之處。 
 

From: CMake 入門實戰,以及代碼

  1. 編寫 CMake 配置文件 CMakeLists.txt 。
  2. 執行命令 cmake PATH 或者 ccmake PATH 生成 Makefile。其中, PATH 是 CMakeLists.txt 所在的目錄。
  3. 使用 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)

 

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

  1. 導入 InstallRequiredSystemLibraries 模塊,以便之后導入 CPack 模塊;
  2. 設置一些 CPack 相關變量,包括版權信息和版本信息,其中版本信息用了上一節定義的版本號;
  3. 導入 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.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM