阅读量:

121

为什么使用CMake

实现C/C++编译的跨平台一致性

无CMake时添加一个新源文件,需要在各个平台的工程文件里分别修改

有CMake时添加一个新源文件,只需修改CMakeLists即可

基本语法特性

基本语法格式:指令(参数1 参数2)

参数使用括弧括起

参数之间使用空格或分号分开

指令是大小写无关的

add_executable(hello main.cpp hello.cpp)

ADD_EXECUTABLE(hello main.cpp hello.cpp)

变量是大小写相关的,使用${}方式取值。但在if语句中是直接使用变量名

set(HELLO hello.cpp) # 设置一个变量HELLO,值是hello.cpp

add_executable(hello main.cpp ${HELLO})

重要指令&常用变量

1. 重要指令

cmake_minimum_required:指定CMake的最小版本要求

语法:cmake_minimum_required(VERSION 版本号 [FATAL_ERROR])

// CMake最小版本要求为2.8.3

cmake_minimum_required(VERSION 2.8.3)

project:定义工程名称,并可指定工程支持的语言

语法:project(工程名称 [CXX] [C] [java])

// 指定工程名为HELLOWORLD

project(HELLOWORLD)

set:显式的定义变量

语法:set(变量名 [变量值] [CACHE TYPE DOCSTRING [FORCE]])

// 定义SRC变量,其值为main.cpp hello.cpp

set(SRC sayhello.cpp hello.cpp)

include_directories:向工程添加多个特定的头文件搜索路径,相当于指定g++编译器的-I参数

语法:include_directories([AFTER|BEFORE][SYSTEM] dir1 dir2 ...)

// 将/usr/include/myincludefolder 和 ./include 添加到头文件搜索路径

include_directories(/usr/include/myincludefolder ./include)

link_directories:向工程添加多个特定的库文件搜索路径,相当于指定g++编译器的-L参数

语法:link_directories(dir1 dir2 ...)

// 将/usr/lib/mylibfolder 和 ./lib 添加到库文件搜索路径

link_directories(/usr/lib/mylibfolder ./lib)

add_library:生成库文件

语法:add_library(库名 [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL] source1 source2 .. sourceN)

// 通过变量 SRC 生成 libhello.so 共享库

// SHARED代表动态库,STATIC代表静态库

add_library(hello SHARED ${SRC})

add_compile_options:添加编译参数

语法:add_compile_options(编译参数)

// 添加编译参数 -wall -std=c++11

add_compile_options(-wall -std=c++11 -o2)

add_executable:生成可执行文件

语法:add_executable(exe文件名 source1 source2 .. sourceN)

// 编译main.cpp生成可执行文件main

add_executable(main main.cpp)

target_link_libraries:为target添加需要链接的共享库,相当于指定g++编译器-l参数

语法:target_link_libraries(target library1 library2...)

// 将hello动态库文件链接到可执行文件main

target_link_libraries(main hello)

add_subdirectory:向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制存放的位置

语法:add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

// 添加src子目录,src中需要有一个CMakeLists.txt

add_subdirectory(src)

aux_source_directory:发现一个目录下所有的源代码文件并将列表存储在一个变量中,这个指令临时被用来自动构建源文件列表

语法:aux_source_directory(文件夹路径 变量名)

// 定义SRC变量,其值为当前目录下所有的源代码文件

aux_source_directory(. SRC)

// 编译SRC变量所代表的源代码文件,生成main可执行文件

add_executable(main ${SRC})

2. 常用变量

CMAKE_C_FLAGS:gcc编译选项

CMAKE_CXX_FLAGS:g++编译选项

// 在CMAKE_CXX_FLAGS编译选项后追加-std=c++11

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

CMAKE_BUILD_TYPE:编译类型(Debug, Release)

// 设定编译类型为debug,因为在调试时需要选择debug

set(CMAKE_BUILD_TYPE Debug)

// 设定编译类型为release,因为在发布时需要选择release

set(CMAKE_BUILD_TYPE release)

EXECUTABLE_OUTPUT_PATH:可执行文件输出的存放路径

LIBRARY_OUTPUT_PATH:库文件输出的存放路径

CMake编译工程

CMake目录结构:项目主目录存在一个CMakeLists.txt文件

两种方式设置编译规则:

包含源文件的子文件夹包含CMakeLists.txt文件,主目录的CMakeLists.txt通过add_subdirectory添加子目录即可

包含源文件的子文件夹未包含CMakeLists.txt文件,子目录编译规则体现在主目录的CMakeLists.txt中

1. 编译流程

在linux平台下使用CMake构建C/C++工程的流程如下:

手动编写CMakeLists.txt

执行命令cmake PATH生成Makefile(PATH是顶层CMakeLists.txt所在目录)

执行命令make进行编译

2. 两种构建方式

内部构建(in-source build):不推荐使用

内部构建会在同级目录下产生一大堆中间文件,这些中间文件和工程源文件放在一起显得杂乱无章

## 内部构建

# 在当前目录下,编译本目录的CMakeLists.txt,生成Makefile和其他文件

$ cmake .

# 执行make命令,生成target

$ make

外部构建(out-of-source build):推荐使用

将编译输出文件和源文件放到不同的目录中

## 外部构建

# 1. 在当前目录下,创建build文件夹

$ mkdir build

# 2. 进入到build文件夹

$ cd build

# 3. 编译上级目录的CMakeLists.txt,生成Makefile和其他文件

$ cmake ..

# 4. 执行make命令,生成target

$ make

CMake代码实例

1. 项目结构

2. 项目内容

swap.h

swap.cpp:包含swap.h

main.cpp:包含swap.h

3. 编写CMakeLists.txt

cmake_minimum_required(VERSION 3.0)

project(SWAP)

include_directories(include) // 相当于g++编译命令里的-Iinclude

add_executable(main_cmake main.cpp src/swap.cpp)

CMakeLists.txt的位置在主目录

4. 外部构建编译

# 在主目录/build中编译链接

$ mkdir build

$ cd build

$ cmake ..

$ make

5. 项目最终结构

linux cmake 教程,CMake简明教程相关推荐

  1. 简明python教程pdf-python简明教程中文pdf

    python简明教程中文pdf电子书是作者通过自己对计算机语言多年来的研究和学习得出的学习经验,对于python新手来说非常有用,值得大家下载学习. python简明教程中文pdf文章目录 1.介绍 ...

  2. 计算机 电工学简明教程,电工学简明教程复习要点

    <电工学简明教程复习要点>由会员分享,可在线阅读,更多相关<电工学简明教程复习要点(88页珍藏版)>请在人人文库网上搜索. 1.本章要求掌握1 .旁路电流法.叠加原理.达宾定理 ...

  3. zerotier使用教程_zerotier简明教程

    zerotier简明教程 最近使用zerotier替换了frp来实现内网穿透,zerotier是一个软交换机,使用zerotier可以让多台内网机器组成一个局域网. 首先要安装 zerotier-on ...

  4. linux之SQL语句简明教程---IN

    在 SQL 中,在两个情况下会用到 IN 这个指令:这一页将介绍其中之一 -- 与 WHERE 有关的那一个情况.在这个用法下,我们事先已知道至少一个我们需要的值,而我们将这些知道的值都放入IN 这个 ...

  5. linux之SQL语句简明教程---AND OR

    在上一页中,我们看到 WHERE 指令能够被用来由表格中有条件地选取资料. 这个条件可能是简单的 (像上一页的样例).也可能是复杂的. 复杂条件是由二或多个简单条件透过 AND 或是 OR的连接而成. ...

  6. linux之SQL语句简明教程---UNION ALL

    UNION ALL 这个指令的目的也是要将两个 SQL 语句的结果合并在一起. UNION ALL 和UNION 不同之处在于 UNION ALL 会将每一笔符合条件的资料都列出来,不管资料值有无反复 ...

  7. linux之SQL语句简明教程---SUBSTRING

    SQL 中的 substring 函数是用来抓出一个栏位资料中的当中一部分.这个函数的名称在不同的资料库中不全然一样: MySQL: SUBSTR( ), SUBSTRING( ) Oracle: S ...

  8. Linux开发之Makefile简明教程及示例

    前言 Linux下的开发,一般都是基于开源的编译器,很多时候并没有太好的IDE,此时非常有必要掌握一门通用的编译构建方法.Makefile应运而生,成功了最流行的Linux下的编译构建方法.Makef ...

  9. 【linux工具】Tmux简明教程

    A Quick and Easy Guide to tmux (hamvocke.com) 一.说明 我们常用ubuntu,用alt+ctl+T实现终端窗口弹出.然而当需要多个终端一起工作,切换的效率 ...

  10. linux怎么退出SQL语句,linux之SQL语句简明教程---UPDATE DELETE FROM

    我们有时候可能会需要修改表格中的资料.在这个时候,我们就需要用到 UPDATE 指令.这个指令的语法是: UPDATE "表格名" SET "栏位1" = [新 ...

最新文章

  1. 【C#】【APK】APK文件解析AXML-层层深入APK文件解析之一
  2. How OPA addFrame is called
  3. 冲刺一团队五亲亲精英队
  4. iOS开发之企业级账号的使用注意的坑
  5. 使用 Groovy 合并 MSN 聊天记录
  6. Jenkins linux 操作系统一键部署多节点
  7. 计算机类专业都有什么区别?
  8. 西门子博图功能指令(移动块)
  9. 软件架构设计---产品线及系统演化
  10. c 使用mysql的语句_在 MySQL 数据库中使用C 履行SQL的语句
  11. 下载、预览PDF报错问题排查
  12. 04. Redis 环境搭建-单实例
  13. kalibr标定IMU随机变量(高斯分布)的方差
  14. 7.26 5 优化浪漫 恋爱中的经济学
  15. WSUS客户端更新补丁失败(1)
  16. 在这个互联网加的时代,我们能做些什么呢?
  17. 以梦为马之89c51单片机精确1s时间LED灯闪烁(中断技术+定时/计数器技术)
  18. RecycleBin
  19. UltraEdit+注册机+激活方法
  20. 【游戏开发】多人游戏网络同步相关技术(延迟处理)

热门文章

  1. 从腾讯朋友圈揭秘内部AI部门竞争关系,谁能像微信当年一样熬出头?
  2. nvm介绍、nvm下载安装及使用
  3. 同一个应用安装两个apk在同一个手机的方法
  4. 教妹学 Java:try-catch-finally
  5. 百度云不限速c语言,如何解决百度云下载大文件限速问题
  6. Django REST Framework教程(10): 限流(throttle)详解与示例
  7. 2021CVPR 弱/暗光《Seeing in Extra Darkness Using a Deep-Red Flash》
  8. 暗光增强论文MBLLEN: Low-light Image/Video Enhancement Using CNNs阅读笔记
  9. showdialog wpf 如何关闭_WPF用ShowDialog()弹出窗体时控制该窗体的显示位置,并传值回父窗体...
  10. 2021.04.06JAVA定义一个数组,随便输入一个数字,判断这个数在数组中是否存在,存在返回数组的下标,否则返回-1