当前课程知识点:基于Linux的C++ >  第十二讲 Linux系统编程基础 >  12.14 makefile文件(三) >  LinuxCPP1214

返回《基于Linux的C++》慕课在线视频课程列表

LinuxCPP1214在线视频

LinuxCPP1214

下一节:LinuxCPP1215

返回《基于Linux的C++》慕课在线视频列表

LinuxCPP1214课程教案、知识点、字幕

在编写 makefile 的时候

我们可以使用静态模式

用百分号来进行通配

它的基本格式是这样的:

“target : target_pattern : prerequisites”

第二行以后就用 Tab 键开头的 commands

你按照这个模式来写

它的最主要目的

就是用于处理模式相同的很多个目标

来简化我们脚本代码的

你比如讲

我有这样的一个程序需要编译

每一个目标的文件

都是以 “.o” 的形式存在的

先决条件都是以 “.c” 的形式来存在的

就像我们刚才那个例子

我就俩文件 “main.c”、“library.c”

还有一个头文件 “library.h” 对吧

总共就三文件 两个源文件

我要编译出来的目标文件其实就两个

“main.o”、“library.o”

这两个文件的格式是一模一样的

我不需要写两个 我写一个就行了

那么我就可以按照这个模式来写 makefile:

“objs = main.o library.o”

然后写一个规则 “$(objs) : %.o : %.c”

命令是 “$(CC) -c $(CFLAGS) $< -o $@”

什么东西 太怪了

把它翻译出来就是 “main.o : main.c”

“$(CC) -c $(CFLAGS) main.c -o main.o”

“library.o : library.c”

“$(CC) -c $(CFLAGS) library.c -o library.o”

明白了 我要生成两个目标文件

都以 “.o” 结尾

对应的先决条件的文件名字都是 “.c” 结尾

所以我们就可以把它统一成一行

就是对 $(objs) 这个变量里边的先决条件中的每一个

就是对 $(objs) 这个变量里边的先决条件中的每一个

它是个目标 $(objs) 这是一个目标了

那就是对这个目标中的每一个

因为它对应于 “main.o” 和 “library.o” 嘛

是双目标 我们这里面是多目标了

对于这多目标里面的每一个目标

“.o” 格式的目标

我们就找它对应的 “.c” 文件编译它

就一行就把它通配完了

用百分号来通配

这样的写法

当然要比写两行要方便一点

还记得我们刚才说了吧

“$<” 取的是它的第一个先决条件

如果它是 “main.o”

找它的第一个先决条件

就是 “main.c”

如果是 “library.o”

找它的第一个先决条件

就是 “library.c”

“$@” 就是它的目标名字 当前目标啊

生成的就是 “main.o”、“library.o”

每一个都是分解开来的当前的目标

就是这个意思

这是我们的静态模式

可以在 makefile 里面写条件判断

基本格式是条件指示

后面跟着一堆命令然后 endif

或者双路分支

条件指示之后跟着命令一串

else 命令一串 endif

就按照这个格式来书写我们的条件判断

就按照这个格式来书写我们的条件判断

可用的条件判断主要是四个

判断两个参数是不是相等

用 ifeq 问它是不是相等

小括号对里写 arg1, arg2

可以不加小括号对

用单引号引 arg1、arg2 也可以

用双引号引 arg1、arg2 也 OK

三种模式都可以

你要想判断两个参数不等那就 ifneq

实际上是 if not equal

如果不等 它的格式和 ifeq 是一样的

还可以判断某个变量是不是已经定义了

就用 ifdef

判断是不是没定义 ifndef 都可以

可以在 makefile 里边写循环

你比如讲

我们在这里面使用shell循环

定义一个伪目标 “rulefor :”

“for filename in `echo $(objs)`; \”

“do \” “rm –f $$filename; \” “done”

这是一个 shell 循环

写的时候要注意

循环是一个 shell 循环

为了保证这多行命令

可以在一个 shell 下面运行

那么你必须把它合并成一个单行的命令

每个单行的命令合并

前面不说了嘛 要用分号来分隔

你觉得写在一行 可读性不佳

那么你就可以用 “\”

在行尾输入一个折行标志

就可以分行写了

特别注意反引号表示执行这个命令

把这个命令执行后的结果

作为我们 for 循环的输入的集合

filename 就从 echo 这个命令做完了以后

出来的结果中去找

当你要在这个循环内部

想删除这个文件的时候

这个 filename 不是你定义的一个变量吗

这是在 shell 中定义的变量

因为在 shell 上面运行这个循环

所以这是 shell 变量

所以你要想在 makefile 引用它

必须使用 $$filename

不能使用 $(filename)

那是访问不到的 必须 $$filename

特别注意这一点

还可以在 makefile 里边使用函数

就像变量一样用 “$()”

它的基本格式是 “$( function arg1,arg2,…)”

有多少个参数 你就接着往下写就完了

写的时候就特别注意

函数名字和函数的参数都封在 “()” 里

函数名字和后面跟着参数列表中间

是有一个空格的

参数列表之间只有逗号没有空格

前面没空格后面也不能有空格

不能有多余的空格

特别注意这一条

有多余的空格

它会认为是参数的一部分

特别要小心

比如讲有一个函数叫 subst

处理子串的一个函数

这是 makefile 里面

已经预定义好的一个函数

我们可以直接用的

它后面带三个参数 from、to、text

什么意思呢 就是把 text

这个文本中的 from 那个字符串

那个子串 替换成 to 那个子串

这个函数做完了

它的结果就是替换后的那个字符串

我们看这样一个例子

我们定义一个逗号变量 comma

然后定义一个 empty 空值变量

它右边什么东西都没有 空值

注意它并不是一个空格 它是个空值

我们还想定义空格

一个空格 我们怎么定义呢

最简单的方式就是 space := $(empty) $(empty)

把它定义成两个空值变量

包着的一个空白

这样它在生成的时候

$(empty) 就什么东西也不生成

但是中间那个空格会保留下来

干嘛用的 你很快就能看到

假设我有一个变量叫 foo

它被定义成了 “a b c”

它可能对应我们三个文件的名字

也可能不是三个文件的名字

但是我想把 “a b c” 这个串

最终给它替换成 “a,b,c” 的模式

那儿你就应该这么写

bar := $(subst $(space),$(comma),$(foo))

就是把这个 foo 这个值 “a b c” 的里边

凡是空格的地方全都用 “,” 给我替换掉

所以出来的结果就是 “a,b,c”

就把它改了

这个就是 makefile 里面的函数的用法

很有趣

有的时候可能会给我们带来一些

非常好玩的结果

基于Linux的C++课程列表:

第一讲 C/C++基本语法元素

-1.1 提纲

--LinuxCPP0101

-1.2 程序设计的基本概念

--LinuxCPP0102

-1.3 简单C/C++程序介绍

--LinuxCPP0103

-1.4 程序设计的基本流程

--LinuxCPP0104

-1.5 基本语法元素

--LinuxCPP0105

-1.6 程序设计风格

--LinuxCPP0106

-1.7 编程实践

--LinuxCPP0107

-第一讲 C/C++基本语法元素--编程实践提交入口

第二讲 程序控制结构

-2.1 提纲

--LinuxCPP0201

-2.2 结构化程序设计基础

--LinuxCPP0202

-2.3 布尔数据

--LinuxCPP0203

-2.4 分支结构

--LinuxCPP0204

-2.5 break语句

--LinuxCPP0205

-2.6 循环结构

--LinuxCPP0206

-2.7 编程实践

--LinuxCPP0207

-第二讲 程序控制结构--编程实践提交入口

第三讲 函数

-3.1 提纲

--LinuxCPP0301

-3.2 函数声明、调用与定义

--LinuxCPP0302

-3.3 函数调用栈框架

--LinuxCPP0303

-3.4 编程实践

--LinuxCPP0304

-第三讲 函数--编程实践提交入口

第四讲 算法

-4.1 提纲

--LinuxCPP0401

-4.2 算法概念与特征

--LinuxCPP0402

-4.3 算法描述

--LinuxCPP0403

-4.4 算法设计与实现

--LinuxCPP0404

-4.5 递归算法(一)

--LinuxCPP0405

-4.6 递归算法(二)

--LinuxCPP0406

-4.7 容错与计算复杂度

--LinuxCPP0407

-4.8 编程实践

--LinuxCPP0408

-第四讲 算法--编程实践提交入口

第五讲 程序组织与开发方法

-5.1 提纲

--LinuxCPP0501

-5.2 库与接口

--LinuxCPP0502

-5.3 随机数库(一)

--LinuxCPP0503

-5.4 随机数库(二)

--LinuxCPP0504

-5.5 作用域与生存期

--LinuxCPP0505

-5.6 典型软件开发流程(一)

--LinuxCPP0506

-5.7 典型软件开发流程(二)

--LinuxCPP0507

-5.8 编程实践

--LinuxCPP0508

-第五讲 程序组织与开发方法--编程实践提交入口

第六讲 复合数据类型

-6.1 提纲

--LinuxCPP0601

-6.2 字符

--LinuxCPP0602

-6.3 数组(一)

--LinuxCPP0603

-6.4 数组(二)

--LinuxCPP0604

-6.5 结构体

--LinuxCPP0605

-6.6 编程实践

--LinuxCPP0606

-第六讲 复合数据类型--编程实践提交入口

第七讲 指针与引用

-7.1 提纲

--LinuxCPP0701

-7.2 指针基本概念

--LinuxCPP0702

-7.3 指针与函数

--LinuxCPP0703

-7.4 指针与复合数据类型(一)

--LinuxCPP0704

-7.5 指针与复合数据类型(二)

--LinuxCPP0705

-7.6 字符串

--LinuxCPP0706

-7.7 动态存储管理(一)

--LinuxCPP0707

-7.8 动态存储管理(二)

--LinuxCPP0708

-7.9 引用

--LinuxCPP0709

-7.10 编程实践

--LinuxCPP0710

-第七讲 指针与引用--编程实践提交入口

第八讲 链表与程序抽象

-8.1 提纲

--LinuxCPP0801

-8.2 数据抽象(一)

--LinuxCPP0802

-8.3 数据抽象(二)

--LinuxCPP0803

-8.4 链表(一)

--LinuxCPP0804

-8.5 链表(二)

--LinuxCPP0805

-8.6 链表(三)

--LinuxCPP0806

-8.7 链表(四)

--LinuxCPP0807

-8.8 函数指针(一)

--LinuxCPP0808

-8.9 函数指针(二)

--LinuxCPP0809

-8.10 抽象链表(一)

--LinuxCPP0810

-8.11 抽象链表(二)

--LinuxCPP0811

-8.12 编程实践

--LinuxCPP0812

-第八讲 链表与程序抽象--编程实践提交入口

第九讲 类与对象

-9.1 提纲

--LinuxCPP0901

-9.2 程序抽象与面向对象

--LinuxCPP0902

-9.3 类类型

--LinuxCPP0903

-9.4 对象(一)

--LinuxCPP0904

-9.5 对象(二)

--LinuxCPP0905

-9.6 类与对象的成员(一)

--LinuxCPP0906

-9.7 类与对象的成员(二)

--LinuxCPP0907

-9.8 类与对象的成员(三)

--LinuxCPP0908

-9.9 继承(一)

--LinuxCPP0909

-9.10 继承(二)

--LinuxCPP0910

-9.11 继承(三)

--LinuxCPP0911

-9.12 多态(一)

--LinuxCPP0912

-9.13 多态(二)

--LinuxCPP0913

-9.14 编程实践

--LinuxCPP0914

-第九讲 类与对象--编程实践提交入口

第十讲 操作符重载

-10.1 提纲

--LinuxCPP1001

-10.2 四则运算符重载(一)

--LinuxCPP1002

-10.3 四则运算符重载(二)

--LinuxCPP1003

-10.4 关系与下标操作符重载

--LinuxCPP1004

-10.5 赋值操作符重载(一)

--LinuxCPP1005

-10.6 赋值操作符重载(二)

--LinuxCPP1006

-10.7 赋值操作符重载(三)

--LinuxCPP1007

-10.8 赋值操作符重载(四)

--LinuxCPP1008

-10.9 赋值操作符重载(五)

--LinuxCPP1009

-10.10 流操作符重载(一)

--LinuxCPP1010

-10.11 流操作符重载(二)

--LinuxCPP1011

-10.12 流操作符重载(三)

--LinuxCPP1012

-10.13 操作符重载总结

--LinuxCPP1013

-10.14 编程实践

--LinuxCPP1014

-第十讲 操作符重载--编程实践提交入口

第十一讲 泛型编程

-11.1 提纲

--LinuxCPP1101

-11.2 泛型编程概览

--LinuxCPP1102

-11.3 异常处理机制(一)

--LinuxCPP1103

-11.4 异常处理机制(二)

--LinuxCPP1104

-11.5 运行期型式信息(一)

--LinuxCPP1105

-11.6 运行期型式信息(二)

--LinuxCPP1106

-11.7 模板与型式参数化

--LinuxCPP1107

-11.8 题外话:术语翻译

--LinuxCPP1108

-11.9 泛型编程实践(一)

--LinuxCPP1109

-11.10 泛型编程实践(二)

--LinuxCPP1110

-11.11 泛型编程实践(三)

--LinuxCPP1111

-11.12 泛型编程实践(四)

--LinuxCPP1112

-11.13 泛型编程实践(五)

--LinuxCPP1113

-11.14 泛型编程实践(六)

--LinuxCPP1114

-11.15 泛型编程实践(七)

--LinuxCPP1115

-11.16 泛型编程实践(八)

--LinuxCPP1116

-11.17 泛型编程实践(九)

--LinuxCPP1117

-11.18 泛型编程实践(十)

--LinuxCPP1118

-11.19 编程实践

--LinuxCPP1119

-第十一讲 泛型编程--编程实践提交入口

第十二讲 Linux系统编程基础

-12.1 提纲

--LinuxCPP1201

-12.2 程序执行环境(一)

--LinuxCPP1202

-12.3 程序执行环境(二)

--LinuxCPP1203

-12.4 程序执行环境(三)

--LinuxCPP1204

-12.5 程序执行环境(四)

--LinuxCPP1205

-12.6 输入输出(一)

--LinuxCPP1206

-12.7 输入输出(二)

--LinuxCPP1207

-12.8 文件系统

--LinuxCPP1208

-12.9 设备

--LinuxCPP1209

-12.10 库(一)

--LinuxCPP1210

-12.11 库(二)

--LinuxCPP1211

-12.12 makefile文件(一)

--LinuxCPP1212

-12.13 makefile文件(二)

--LinuxCPP1213

-12.14 makefile文件(三)

--LinuxCPP1214

-12.15 编程实践

--LinuxCPP1215

-第十二讲 Linux系统编程基础--编程实践提交入口

第十三讲 进程编程

-13.01 提纲

--LinuxCPP1301

-13.02 进程基本概念

--LinuxCPP1302

-13.03 信号

--LinuxCPP1303

-13.04 进程管理(一)

--LinuxCPP1304

-13.05 进程管理(二)

--LinuxCPP1305

-13.06 进程管理(三)

--LinuxCPP1306

-13.07 进程间通信(一)

--LinuxCPP1307

-13.08 进程间通信(二)

--LinuxCPP1308

-13.09 进程间通信(三)

--LinuxCPP1309

-13.10 进程间通信(四)

--LinuxCPP1310

-13.11 进程池

--LinuxCPP1311

-13.12 编程实践

--LinuxCPP1312

-第十三讲 进程编程--编程实践提交入口

第十四讲 线程编程

-14.1 提纲

--LinuxCPP1401

-14.2 线程基本概念

--LinuxCPP1402

-14.3 线程管理(一)

--LinuxCPP1403

-14.4 线程管理(二)

--LinuxCPP1404

-14.5 线程管理(三)

--LinuxCPP1405

-14.6 线程管理(四)

--LinuxCPP1406

-14.7 线程同步机制(一)

--LinuxCPP1407

-14.8 线程同步机制(二)

--LinuxCPP1408

-14.9 C++11线程库(一)

--LinuxCPP1409

-14.10 C++11线程库(二)

--LinuxCPP1410

-14.11 C++11线程库(三)

--LinuxCPP1411

-14.12 C++11线程库(四)

--LinuxCPP1412

-14.13 C++11线程库(五)

--LinuxCPP1413

-14.14 编程实践

--LinuxCPP1414

-第十四讲 线程编程--编程实践提交入口

第十五讲 网络编程

-15.1 提纲

--LinuxCPP1501

-15.2 Internet网络协议

--LinuxCPP1502

-15.3 套接字(一)

--LinuxCPP1503

-15.4 套接字(二)

--LinuxCPP1504

-15.5 编程实践

--LinuxCPP1505

-第十五讲 网络编程--编程实践提交入口

课程文档

-课程PDF文件

LinuxCPP1214笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。