1.准备工作:

首先,在/code_test 目录下建立一个 cmake 目录,用来放置我们学习过程中的所有练习。(如果以下命令出现xxx: cannot create directory ‘x’: Permission denied错误则需要在命令前加上sudo,编译时也是)
mkdir -p /code_test/cmake
以后我们所有的cmake练习都会放在/code_test/cmake 的子目录下(你也可以自行安排目录,这个并不是限制,仅仅是为了叙述的方便)然后在cmake目录下建立第一个练习目录p1
cd /code_test/cmake
mkdir p1
cd p1

在 p1 目录建立 main.cpp 和 CMakeLists.txt(注意文件名大小写)并用你所熟悉的文本编辑器加入以下内容:

//main.cpp

#include <iostream>

using namespace std;

int main()
{
cout<<"Hello World !"<<endl;return ;
}

//CmakeLists.txt 文件内容:

PROJECT (HELLO)
SET(SRC_LIST main.cpp)
MESSAGE(STATUS "This is BINARY dir " ${HELLO_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir "${HELLO_SOURCE_DIR})
ADD_EXECUTABLE(hello ${SRC_LIST})

CMakeLists.txt是cmake的构建定义文件,注意文件名是大小写相关的,如果工程存在多个目录,需要确保每个要管理的目录都存在一个CMakeLists.txt。目的是生成Makefile文件,其实也可以直接编写makefile,但是大工程比较复杂,所以用CmakeLists.txt目的就是自动生成Makefile。

下面分析语法:

PROJECT指令的语法是

PROJECT(projectname [CXX] [C] [Java])
这个指令定义工程名称,并可指定工程支持的语言,默认情况表示支持所有语言。非常重要的是这个指令隐式的定义了两个cmake变量: <projectname>_BINARY_DIR 以及<projectname>_SOURCE_DIR 这里就是HELLO_BINARY_DIR 和 HELLO_SOURCE_DIR (所以CMakeLists.txt中两 MESSAGE指令可以直接使用了这两个变量),如果采用的是内部编译,两个变量目前指的都是工程所在路径/code_test/cmake/p1,后面我们会讲到外部编译,两者所指代的内容会有所不同。为了统一起见,建议以后直接使用 PROJECT_BINARY_DIR  PROJECT_SOURCE_DIR,好处是即使修改了工程名称,也不会影响这两个变量。如果使用了<projectname>_SOURCE_DIR,修改工程名称后,需要同时修改这些变量。
 

SET指令的语法是

SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])
SET指令可以用来显式的定义变量,比如我们用到的SET(SRC_LIST main.cpp), 也就是将man.cpp赋给SRC_LIST变量,以后SRC_LIST就是指man.cpp可以理解为c++里的别名引用,如果有多个源文件,也可以定义成:SET(SRC_LIST main.cpp x1.cpp x2.cpp)还有一点虽不常用但得注意SET(SRC_LIST main.cpp)也可以写成 SET(SRC_LIST “main.cpp”)是没有区别的,但是假设一个源文件的文件名是 fu nc.cpp(文件名中间包含了空格)。这时候就必须使用双引号,如果写成了 SET(SRC_LIST fu nc.cpp),就会出现错误,提示你找不到 fu 文件和 nc.cpp 文件。
 

MESSAGE 指令的语法是:

MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message to display" ...)
这个指令主要用来调试用,用于向终端输出用户定义的信息,包含了三种类型:
SEND_ERROR,产生错误,生成过程被跳过。
SATUS,输出信息。
FATAL_ERROR,立即终止所有 cmake 过程。
我们在这里使用的是 STATUS 信息输出,显示的效果是: 
This is BINARY dir /code_test/cmake/p1
This is SOURCE dir /code_test/cmake/p1
 
ADD_EXECUTABLE(hello ${SRC_LIST})
定义了这个工程会生成一个文件名为hello的可执行文件(自己随便起名字),相关的源文件是SRC_LIST中定义的源文件列表,本例中你也可以直接写成 ADD_EXECUTABLE(hello main.cpp)。变量使用${}方式取值,这是cmake的变量应用方式,但是,有一些例外,在IF控制语句中是直接使用变量名引用,而不需要${}。
 
注意:1.参数使用括弧括起,参数之间使用空格或分号分开。2.指令是大小写无关的,参数和变量是大小写相关的。但推荐全部使用大写指令。
2.开始构建:构建分为内部构建(in-sourcebuild)和外部构建(out-of-source build),外部构建一个最大的好处是,对于原有的工程没有任何影响,所有动作全部发生在编译目录。而cmake强烈推荐的是外部构建。

内部构建:

这在个目录下输入命令:
cmake .  //注意命令后面的点号,代表本目录

输出大概是这个样子:

你会发现,目录中系统自动生成了:

CMakeFiles, CMakeCache.txt, cmake_install.cmake 等文件,并且生成了Makefile.最关键的是它自动生成Makefile其他的不用理,make主要去找Makefile,make是一个命令工具,是一个解释makefile中指令的命令工具,其实也可以直接编写makefile,但是大工程比较复杂,所以用CmakeLists.txt目的就是自动生成Makefile。
然后进行工程的实际构建,在这个目录输入命令:
 
make 

输出大概是这个样子:

如果你需要看到 make 构建的详细过程,可以使用 make VERBOSE=1 或者 VERBOSE=1命令来进行构建。
我们需要的目标文件 hello 已经构建完成,位于当前目录,尝试运行一下:
./hello

得到输出:

Hello World !

外部编译:

1.首先,请清除p1目录中除main.c CmakeLists.txt之外的所有中间文件,最关键的是CMakeCache.txt。
2.在p1目录中建立build目录,当然你也可以在任何地方建立build目录,不一定必须在工程目录中。
mkdir build
3.进入build目录,运行cmake ..(: .. 代表父目录,因为父目录存在我们需要的CMakeLists.txt,如果你在其他地方建立了build目录,需要运行cmake<工程的全路径>找到CMakeLists.txt),查看一下build目录,就会发现了生成了编译需要的Makefile以及其他的中间文件。
cd build
cmake ..
4.运行make构建工程,就会在当前目录(build目录)中获得目标文件hello 
make

让我们的代码更像个工程:

http://www.cnblogs.com/zjiaxing/p/5557648.html

cmake实战第一篇:初试 cmake的更多相关文章

  1. spring boot实战(第一篇)第一个案例

    版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[+]   spring boot实战(第一篇)第一个案例 前言 写在前面的话 一直想将spring boot相关内容写成一个系列的 ...

  2. vue+uni-app商城实战 | 第一篇:【有来小店】微信小程序快速开发接入Spring Cloud OAuth2认证中心完成授权登录

    一. 前言 本篇通过实战来讲述如何使用uni-app快速进行商城微信小程序的开发以及小程序如何接入后台Spring Cloud微服务. 有来商城 youlai-mall 项目是一套全栈商城系统,技术栈 ...

  3. Hadoop实战第一篇

    前言:  都说现在是草根为尊的时代,近年来hadoop及spark技术在国内越来越流行.而且渐渐现成为企业的新宠.在DT时代全面来临之前,能提早接触大数据的技术必然能先人一步.本文作为Hadoop系列 ...

  4. (python3爬虫实战-第一篇)利用requests+正则抓取猫眼电影热映口碑榜

    今天是个值得纪念了日子,我终于在博客园上发表自己的第一篇博文了.作为一名刚刚开始学习python网络爬虫的爱好者,后期本人会定期发布自己学习过程中的经验与心得,希望各位技术大佬批评指正.以下是我自己做 ...

  5. cmake实战第二篇:让我们的代码更像个工程

    为工程添加以下文件夹:    bin 用来放编译好的可执行二进制文件. src 用来放源代码. lib 用来放编译好的库文件. include 用来放头文件. sudo mkdir -p /code_ ...

  6. Canal 实战 | 第一篇:SpringBoot 整合 Canal + RabbitMQ 实现监听 MySQL 数据库同步更新 Redis 缓存

    一. Canal 简介 canal [kə'næl],译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费 早期阿里巴巴因为杭州和美国双机房部署,存在跨机房同 ...

  7. SpringCloud实战 | 第一篇:Windows搭建Nacos服务

    前言 为什么放弃eureka选择nacos?本地开发环境需要搭建nacos-server,想着是很简单的事但是被一些文章(少了关键必要的步骤)给带偏了,所以亲测成功后写了这篇文章. 搭建nacos-s ...

  8. Docker实战 | 第一篇:Centos8 安装 Docker

    1. 安装依赖包 yum install -y yum-utils device-mapper-persistent-data lvm2 2. 配置镜像源 yum config-manager --a ...

  9. Spring Cloud实战 | 最终篇:Spring Cloud Gateway+Spring Security OAuth2集成统一认证授权平台下实现注销使JWT失效方案

    一. 前言 在上一篇文章介绍 youlai-mall 项目中,通过整合Spring Cloud Gateway.Spring Security OAuth2.JWT等技术实现了微服务下统一认证授权平台 ...

随机推荐

  1. tc: 模拟网络异常的工具-----------鸟窝

    http://colobu.com/2017/04/21/tc-introduction/

  2. linux之vim命令

    :tabe fn     在一个新的标签页中编辑文件fngt     切换到下一个标签页gT     切换到上一个标签页:tabr     切换到第一个标签页:tabl     切换到最后一个标签页: ...

  3. python下性能提示

    性能提示 3.1 嵌套if/else结构比一系列单选if结构块,因为只要有一个条件满足,其余测试就会终止. 3.2 在嵌套if/else结构中,把最可能成立的条件放在该嵌套结构的开始处.和把不常见的条 ...

  4. selfshadow

    realtime rendering v3 page 351 Moire pattern sruface acne artifacts ----------------------- 用 setsta ...

  5. Vue自定义指令和路由

    一.自定义指令 除了默认设置的核心指令( v-model 和 v-show ), Vue 也允许注册自定义指令. 下面我们注册一个全局指令 v-focus,该指令的功能是在页面加载时,元素获得焦点: ...

  6. 【Hadoop】HADOOP 总结--思维导图

  7. ListView控件绑定DataSet

    DataSet数据集,数据缓存在客户端内存中,支持断开式连接.   在对DataSet做操作的时候,首先一定要修改其行的状态,然后执行SqlDataAdapter的Update方法,Update方法根 ...

  8. MYSQL优化之碎片整理

    MYSQL优化之碎片整理   在MySQL中,我们经常会使用VARCHAR.TEXT.BLOB等可变长度的文本数据类型.不过,当我们使用这些数据类型之后,我们就不得不做一些额外的工作--MySQL数据 ...

  9. 【Java】各种软件安装与环境配置的失败

    又来到了java的世界,看了一段时间的视频.感觉太空虚,便从网上找到一个教程.想做几个demo试试,少不了的前期准备:Java开发环境配置,Eclipse JSP/Servlet 环境搭建等.     ...

  10. linux驱动current,引用当前进程,及task_struct(转)

    尽管内核模块不象应用程序一样顺序执行, 内核做的大部分动作是代表一个特定进程的. 内核代码可以引用当前进程, 通过存取全局项 current, 它在 <asm/current.h> 中定义 ...