CMake 简易教程

对于大部分小白来说,不太关心项目的构造过程,拿到项目之后也不太清楚怎么构建。导致在Github上Fork代码之后,或者下载某个linux版的软件,面对着一大堆源码不知道怎么使用。本文简单的介绍一下C++ 常见的CMake编译方法。

Cmake 是一个跨平台的、开源的构建工具。cmake 是 makefile 的上层工具,它们的目的正是为了产生可移植的makefile,并简化自己动手写makefile时的巨大工作量

Cmake的使用

拿到一个由Cmake构建的工程源代码之后,我们首先要做的是当然是安装CMake
Ubuntu 使用命令进行安装

sudo apt install cmake

之后进入项目的根目录创建一个名为build的文件夹并进入该目录下,执行cmake…

$ mkdir build
$ cd build/
$ cmake ..

最后在build目录内,执行make命令就可以进行编译了

1 创建build目录是为了不让编译产生的中间文件和执行文件污染我们的工程,这是普遍的做法。
2 cmake命令会根据 CMakeLists.txt 文件进行配置生成
3 最后使用make命令进行构建项目

cmake执行过后,项目中就会出现对应的编译产物,它可能是
动态链接库,静态链接库,可执行文件
三种中的一种或多种,除了可执行文件之外,其余两种还需要使用额外的代码才能让他运行起来,但对于项目来说,确实是最终产物了。

CMakeLists.txt 的编写

从上面的过程可以看出,cmake 的重点在配置 CMakeLists.txt 文件。这里直接使用一个开源项目作为例子进行学习
关于CMakeLists.txt的常用指令可以查看
其实我们只要知道添加源文件,添加宏定义等几个常用命令也就足够了。

https://aiden-dong.github.io/2019/07/20/CMake%E6%95%99%E7%A8%8B%E4%B9%8BCMake%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E5%BA%94%E7%94%A8/#cmake-%E5%B8%B8%E7%94%A8%E6%8C%87%E4%BB%A4

下面是一个实际的CMake例子 : LevelDB项目

cmake_minimum_required(VERSION 3.9)       --版本要求
project(leveldb VERSION 1.22.0 LANGUAGES C CXX)  --工程名,版本信息等

// 设置选项
# This project requires C++11.
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

#WIN32 是系统的变量,可以直接使用, 这里类似与宏定义
if (WIN32)
  set(LEVELDB_PLATFORM_NAME LEVELDB_PLATFORM_WINDOWS)
  add_definitions(-D_UNICODE -DUNICODE)
else (WIN32)
  set(LEVELDB_PLATFORM_NAME LEVELDB_PLATFORM_POSIX)
endif (WIN32)


//自定义编译选项, 可以在cmakelist文件接下来的部分使用
// 与set 的区别, set有更丰富的 使用方法, 而option只能定义 ON 或者 OFF
option(LEVELDB_BUILD_TESTS "Build LevelDB's unit tests" ON)
option(LEVELDB_BUILD_BENCHMARKS "Build LevelDB's benchmarks" ON)
option(LEVELDB_INSTALL "Install LevelDB's header and library" ON)

// 设置 C编译器的选项,设置 C++编译器选项  为 CMAKE_CXX_FLAGS
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wstrict-prototypes")

// 如果使用 add_compile_options 则对所有编译器生效
  add_compile_options(-fvisibility=hidden)
  
// 添加 宏定义, 如果你的代码中定义了#ifdef ENABLE_DEBUG #endif,这个代码块就会生效。
 ADD_DEFINITIONS(-DENABLE_DEBUG -DABC)

// add_library 命令用于生成动态或静态链接库, 即添加一个目标, 后续会根据目标名进行区分
//语法 : ADD_LIBRARY(<name> [STATIC | SHARED | MODULE] [source1] [source2 ...])
add_library(leveldb SHARED "")  // 添加动态链接目标
#add_library(leveldb STATIC "")  // 添加静态链接目标
#add_executable(leveldb "") //  添加可执行文件
// 添加源码文件, 生成 add_library 链接库 所需的文件列表
// PROJECT_SOURCE_DIR是根目录
target_sources(leveldb
  PRIVATE
    "${PROJECT_BINARY_DIR}/${LEVELDB_PORT_CONFIG_DIR}/port_config.h"
    "${PROJECT_SOURCE_DIR}/db/builder.cc"
    "${PROJECT_SOURCE_DIR}/db/builder.h"
    "${PROJECT_SOURCE_DIR}/db/c.cc"
    "${PROJECT_SOURCE_DIR}/db/db_impl.cc"
    "${PROJECT_SOURCE_DIR}/db/db_impl.h"
    "${PROJECT_SOURCE_DIR}/db/db_iter.cc"
    "${PROJECT_SOURCE_DIR}/db/db_iter.h"
    "${PROJECT_SOURCE_DIR}/db/dbformat.cc"
.....
)

//target_sources 可以不连续, 在后面也可以再次定义,会自动视为append, 例如下面需要根据平台引入不同的文件
if (WIN32)
  target_sources(leveldb
    PRIVATE
      "${PROJECT_SOURCE_DIR}/util/env_windows.cc"
      "${PROJECT_SOURCE_DIR}/util/windows_logger.h"
  )
else (WIN32)
  target_sources(leveldb
    PRIVATE
      "${PROJECT_SOURCE_DIR}/util/env_posix.cc"
      "${PROJECT_SOURCE_DIR}/util/posix_logger.h"
  )
endif (WIN32)

 //编译子文件夹的CMakeLists.txt, 如果子目录下有CMakeList.txt文件,可以通过该命令找到子目录进行编译
add_subdirectory(test)

编译结果

执行完cmake命令之后,就会生成一个对应的编译产物,名字是使用add_library 或者 add_executable 设置的名称。如果设置的是可执行对象,就会生成linux下的可执行文件,可以直接在终端中运行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值