cmake用法

示例源码 在 linux 平台下使用 CMake 生成 Makefile 并编译的流程如下:

    1. 编写 CMake 配置文件 CMakeLists.txt
    1. 执行命令 cmake PATH 或者 ccmake PATH 生成 Makefile

ccmake 和 cmake 的区别在于前者提供了一个交互式的界面。 。其中, PATH 是 CMakeLists.txt 所在的目录。

  • 使用 make 命令进行编译。
入门案例一(单文件)

先看下目录和源码

1.png

代码的逻辑非常简单就是求10的立方。 重点时候在CMakeLists.txt

# '#'行后面的都是注释

# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)

# 项目信息
project (Calc)

# 指定生成目标  main为编译生成文件, main.cpp为源文件
add_executable(main main.cpp)
  • # 为注释标识
  • cmake_minimum_required是最低版本要求,这个是必须要的
  • project 项目信息
  • add_executable 将main.cpp编译成main

如果我们将cmake_minimum_required (VERSION 2.8)版本改成2.9.2。我的机器上cmake版本是cmake version 2.8.12.2。执行cmake .后报错:

2.png

正常执行完cmake后,会在根目录下生成Makefile。然后我们就可以用make来编译了。

入门案例二(同目录多文件)

这里我们在案例一的基础上新增Math.hMath.cpp

#include "Math.h"
long pow(int base,int power){
        long res=1;
        for(int i=0; i<power; i++) {
                res*=base;
        }
        return res;
}

然后修改main.cpp的include文件,将使用系统的math.h替换成我们自己的Math.h

#include <iostream>
#include "Math.h"
using namespace std;
int main(){
        int x=10;
        int y=3;
        int res=pow(10,3);
        cout<<res<<endl;
        return 0;
}

修改CMakeLists.txt 方法一

add_executable(main main.cpp Math.cpp)

add_executable参数中加入Math.cpp 方法二 如果源文件很多,这样写就很蛋疼了。我们可以使用aux_source_directory命令

aux_source_directory(<dir> <variable>)

该命令会查找指定目录下的所有源文件,然后将结果存进指定变量名。

# '#'行后面的都是注释

# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)

# 项目信息
project (Calc)

# 指定生成目标  main为编译生成文件, main.cpp为源文件
# 方法一:一个个添加
# add_executable(main main.cpp Math.cpp)

# 方法二:查找目录下文件到变量中,然后引用变量
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)

# 指定生成目标
add_executable(Demo ${DIR_SRCS})
入门案例三(多目录、多文件)

对于这种情况,需要分别在项目根目录 Simple和 math 目录里各编写一个 CMakeLists.txt 文件。为了方便,我们可以先将 math 目录里的文件编译成静态库再由 main 函数调用。

3.png

math瞎的CMakeLists.txt内容为:

# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_LIB_SRCS 变量
aux_source_directory(. DIR_LIB_SRCS)

# 生成链接库
add_library (MathFunctions ${DIR_LIB_SRCS})

当然,main.cpp引入的头文件也要修改,math.h的位置已经变了。

#include "math/Math.h"
入门案例四(自定义编译选项)
# '#'行后面的都是注释

# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)

# 项目信息
project (Calc)

# 加入一个配置头文件,用于处理 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(main main.cpp)

# 添加链接库
target_link_libraries(main ${EXTRA_LIBS})

添加config.h.in

#cmakedefine USE_MYMATH

修改main.cpp

#include <iostream>
#include "config.h"

#ifdef USE_MYMATH
  #include "math/Math.h"
#else
  #include <math.h>
#endif

using namespace std;
int main(){
        int x=10;
        int y=3;
        int res=pow(10,3);
        cout<<res<<endl;
        return 0;
}

如果定义了USE_MYMATH就使用自己的Math.h否则include系统的math.h 这里我们可以使用ccmake命令,可以选择ON或OFF。然后按c进行配置。然后再按g进行生成

4.png

5.png

入门案例五(安装和测试)
添加版本号

首先修改顶层 CMakeLists 文件,在 project 命令之后加入如下两行:

# 设置版本号
set (Demo_VERSION_MAJOR 1)
set (Demo_VERSION_MINOR 0)

为了在代码中获取版本信息,我们可以修改 config.h.in 文件,添加两个预定义变量:

#define Demo_VERSION_MAJOR @Demo_VERSION_MAJOR@
#define Demo_VERSION_MINOR @Demo_VERSION_MINOR@

程序中就可以获取相关信息

cout<<"Version "<<Demo_VERSION_MAJOR<<"."<<Demo_VERSION_MINOR<<endl;
生成安装包

首先在顶层的 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 -C CPackConfig.cmake

6.png

  • 生成源码安装包
cpack -C CPackSourceConfig.cmake

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏运维技术迷

Linux强制用户首次登陆修改密码

Linux强制用户首次登陆修改密码这个应该是RHCE认证中用户管理部分,属于基础中的基础。可是我忘记了,所以就有了下面的记录。 [root@jd /]# use...

4259
来自专栏Java架构师学习

Spring面试底层原理的那些问题,你是不是真的懂Spring?

4234
来自专栏everhad

笔记:Binder通信机制

TODO: 待修正 Binder简介 Binder是android系统中实现的一种高效的IPC机制,平常接触到的各种XxxManager,以及绑定Service...

2598
来自专栏精讲JAVA

关于Spring底层原理面试的那些问题,你是不是真的懂Spring?

Spring 框架是一个为 Java 应用程序的开发提供了综合、广泛的基础性支持的 Java 平台。Spring帮助开发者解决了开发中基础性的问题,使得开发人员...

1.8K3
来自专栏Java学习之路

06 Spring框架 依赖注入(三)多配置文件

在Spring前几节的学习中我们都使用了一个配置文件,就像struts2中可以包含其他的配置文件,我们能不能使用多个配置文件呢(在工程比庞大,配置比较多的时候)...

30710
来自专栏ImportSource

Spring的三种Circuit Breaker

今天我们分享的内容是在spring下的三种circuit breaker的做法。接下来我们分别演示spring cloud netflix hystrix、sp...

7138
来自专栏小筱月

SSM整合开发

controller:作为请求转发,调用service接口处理逻辑,页面所有路径的访问方法:控制层的命名空间+@RequestMapping的value ser...

3731
来自专栏Android 研究

Android跨进程通信IPC之7——Binder相关结构体简介

binder_node 代表的是Binder实体对象,每一个service组件或者ServiceManager在Binder驱动程序中的描述,Binder驱动通...

1062
来自专栏潇涧技术专栏

Art of Android Development Reading Notes 2

(1)任何一个操作系统都需要有相应的IPC机制,Linux上可以通过命名通道、共享内存、信号量等来进行进程间通信。 (2)Android系统不仅可以使用Bin...

892
来自专栏专注研发

IDEA环境下SSM整合------注解开发

3.别的好像没啥介绍了,基本步骤就这些,数据流程在上面,注解介绍在下面。 基本注解介绍 @Controller   负责注册一个控制器,Singlet...

3092

扫码关注云+社区

领取腾讯云代金券