一、CMake简介

  • CMake是一个跨平台的编译工具,能够输出各种各样的makefile或者project文件。
  • CMake并不直接构建出最终的软件,而是生成标准的Makefile文件或者VisualStudio项目文件,然后再使用Make或者VisualStudio进行编译。
  • CMake在Windows平台上生成VisualStudio项目文件,在Linux和Unix平台上生成Makefile文件。

二、CMake典型示例

源代码 demo.cpp

int main()
{
return 0;
}

cmake脚本 CMakeLists.txt

# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (demo)
# 指定生成目标
add_executable(demo demo.cpp)

编译流程

  • Windows

    1. 创建build文件夹
    2. 在build文件夹中执行 cmake .. 命令
    3. 用Visual Studio打开生成的demo.sln,然后编译
  • Linux

mkdir build
cd build
cmake ..
make

三、CMake常用命令

CMake中常用的语法包含三类:

  • 命令
  • 变量
  • 属性

常用命令介绍

设置编译目标类型

  • add_executable 生成可执行文件
  • add_library 生成库文件

比如:

add_executable(demo demo.cpp)
add_library(common util.cpp)

add_library默认生成静态库,可以显式的控制生成的库的类型

add_library(common STATIC util.cpp) #生成静态库
add_library(common SHARED util.cpp) #生成动态库或共享库

通过以上命令生成文件名字,在Windows下是:

demo.exe
common.lib
common.dll

在Linux下是:

demo
libcommon.a
libcommon.so

指定编译包含的源文件

  1. 明确指定包含的源文件
add_executable(demo demo.cpp test.cpp util.cpp)
  1. 搜索所有的cpp文件
aux_source_directory(. SRC_LIST) #搜索当前目录下的所有.cpp文件
add_executable(demo ${SRC_LIST})
  1. 自定义搜索规则
file(GLOB SRC_LIST "*.cpp" "*.cc")
add_executable(demo ${SRC_LIST})
  1. 包含多个文件夹的文件
file(GLOB SRC_LIST "*.cpp" "protocol/*.cpp")
add_executable(demo ${SRC_LIST})
# 或者
file(GLOB SRC_LIST "*.cpp")
file(GLOB SRC_PROTOCOL_LIST "protocol/*.cpp")
add_executable(demo ${SRC_LIST} ${SRC_PROTOCOL_LIST})
# 或者
aux_source_directory(. SRC_LIST)
aux_source_directory(protocol SRC_PROTOCOL_LIST)
add_executable(demo ${SRC_LIST} ${SRC_PROTOCOL_LIST})
  1. 通过模糊搜索的方式包含源文件,当添加新的源文件后,需要通过cmake命令重新生成Makefile或者VS项目文件

设置包含目录

include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
)

Linux下还可以通过如下方式设置包含目录

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I${CMAKE_CURRENT_SOURCE_DIR}")

设置链接库搜索目录

link_directories(
${CMAKE_CURRENT_SOURCE_DIR}/libs64
)

Linux下还可以通过如下方式设置包含目录

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_CURRENT_SOURCE_DIR}/libs64")

设置需要链接的库

根据链接库目录搜索

target_link_libraries(demo Math)
  • 在Windows下,会根据链接库目录,搜索Math.lib文件
  • 在Linux下,会根据链接库目录搜索如下文件:
libMath.so
libMath.a

默认优先链接动态库,可以在链接时指定动态库或者静态库如:

target_link_libraries(demo Math.a)  # 链接libMath.a
target_link_libraries(demo Math.so) # 链接libMath.so

指定全路径

target_link_libraries(demo ${CMAKE_CURRENT_SOURCE_DIR}/libs64/libMath.a)
target_link_libraries(demo ${CMAKE_CURRENT_SOURCE_DIR}/libs64/libMath.so)

指定多个链接库

target_link_libraries(demo
${CMAKE_CURRENT_SOURCE_DIR}/libs64/libMath.a
boost_system.a
boost_thread
pthread)

设置变量

  1. set 直接设置变量的值
set(SRC_LIST main.cpp test.cpp)
add_executable(demo ${SRC_LIST})
  1. set 追加变量的值
set(SRC_LIST main.cpp)
set(SRC_LIST ${SRC_LIST} test.cpp)
add_executable(demo ${SRC_LIST})
  1. list 追加或者删除变量的值
set(SRC_LIST main.cpp)
list(APPEND SRC_LIST test.cpp)
list(REMOVE_ITEM SRC_LIST main.cpp)
add_executable(demo ${SRC_LIST})

条件控制

  • if else elseif endif
if(MSVC)
set(LINK_LIBS common)
else()
set(boost_thread boost_log.a boost_system.a)
endif() target_link_libraries(demo ${LINK_LIBS}) # 或者
if(UNIX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fpermissive -g")
else()
add_definitions(-D_SCL_SECURE_NO_WARNINGS
-D_CRT_SECURE_NO_WARNINGS
-D_WIN32_WINNT=0x601
-D_WINSOCK_DEPRECATED_NO_WARNINGS)
endif() if(${CMAKE_BUILD_TYPE} MATCHES "debug")
...
else()
...
endif()
  • while break continue foreach end_while end_foreach

其他常用命令

  • message 显示一些消息
message(${MY_VAR})
message("build with debug mode")
message(WARNING "this is warnning message")
message(FATAL_ERROR "this build has many error") # 会导致生成失败
  • source_group 在Windows下起作用,设置源文件在项目中的目录结构
file(GLOB PROTOCOL_FILES "protocol/*.cpp")
source_group("协议" FILES ${PROTOCOL_FILES})
  • set_target_properties 设置项目属性
  • set_property 设置全局属性、项目属性等
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
#设置项目在解决方案中的目录结构,只在Windows下生效
set_target_properties(ServerManager PROPERTIES FOLDER "manager")
  • include 包含其他cmake文件
include(./common.cmake) #指定包含文件的全路径
include(def) #在搜索路径中搜索def.cmake文件
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) #设置include的搜索路径

四、复杂项目示例

多个目录,多个源文件,多个项目

项目目录结构如下:

./demo
|
+--- main.cc
|
+--- math/
|
+--- MathFunctions.cc
|
+--- MathFunctions.h

这种情况还可以通过add_subdirectory的方式添加子目录

添加cmake脚本后的目录结构如下:

./demo
|
+--- CMakeLists.txt
|
+--- main.cc
|
+--- math/
|
+--- CMakeLists.txt
|
+--- MathFunctions.cc
|
+--- MathFunctions.h

demo下的CMakeLists.txt文件如下:

cmake_minimum_required (VERSION 2.8)
project(demo)
aux_source_directory(. DIR_SRCS) # 添加math子目录
add_subdirectory(math) # 指定生成目标
add_executable(demo ${DIR_SRCS}) # 添加链接库
target_link_libraries(demo MathFunctions)

math目录中的CMakeLists.txt:

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

五、常用变量

构建类型

cmake默认支持多种构建类型(build type),每种构建类型都有专门的编译参数变量,详情见下表

CMAKE_BUILD_TYPE 对应的c编译选项变量 对应的c++编译选项变量
None CMAKE_C_FLAGS CMAKE_CXX_FLAGS
Debug CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG
Release CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE
RelWithDebInfo CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS_RELWITHDEBINFO
MinSizeRel CMAKE_C_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_MINSIZEREL

指定构建类型

  1. Windows的VS项目属于多配置型,可以在VS中选择生成的配置
  2. 生成后的项目默认包含四种配置
  3. 改变默认的配置
set(CMAKE_CONFIGURATION_TYPES "Debug;RelWithDebInfo")
  1. 默认生成的平台类型为Win32,如果需要x64类型,则需要按如下命令执行
cmake -G "Visual Studio 14 2015 Win64" ..
  1. Linux下的Makefile属于单配置型,需要指定生成配置
  2. 默认执行 cmake ..,会生成None配置
  3. 可以通过命令行指定配置
cmake -DCMAKE_BUILD_TYPE=Debug ..
  1. 可以在CMake文件中指定配置
set(CMAKE_BUILD_TYPE DEBUG)

变量

  • 变量的引用方式是使用“${}”,在if命令中,不需要使用这种方式,直接使用变量名即可
  • 自定义变量使用SET(OBJ_NAME xxxx),使用时${OBJ_NAME}

常用变量

  • CMAKE_BINARY_DIR,PROJECT_BINARY_DIR,_BINARY_DIR:

    这三个变量内容一致,如果是内部编译,就指的是工程的顶级目录,如果是外部编译,指的就是工程编译发生的目录。

  • CMAKE_SOURCE_DIR,PROJECT_SOURCE_DIR,_SOURCE_DIR:

    这三个变量内容一致,都指的是工程的顶级目录。

  • CMAKE_CURRENT_BINARY_DIR:外部编译时,指的是target目录,内部编译时,指的是顶级目录

  • CMAKE_CURRENT_SOURCE_DIR:CMakeList.txt所在的目录

  • CMAKE_CURRENT_LIST_DIR:CMakeList.txt的完整路径

  • CMAKE_CURRENT_LIST_LINE:当前所在的行

  • CMAKE_MODULE_PATH:如果工程复杂,可能需要编写一些cmake模块-,这里通过SET指定这个变量

  • LIBRARY_OUTPUT_DIR,BINARY_OUTPUT_DIR:库和可执行的最终存放目录

环境变量

  • 使用环境变量:$ENV{Name}
  • 写入环境变量:set(ENV{Name} value) #这里没有“$”符号

系统信息

  • CMAKE_MAJOR_VERSION,CMAKE 主版本号,比如2.4.6 中的2
  • CMAKE_MINOR_VERSION,CMAKE 次版本号,比如2.4.6 中的4
  • CMAKE_PATCH_VERSION,CMAKE 补丁等级,比如2.4.6 中的6
  • CMAKE_SYSTEM ,系统名称,比如Linux-2.6.22
  • CMAKE_SYSTEM_NAME ,不包含版本的系统名,比如Linux
  • CMAKE_SYSTEM_VERSION ,系统版本,比如2.6.22
  • CMAKE_SYSTEM_PROCESSOR,处理器名称,比如i686
  • UNIX ,在所有的类UNIX平台为TRUE,包括OS X 和cygwin
  • WIN32 ,在所有的win32 平台为TRUE,包括cygwin

主要开关选项

  • BUILD_SHARED_LIBS, 这个开关用来控制默认的库编译方式,如果不进行设置,使用add_library 并没有指定库类型的情况下,默认编译生成的库都是静态库。如果set(BUILD_SHARED_LIBS ON) 后,默认生成的为动态库
  • CMAKE_C_FLAGS 设置C编译选项,也可以通过指令add_definitions() 添加
  • CMAKE_CXX_FLAGS 设置C++ 编译选项,也可以通过指令add_definitions() 添加

六、参考资料

CMake简介的更多相关文章

  1. 【转载】CMake 简介和 CMake 模板

    转载自我的博客: CMake 简介和 CMake 模板 . 如果你用 Linux 操作系统,使用 cmake 会简单很多,可以参考一个很好的教程: CMake 入门实战 | HaHack .如果你用 ...

  2. CMake 简介与使用

    cross platform make的缩写. 是一个比make更高级的编译配置工具,它可以根据不同平台.不同的编译器,生成相应的Makefile或者vcproj项目文件.通过编写CMakeLists ...

  3. cmake 简介

    CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程).他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的 ...

  4. 非常陌生的cmake

    CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程).他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的 ...

  5. cmake,gtest单元测试程序

    参考:http://blog.csdn.net/stdcoutzyx/article/details/8284183 PROJECT (HELLO) SET(SRC_LIST main.c) MESS ...

  6. CMake基本语法

    CMake简介 CMake 是做什么的? CMake是一套类似于automake的跨平台辅助项目编译的工具. 我觉得语法更加简单易用. CMake的工作流程 CMake处理顶级目录的CMakeList ...

  7. CMake 条件判断

    CMake简介 CMake 是做什么的? CMake是一套类似于automake的跨平台辅助项目编译的工具. 我觉得语法更加简单易用. CMake的工作流程 CMake处理顶级目录的CMakeList ...

  8. 基于Cmake+QT+VS的C++项目构建开发编译简明教程

    目录 一.工具下载与安装 1.     Qt 2.     Visual Studio 2015 3.     Cmake 二.C++及Qt项目构建 1.     基于VS构建Qt项目 2.     ...

  9. [转] CMake

    转载地址:https://www.cnblogs.com/lidabo/p/7359422.html cmake 简介 CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装( ...

随机推荐

  1. ARP攻击之Kali Linux局域网断网攻击

    特别声明: 我们学习研究网络安全技术的目的应是为了维护网络世界的安全,保护自己和他人的私有信息不被非法窃取和传播.请您遵守您所在地的法律,请勿利用本文所介绍的相关技术做背离道德或者违反法律的事情. S ...

  2. jQuery学习之旅 Item5 $与jQuery对象

    1.$符号的由来 $符号本质就是函数的名字. jquery源码分析 通过分析我们知道,在jquery里边不只可以使用$符号,还可以使用jQuery标志 解决冲突问题 有的项目是中间过渡项目(proto ...

  3. 关于bash

    Linux中有一位名叫"巴士"的tool.他是如何出世的呢?原来,他是一个为GNU计划(GNU计划,又称革奴计划,是由Richard Stallman在1983年9月27日公开发起 ...

  4. 安卓----Spinner

    <?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android=" ...

  5. C++中使用引用作为函数参数的优点

    1.传递引用给函数与传递指针的效果是一样的.这时,被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其相应的目标 对象(在主调函数中)的操作. ...

  6. Android性能优化-内存泄漏的8个Case

    1为什么要做性能优化? 手机性能越来越好,不用纠结这些细微的性能? Android每一个应用都是运行的独立的Dalivk虚拟机,根据不同的手机分配的可用内存可能只有(32M.64M等),所谓的4GB. ...

  7. RecyclerView 刷新后自动滚动的问题,notifyDataSetChanged 后自己滚动

    把recyclerview 高度设为match_parent就解决了..... source: https://segmentfault.com/q/1010000005966966

  8. FTRL(Follow The Regularized Leader)学习总结

    摘要: 1.算法概述 2.算法要点与推导 3.算法特性及优缺点 4.注意事项 5.实现和具体例子 6.适用场合 内容: 1.算法概述 FTRL是一种适用于处理超大规模数据的,含大量稀疏特征的在线学习的 ...

  9. es6学习笔记-proxy对象

    前提摘要 尤大大的vue3.0即将到来,虽然学不动了,但是还要学的啊,据说vue3.0是基于proxy来进行对值进行拦截并操作,所以es6的proxy也是要学习一下的. 一 什么是proxy Prox ...

  10. 100 天从 Python 新手到大师

    Python应用领域和就业形势分析 简单的说,Python是一个“优雅”.“明确”.“简单”的编程语言. 学习曲线低,非专业人士也能上手 开源系统,拥有强大的生态圈 解释型语言,完美的平台可移植性 支 ...