[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