makefile笔记1 - 初识makefile
前情提要
上一篇《编译入门》讲了变成的基本问题。如果源文件只有一个,就如之前的例子,那么用gcc命令直接编译就可以了。但是很多实际的工程用到的源文件都是相当多的,这时候用命令一个个编译是很不现实的。所以需要一个自动化编译系统来做这件事情,那就是make和makefile了。
make和makefile介绍
一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile 定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 makefile 就像一个 Shell 脚本一样,其中也可以执行操作系统的命令。
make 是一个命令工具,是一个解释makefile 中指令的命令工具,一般来说,大多数的 IDE 都有这个命令,比如:Delphi 的make,Visual C++的 nmake,Linux 下 GNU 的 make。可见,makefile 都成为了一种在工程方面的编译方法。
make和makefile的示例:它们是如何工作的
我们的工程有 8 个 C 文件,和 3 个头文件,我们要写一个 Makefile 来告诉 make 命令如何编译和链接这几个文件。我们要写一个 Makefile 来告诉 make 命令如何编译和链接这几个文件。我们的规则是:
1. 如果这个工程没有编译过,那么我们的所有 C 文件都要编译并被链接。
2. 如果这个工程的某几个 C 文件被修改,那么我们只编译被修改的 C 文件,并链接目标程序。
3. 如果这个工程的头文件被改变了,那么我们需要编译引用了这几个头文件的 C 文件,并链接目标程序。
在讲述这个 Makefile 之前,还是让我们先来粗略地看一看 Makefile 的规则。
target ... : prerequisites ...
command
...
...
target 也就是一个目标文件,可以是 Object File,也可以是执行文件。还可以是一个标签(Label),对于标签这种特性,在后续的“伪目标”章节中会有叙述。
prerequisites 就是,要生成那个 target 所需要的文件或是目标。
command 也就是 make 需要执行的命令。(任意的 Shell 命令)
这是一个文件的依赖关系,也就是说,target这一个或多个的目标文件依赖于prerequisites中的文件,其生成规则定义在command中。说白一点就是说,prerequisites中如果有一个以上的文件比 target 文件要新的话, command 所定义的命令就会被执行。
这就是 Makefile 的规则。也就是 Makefile 中最核心的内容。
以下是makefile的代码。
edit : main.o kbd.o command.o display.o insert.o search.o files.o utils.o
cc -o edit main.o kbd.o command.o display.o insert.o search.o files.o utils.o
main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h buffer.h
cc -c display.c
insert.o : insert.c defs.h buffer.h
cc -c insert.c
search.o : search.c defs.h buffer.h
cc -c search.c
files.o : files.c defs.h buffer.h command.h
cc -c files.c
utils.o : utils.c defs.h
cc -c utils.c
clean :
rm edit main.o kbd.o command.o display.o insert.o search.o files.o utils.o
我们可以把这个内容保存在文件为“Makefile”或“makefile”的文件中,然后在该目录下直接输入命令“make”就可以生成执行文件 edit。
如果要删除执行文件和所有的中间目标文件,那么,只要简单地执行一下“make clean”就可以了。
在这个 makefile 中,目标文件(target)包含:执行文件 edit 和中间目标文件(*.o),依赖文件(prerequisites)就是冒号后面的那些 .c 文件和 .h 文件。每一个 .o 文件都有一组依赖文件,而这些 .o 文件又是执行文件 edit 的依赖文件。依赖关系的实质上就是说明了目标文件是由哪些文件生成的,换言之,目标文件是哪些文件更新的。
在定义好依赖关系后,后续的那一行定义了如何生成目标文件的操作系统命令,一定要以一个 Tab 键作为开头。记住, make 并不管命令是怎么工作的,他只管执行所定义的命令。 make会比较 targets 文件和 prerequisites 文件的修改日期,如果 prerequisites 文件的日期要比 targets 文件的日期要新,或者 target 不存在的话,那么, make 就会执行后续定义的命令。
这里要说明一点的是, clean 不是一个文件,它只不过是一个动作名字,有点像 C 语言中的lable 一样,其冒号后什么也没有,那么, make 就不会自动去找文件的依赖性,也就不会自动执行其后所定义的命令。要执行其后的命令,就要在 make 命令后明显得指出这个 lable的名字。这样的方法非常有用,我们可以在一个 makefile 中定义不用的编译或是和编译无关的命令,比如程序的打包,程序的备份,等等。
上面是makfile的核心,但还有很多很多其他的细节,慢慢道来。
参考文献:
跟我一起写makefile
makefile笔记1 - 初识makefile的更多相关文章
- 第2课 - 初识makefile的结构
第2课 - 初识makefile的结构 1. makefile 的意义 (1)makefile 用于定义源文件之间的依赖关系 (在阅读开源软件源码时,可通过Makefile掌握源码中各个文件之间的关系 ...
- Makefile笔记之二------make的递归执行
1.make的递归过程指的是: 在Makefile中使用"make"作为一个命令来执行本身或者其它makefile文件的过程. 2.递归的意义: 当前目录下存在一个"su ...
- C++学习笔记24:makefile文件
makefile make命令:负责c/c++程序编译与链接 make根据指定命令进行建构 建构规则文件:GNUmakefile , makefile,Makefile makefile 文件格式 m ...
- Makefile笔记
一个简单的Makefile描述规则组成: TARGET...:PREREQUISITES... COMMANDS... ... target:规则的目标.通常是程序中间或者最后要生成的文件名,也可以是 ...
- makefile笔记4 - makefile命令
每条规则中的命令和操作系统 Shell 的命令行是一致的. make 会一按顺序一条一条的执行命令,每条命令的开头必须以[Tab]键开头,除非,命令是紧跟在依赖规则后面的分号后的. 在命令行之间中的空 ...
- 工程管理之makefile与自动创建makefile文件过程
(风雪之隅 http://www.laruence.com/2009/11/18/1154.html) Linux Makefile自动编译和链接使用的环境 想知道到Linux Makefile系统的 ...
- makefile中引用其他makefile方法
在Makefile中引用其他Makefile文件的方法是,使用inclue filename.mk
- Storm学习笔记 - Storm初识
Storm学习笔记 - Storm初识 1. Strom是什么? Storm是一个开源免费的分布式计算框架,可以实时处理大量的数据流. 2. Storm的特点 高性能,低延迟. 分布式:可解决数据量大 ...
- LevelDB学习笔记 (1):初识LevelDB
LevelDB学习笔记 (1):初识LevelDB 1. 写在前面 1.1 什么是levelDB LevelDB就是一个由Google开源的高效的单机Key/Value存储系统,该存储系统提供了Key ...
随机推荐
- vs2015编译caffe
有些时候,需要在python3的环境下import caffe,需要用vs2015在python3的环境下,编译pycaffe. microsoft的windows版本的caffe,依赖的库Nuget ...
- POJ-2796 & 2019南昌邀请赛网络赛 I. 区间最大min*sum
http://poj.org/problem?id=2796 https://nanti.jisuanke.com/t/38228 背景 给定一个序列,对于任意区间,min表示区间中最小的数,sum表 ...
- scikit_learn lasso详解
Lasso 回归 l1 正则化 The Lasso 是估计稀疏系数的线性模型. 它在一些情况下是有用的,因为它倾向于使用具有较少参数值的情况,有效地减少给定解决方案所依赖变量的数量. 因此,Lasso ...
- 创建ajax的步骤
第1步:创建XMLHttpRequest对象,也就是创建一个异步调用对象. 第2步:创建一个新的HTTP请求,并指定该HTTP请求的方法.URL以及验证信息. 第3步:设置响应HTTP状态变化的函数. ...
- linux添加本地yum源
增加一块硬盘 然后格式化成btrfs格式的文件 mkfs.btrfs /dev/sde 永久挂载 echo "/dev/sde /mnt btrfs defaults 0 0" & ...
- 【javascript】数据类型中的一些小知识点
1. undefined 和 null undefined是一个变量而不是一个关键字,所以可以被重新赋值.为了避免歧义,一般推荐用void 0 来获取undefined: null是一个关键字,所以可 ...
- 利用pom配置实现静态文件拷贝
java项目有时候需要将一些静态文件拷贝到生成的test-class文件夹或者其他地方,虽然手动拷贝可以做到,但是很麻烦.今天主要讲解如何利用pom.xml进行动态的拷贝. 具体的配置信息如下,在de ...
- 【调试基础】Part 4 保护模式
保护模式.虚拟内存.权限
- PROJ.4学习——坐标系转换
PROJ.4学习——坐标系转换 前言 PROJ可以做任从最简单的投影到许多参考数据非常复杂的转换.PROJ最初是作为地图投影工具开发的,但随着时间的推移,它已经发展成为一个强大的通用坐标转换引擎,可以 ...
- unity中EventTrigger组件的应用
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using D ...