cmake简介

在cmake出现之前,在linuxiax下,大型软件系统一般使用make来控制编译过程,而在Windows下可能是用vs下一个project来构建。一个复杂的系统本身依赖关系就很麻烦,如果想把一个linux下的项目拿到Windows下编译,我们可能要重新建立vs工程,这将是一项乏味且令人讨厌的工作。

cmake就是为了解决这个问题而生,同时他也使得控制软件编译过程变得更简单。其基本原理就是开发人员使用cmake的语法规则编写CMakeLists.txt,cmake executable根据该文件在linux下生产Makefile,在Windows下可能生成vs工程。然后再通过make命令编译、安装。开发人员不再需要自己去写Makefile了。

cmake语法

cmake的语法应该不算难,在初学者看来,至少比make要更user friendly一些。具体的语法可以参见cmake document。下面贴出开源项目muduo的root directory下的CMakeLists.txt,我在该文件中加入了一些comment,可以对cmake command有初步的映像。

# for cmake version control, if cmake version lower than this,
# cmake failed. Also this will call cmake_policy(VERSION, 2.6)
# for bug control.
# I see most of projects set this to 2.6
cmake_minimum_required(VERSION 2.6) #project(<PROJECT-NAME> [LANGUAGES] [<language-name>...])
#default C CXX
#this must call (explict or implict)
project(muduo C CXX)
#enable ctest
#will need add_test() command, may in subdirectory/CMakeList.txt
enable_testing() if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
endif()
#Signatures of this command that specify a <value>... placeholder expect zero or more arguments. Multiple arguments will be joined as a ;-list to form the actual variable value to be set. Zero arguments will cause normal variables to be unset. See the unset() command to unset variables explicitly.
set(CXX_FLAGS
-g
# -DVALGRIND
# -DMUDUO_STD_STRING
-DCHECK_PTHREAD_RETURN_VALUE
-D_FILE_OFFSET_BITS=64
-Wall
-Wextra
#-Werror
-Wconversion
-Wno-unused-parameter
-Wold-style-cast
-Woverloaded-virtual
-Wpointer-arith
-Wshadow
-Wwrite-strings
-march=native
# -MMD
# -std=c++0x
-rdynamic
)
#list(LENGTH <list> <output variable>)
#list(GET <list> <element index> [<element index> ...]
# <output variable>)
#list(APPEND <list> [<element> ...])
#list(FILTER <list> <INCLUDE|EXCLUDE> REGEX <regular_expression>)
#list(FIND <list> <value> <output variable>)
#list(INSERT <list> <element_index> <element> [<element> ...])
#list(REMOVE_ITEM <list> <value> [<value> ...])
#list(REMOVE_AT <list> <index> [<index> ...])
#list(REMOVE_DUPLICATES <list>)
#list(REVERSE <list>)
#list(SORT <list>)
if(CMAKE_BUILD_BITS EQUAL 32)
list(APPEND CXX_FLAGS "-m32")
endif()
#replace all ";" in CXX_FLAGS with " " and output to CMAKE_CXX_FLAGS
string(REPLACE ";" " " CMAKE_CXX_FLAGS "${CXX_FLAGS}") set(CMAKE_CXX_COMPILER "g++")
set(CMAKE_CXX_FLAGS_DEBUG "-O0")
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -finline-limit=1000 -DNDEBUG")
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
# call /usr/share/cmake-3.5/Modules/FindBoost.cmake
find_package(Boost REQUIRED)
find_package(Protobuf)
find_package(CURL)
find_package(ZLIB)
# find the path where ares.h in
find_path(CARES_INCLUDE_DIR ares.h)
find_library(CARES_LIBRARY NAMES cares)
find_path(MHD_INCLUDE_DIR microhttpd.h)
find_library(MHD_LIBRARY NAMES microhttpd)
find_library(BOOSTTEST_LIBRARY NAMES boost_unit_test_framework)
find_library(BOOSTPO_LIBRARY NAMES boost_program_options)
find_path(TCMALLOC_INCLUDE_DIR gperftools/heap-profiler.h)
find_library(TCMALLOC_LIBRARY NAMES tcmalloc_and_profiler)
find_path(HIREDIS_INCLUDE_DIR hiredis/hiredis.h)
find_library(HIREDIS_LIBRARY NAMES hiredis)
find_path(GD_INCLUDE_DIR gd.h)
find_library(GD_LIBRARY NAMES gd)
find_program(THRIFT_COMPILER thrift)
find_path(THRIFT_INCLUDE_DIR thrift)
find_library(THRIFT_LIBRARY NAMES thrift) if(CARES_INCLUDE_DIR AND CARES_LIBRARY)
message(STATUS "found cares")
endif()
if(CURL_FOUND)
message(STATUS "found curl")
endif()
if(PROTOBUF_FOUND)
message(STATUS "found protobuf")
endif()
if(TCMALLOC_INCLUDE_DIR AND TCMALLOC_LIBRARY)
message(STATUS "found tcmalloc")
endif()
if(ZLIB_FOUND)
message(STATUS "found zlib")
endif()
if(HIREDIS_INCLUDE_DIR AND HIREDIS_LIBRARY)
message(STATUS "found hiredis")
endif()
if(GD_INCLUDE_DIR AND GD_LIBRARY)
message(STATUS "found gd")
endif()
if(THRIFT_COMPILER AND THRIFT_INCLUDE_DIR AND THRIFT_LIBRARY)
message(STATUS "found thrift")
endif() include_directories(${Boost_INCLUDE_DIRS}) include_directories(${PROJECT_SOURCE_DIR}) string(TOUPPER ${CMAKE_BUILD_TYPE} BUILD_TYPE)
message(STATUS "CXX_FLAGS = " ${CMAKE_CXX_FLAGS} " " ${CMAKE_CXX_FLAGS_${BUILD_TYPE}}) add_subdirectory(muduo/base)
add_subdirectory(muduo/net) if(NOT CMAKE_BUILD_NO_EXAMPLES)
add_subdirectory(contrib)
add_subdirectory(examples)
else()
if(CARES_INCLUDE_DIR AND CARES_LIBRARY)
add_subdirectory(examples/cdns)
endif()
endif()

cmake示例

编译链接库

构建lib应该算是一个最常见的需求,现在假设我们新建一个简单库,只包含一个整数相加的函数。我们有两个文件add.h和add.cc。

//add.h
int add(int a, int b);
//add.cc
#include"add.h" int add(int a, int b)
{
return a + b;
}

我们可以新建CMakeLists.txt如下

cmake_minimum_required(VERSION 2.6)
project(add)
set (add_SRCS
add.cc
)
add_library(add ${add_SRCS}) install(TARGETS add DESTINATION lib)
file(GLOB HEADERS "*.h")
install(FILES ${HEADERS} DESTINATION include/add)

这个命令不仅可以帮我们编译add这个lib,而且还可以将.a文件和.h文件安装到指令的目录下,这个由变量CMAKE_INSTALL_PREFIX控制,可用ccmake命令更改,default是/usr/local目录下。

编译可执行文件

现在假设我们要写一个程序,并且要使用上一步中的链接库,下面是程序代码及CMakeLists.txt

//test.cc
#include"add.h" #include<iostream> int main()
{
std::cout << add(1, 2) << std::endl;
}
cmake_minimum_required(VERSION 2.6)
project(main)
set (main_SRCS
test.cc
)
include_directories("/home/keviwu/add/include/add")
find_library(LIB_PATH add "/home/keviwu/add/lib") if (NOT LIB_PATH)
message("libadd.a not find")
endif() add_executable(main ${main_SRCS})
target_link_libraries(main ${LIB_PATH})

learn cmake的更多相关文章

  1. CMake速记

    目录 CMake速记 我的demo 外部构建 基础语法 常用指令 环境变量 一些变量 参考文档 title: CMake速记 date: 2019/11/18 19:17:40 toc: true - ...

  2. vscode c++ cmake template project

    VSCode configure C++ dev environment claim use CMake to build the project. For debugging, VSCode's C ...

  3. CMake 构建项目教程-简介

    CMake 构建项目教程-简介 Linux 平台构建项目,选择了CLion作为C++的IDE,而CLion默认就是使用CMake构建项目,所以这里记录了CMake在构建项目过程的一些小知识. 1. 项 ...

  4. win10下VSCode+CMake+Clang+GCC环境搭建

    win10下VSCode+CMake+Clang+GCC环境搭建 win10下VSCode+CMake+Clang+GCC环境搭建 安装软件 VSCode插件安装 新建文件夹, 开始撸代码 main. ...

  5. Reprint: CMake or Make

    CMake vs Make https://prateekvjoshi.com/2014/02/01/cmake-vs-make/ Programmers have been using CMake ...

  6. 使用VSCode和CMake构建跨平台的C/C++开发环境

    日前在学习制作LearnOpenGL教程的实战项目Breakout游戏时,希望能将这个小游戏开发成跨平台的,支持在多个平台运行.工欲善其事必先利其器,首先需要做的自然是搭建一个舒服的跨平台C/C++开 ...

  7. 使用cmake自动构建工程

    公司引擎是用cmake根据目标平台来构建工程的,刚接触的时候深深体会到cmake的方便:如果目标平台是windows,它可以帮你自动构建出vs工程:如果是安卓,自动构建出eclipse工程,如果是IO ...

  8. CMake

    使用CMake编译跨平台静态库 http://www.tuicool.com/articles/3uu2Yj cmake命令 安装.用法简介 https://fukun.org/archives/04 ...

  9. CMake学习笔记

    C++开发者必备技能CMake  先简单介绍一下,CMake是一个跨平台的编译工具,它可以根据不用的平台,不同的编译环境,生成不同的MakeFile,从而控制编译的过程. 使用CMake的步骤: 1. ...

随机推荐

  1. bootstrap modal 一闪

    原因可能是因为bootstrap.min.js(bootstrap.js) 和modal.js重复引用导致的,而且重复引用还会引致bootstrap的js事件失效.

  2. 通过nvm 切换 npm 版本

    通过 nvm-windows 更新 npm 1.先安装 nvm-windows .成功后可在命令窗口 输入nvm 查看到 nvm的版本号. 2..在命令窗口输入 nvm list,查看当前使用的 no ...

  3. CorelDRAW 2019线上发布会报名已开始

    近日,由苏州思杰马克丁软件公司独家代理的CorelDRAW 2019将在苏州开启一场设计上的饕餮盛宴,您报名了么? 不管您是专业的设计师还是热爱设计的狂热粉丝,都将有机会参与到我们的活动中,为了这场盛 ...

  4. ZBrush中的PolyPainting如何理解?

    什么是PolyPainting? PolyPainting在ZBrush ®中是一种创建纹理的方法,该方法通过对每个多边形顶点应用单一RGB值来着色模型.此方法无需使用UV坐标.通过直接对顶点应用颜色 ...

  5. 接口测试及Postman工具

    首先,什么是接口呢? 接口一般来说有两种,一种是程序内部的接口,一种是系统对外的接口.系统对外的接口:比如你要从别的网站或服务器上获取资源或信息,别人肯定不会把数据库共享给你,他只能给你提供一个他们写 ...

  6. Python代码块缓存、小数据池

    引子 前几天遇到了这样一道Python题目:a='123',b='123',下列哪个是正确的? A. a != b B. a is b C. a==123 D. a + b =246 正确答案是B 是 ...

  7. JS 输名字随机弹出

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. CreateFile打开文件或者打开目录

    一.打开目录 参数列表: lpFileName String 要打开的文件的名字 dwDesiredAccess Long 如果为 GENERIC_READ 表示允许对设备进行读访问:如果为 GENE ...

  9. java中super和this用法总结

    一.this用法 概念:this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的指针. this的用法在java中大致可以分为三种: 1. 普通对象的直接引用:this相当于指向当前对象本身 ...

  10. Project Euler 34 Digit factorials

    题意:判断一个数 N 的各个位数阶乘之和是否为其本身,找出所有符合要求的数然后求和 思路:此题思路跟 30 题相同,找到枚举上界 10 ^ n <= 9! × n ,符合要求的 n < 6 ...