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.