1.最简实例
使用cmake的最简实例是由一个源程序文件生成一个可执行文件。例如由下述C++源程序文件生成可执行文件tutorial。
main.cpp
#include<iostream> using namespace std; int main(){ cout<<"hello world"<<endl; }
需要编辑CMakeLists.txt文件如下:
cmake_minimum_required(VERSION 2.6) project (tutorial) add_executable(tutorial main.cpp)
其中cmake_minimum_required指定了cmake最低版本限制,project指定了项目名称,add_executable指定了生成的可执行文件名称为tutorial,源程序文件为main.cpp。
需要生成项目可以cd到此目录,然后依次执行下述命令:
cmake . make
可见,cmake帮助我们快速生成了项目的makefile文件,从而可以通过make命令直接生成项目的可执行文件。此时,在该路径下就生成了可执行文件tutorial,执行该程序,有:
使用cmake就是如此简单快捷!
2.设置版本号和配置头文件
如果在cmake中指定版本号这样更加灵活,我们可以这么操作:通过CMakeLists.txt文件指定版本号,然后通过CMake链接到CMakeLists.txt 文件生成含有该版本号的头文件,之后就可以引用该头文件中的版本号了。
例如:我们在CMakeLists.txt文件中指定了下述两个版本号:
cmake_minimum_required (VERSION 2.6)
project (Tutorial)
# The version number.
set (Tutorial_VERSION_MAJOR 1)
set (Tutorial_VERSION_MINOR 0)
# configure a header file to pass some of the CMake settings
# to the source code
configure_file (
"${PROJECT_SOURCE_DIR}/config.h.in"
"${PROJECT_BINARY_DIR}/config.h"
)
# add the binary tree to the search path for include files
# so that we will find config.h
include_directories("${PROJECT_BINARY_DIR}")
# add the executable
add_executable(Tutorial main.cpp)
config.h.in 中引用了CMakeLists.txt中定义的两个版本号,如下所示:
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
main.cpp文件直接引用config.h头文件中定义的版本号,如下所示:
#include "config.h" #include<iostream> using namespace std; int main(){ cout<<"Tutorial_VERSION_MAJOR: "<<Tutorial_VERSION_MAJOR<<endl; cout<<"Tutorial_VERSION_MINOR: "<<Tutorial_VERSION_MINOR<<endl; cout<<"hello world"<<endl; return 0; }
此时,执行命令cmake不仅生成了makefile文件,还链接生成了config.h文件,如下所示:
#define Tutorial_VERSION_MAJOR 1 #define Tutorial_VERSION_MINOR 0
执行命令make,然后顺利生成了可执行文件Tutorial,执行该文件有:
完美!
3.在项目中添加可选库
在大型项目中,我们需要根据实际情况决定到底引用哪个库中的函数实现。我们可以借助CMake便捷的实现库的可选性。
如下,设置CMakeLists.txt文件如下所示:
# CMake 最低版本号要求 cmake_minimum_required (VERSION 2.8) # 项目信息 project (Tutorial) # 是否使用自己的 MathFunctions 库 这是可选的,ON使用,OFF不使用 option (USE_MYMATH "Use provided math implementation" ON) # 加入一个配置头文件,用于处理 CMake 对源码的设置,与option相对应 configure_file ( "${PROJECT_SOURCE_DIR}/config.h.in" "${PROJECT_BINARY_DIR}/config.h" ) # 是否加入 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 (Tutorial ${DIR_SRCS}) target_link_libraries (Tutorial ${EXTRA_LIBS})
相对应的,为了使得CMake能够自动的根据option自动生成相对应的头文件config.h,我们编辑config.h.in文件如下:
#cmakedefine USE_MYMATH
当我们设置option为ON的时候,CMake链接生成的config.h头文件如下所示:
#define USE_MYMATH
所以,我们可以在主程序源文件中根据USE_MYMATH是否定义来决策是否使用自定义库。主源程序文件main.cpp如下所示:
#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[]) { double base = 2.0; int exponent = 4; #ifdef USE_MYMATH printf("Now we use our own Math library. "); double result = power(base, exponent); #else printf("Now we use the standard library. "); double result = pow(base, exponent); #endif printf("%g ^ %d is %g ", base, exponent, result); return 0; }
我们自行定义的库在子文件夹math中,其中主要有两个文件,分别是头文件和源程序文件,如下所示:
MathFunctions.h
#ifndef POWER_H #define POWER_H extern double power(double base, int exponent); #endif
MathFunctions.cpp
/** * 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; for(i = 1; i < exponent; ++i){ result = result * base; } return result; }
为了打包生成库文件,也需要在库文件夹中定义CMakeLists.txt文件,如下所示:
# 查找当前目录下的所有源文件 # 并将名称保存到 DIR_LIB_SRCS 变量 aux_source_directory(. DIR_LIB_SRCS) # 指定生成 MathFunctions 链接库 add_library (MathFunctions ${DIR_LIB_SRCS})
最后,测试一下我们的项目,执行命令:
cmake . make
项目顺利编译通过,执行生成的可执行文件Tutorial,有:
pass!