前情提要

上一篇《编译入门》讲了变成的基本问题。如果源文件只有一个,就如之前的例子,那么用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的更多相关文章

  1. 第2课 - 初识makefile的结构

    第2课 - 初识makefile的结构 1. makefile 的意义 (1)makefile 用于定义源文件之间的依赖关系 (在阅读开源软件源码时,可通过Makefile掌握源码中各个文件之间的关系 ...

  2. Makefile笔记之二------make的递归执行

    1.make的递归过程指的是: 在Makefile中使用"make"作为一个命令来执行本身或者其它makefile文件的过程. 2.递归的意义: 当前目录下存在一个"su ...

  3. C++学习笔记24:makefile文件

    makefile make命令:负责c/c++程序编译与链接 make根据指定命令进行建构 建构规则文件:GNUmakefile , makefile,Makefile makefile 文件格式 m ...

  4. Makefile笔记

    一个简单的Makefile描述规则组成: TARGET...:PREREQUISITES... COMMANDS... ... target:规则的目标.通常是程序中间或者最后要生成的文件名,也可以是 ...

  5. makefile笔记4 - makefile命令

    每条规则中的命令和操作系统 Shell 的命令行是一致的. make 会一按顺序一条一条的执行命令,每条命令的开头必须以[Tab]键开头,除非,命令是紧跟在依赖规则后面的分号后的. 在命令行之间中的空 ...

  6. 工程管理之makefile与自动创建makefile文件过程

    (风雪之隅 http://www.laruence.com/2009/11/18/1154.html) Linux Makefile自动编译和链接使用的环境 想知道到Linux Makefile系统的 ...

  7. makefile中引用其他makefile方法

    在Makefile中引用其他Makefile文件的方法是,使用inclue   filename.mk

  8. Storm学习笔记 - Storm初识

    Storm学习笔记 - Storm初识 1. Strom是什么? Storm是一个开源免费的分布式计算框架,可以实时处理大量的数据流. 2. Storm的特点 高性能,低延迟. 分布式:可解决数据量大 ...

  9. LevelDB学习笔记 (1):初识LevelDB

    LevelDB学习笔记 (1):初识LevelDB 1. 写在前面 1.1 什么是levelDB LevelDB就是一个由Google开源的高效的单机Key/Value存储系统,该存储系统提供了Key ...

随机推荐

  1. JSR107缓存规范

    Java Caching定义了5个核心接口,分别是CachingProvider, CacheManager, Cache, Entry 和 Expiry. CachingProvider定义了创建. ...

  2. Lua完全自学手册(图文教程)

    Programming in Lua程序设计   http://book.luaer.cn/ Lua完全自学手册(图文教程) https://edu.aliyun.com/course/506/les ...

  3. Creed_颓知乎

    题目背景 二轮省选前的一个最后周,Creed_还在颓知乎. 突然,她看到一个有趣的回答. 紧接着,Creed_点开了评论区,又看到了一个有趣的评论. Creed_想了一下,发现自己并不会,于是她又顺着 ...

  4. max of 直线划平面

    在一个无限延伸平面上有一个圆和n条直线,这些直线中每一条都在一个圆内,并且同其他所有的直线相交,假设没有3条直线相交于一点,试问这些直线最多将圆分成多少区域. Input 第一行包含一个整数T,(0& ...

  5. vue整理

    安装 vue ui axios import axios from 'axios' // let curWwwPath = window.document.location.href // let p ...

  6. Struts 2中如何解决中文乱码问题?

    在配置文件中定义如下常量值配置: <constant name=”struts.i18n.encoding” value=”UTF-8”/> 注意:只能解决post请求的乱码问题,针对ge ...

  7. QT-简易视频播放器

    一直没找到理由去学一下QT,由于工作原因之后的工作内容会用到QT,于是这两天摸索了下:早上临时决定先做个视频播放器玩一下,于是先用qml发现不会用,无果,于是放弃了使用qml,等之后系统的看一下Jav ...

  8. 微信小程序实战练习(仿五洲到家微信版)

    github地址(欢迎star):https://github.com/xiaobinwu/dj 版本:0.15.152900(暂未升级原因:升级后需要图片无法本地引用,必须使用image或是远程路径 ...

  9. week4_1

    ---恢复内容开始--- _________________________________列表生成式_____________________ a = [a*2 for a in range(10) ...

  10. Python爬虫入门之Urllib库的高级用法

    1.设置Headers 有些网站不会同意程序直接用上面的方式进行访问,如果识别有问题,那么站点根本不会响应,所以为了完全模拟浏览器的工作,我们需要设置一些Headers 的属性. 首先,打开我们的浏览 ...