Makefile是由一系列的rule规则组成,这些rule都遵循以下形式:

target ... : prerequisites ...command......

target(目标)

一般来说是需要生成的程序(模块)的名字,也可以是要执行的动作的名字,这种情况叫做(Phony Target)

prerequisites(依赖)

用于生成target,一个target一般会依赖于多个文件

command(命令)

由make来执行的动作,一个规则下可以包含多个command,需要注意的一点是command前必须有一个tab用于区分command所在的行与Makefile的其他行

rule

表明了如何(command)以及何时(prerequisites)生成指定文件(target)。一旦prerequisites新加入到工程或者更新后,则会调用command来生成target。

rule的形式是以prerequisites为原料并通过调用command来生成target文件。不过并不是所有的target都是文件,在这种情况下就不需要prerequisites了(如make clean)。

Makefile可能会包含除了rule以外的其他文本,不过再复杂的Makefile,rule都是其核心部分。

以下有个简单的Makefile,我们可以对他展开分析:

edit : main.o kdb.o command.o display.o \insert.o search.o files.o utils.occ -o edit main.o kbd.o command.o display.o \insert.o search.o files.o utils.omain.o : main.c defs.hcc -c main.c
kbd.o : kbd.c defs.h command.hcc -c kbd.c
command.o : command.c defs.h command.hcc -c command.c
display.o : display.c defs.h buffer.hcc -c display.c
insert.o : insert.c defs.h buffer.hcc -c insert.c
search.o : search.c defs.h buffer.hcc -c search.c
files.o : files.c defs.h buffer.h command.hcc -c files.c
utils.o : utils.c defs.hcc -c utiles.cclean :rm edit main.o kbd.o command.o display.o \insert.o search.o files.o utils.o

在该Makefile中,

  • target                 有edit,main.o等各种“.o”文件,最后还有clean
  • prerequisites       有main.c等各种“.c”文件,defs.h等各种“.h”文件,以及main.o等各种“.o”文件
  • command            有cc -o ..., cc -c ...等命令

当prerequisites文件被改变的时候,会重新调用command来生成新的target。command表明该如何由prerequisites生成新的target文件。但是实际上make并不知道command所做的是什么动作,因为command都是shell命令,最终会由shell调用,因此理论上command可以是任何的shell命令。

在Makefile中,clean不是一个文件,而仅仅是一个动作的名字。由于clean不是其他target的prerequisites,因此除非你手动指定make来调用clean(make clean),否则它不会被调用。另外,由于clean也没有任何的prerequisites,因此调用clean只会执行到其下方的command,这种只为执行某种动作的target叫做phony target。

make如何处理Makefile

对于上方的那个简单Makefile,当我们敲make的时候,make会首先确定Makefile的goal(目标),默认goal就是该Makefile文件中第一个不包含‘.’前缀的target,即edit。

但是make不会立即去执行edit下的command,因为它的rule规定了edit依赖于它的.o,而.o文件的rule又规定了它们依赖于.h,.c文件,因此会先由.c文件先生存.o文件,后再由.o文件生成edit。

clean这种不在edit分支内的target则需要手动执行(make clean)。

command只在特定情况下才会被执行:

  • target文件不存在
  • prerequisites文件时间比target文件新

使Makefile更简洁

1.使用变量

上方的Makefile在edit的prerequisites处列出来一串.o文件,并且需要在command中再次列出来。这种长列表的重复会带来维护艰难的问题。因此可以用变量来取代长列表。变量允许一次定义,多次调用。

对于上方的.o长串,可以写成如下方式:

objects = main.o kbd.o command.o display.o \insert.o search.o files.o utils.o

在需要调用的时候写成“$(objects)”这种形式

上方Makefile可以简化成

objects = main.o kbd.o command.o display.o \insert.o search.o files.o utils.oedit : $(objects)cc -o edit $(objects)main.o : main.c defs.hcc -c main.c
kbd.o : kbd.c defs.h command.hcc -c kbd.c
command.o : command.c defs.h command.hcc -c command.c
display.o : display.c defs.h buffer.hcc -c display.c
insert.o : insert.c defs.h buffer.hcc -c insert.c
search.o : search.c defs.h buffer.hcc -c search.c
files.o : files.c defs.h buffer.h command.hcc -c files.c
utils.o : utils.c defs.hcc -c utils.c
clean :rm edit $(objects)

2.让make推导command

make有一条隐性规则:由.c文件生成相应文件名的.o文件所用的command “cc -c”可以省略,因为make可以自动识别并调用该command。

.c文件也可以省略,因为make会自动加载.o相应的.c文件到prerequisites。

因此,Makefile还可以简化成以下形式:

objects = main.o kbd.o command.o display.o \insert.o search.o files.o utils.oedit : $(objects)cc -o edit $(objects)main.o : defs.h
kbd.o : defs.h command.h
command.o : defs.h command.h
display.o : defs.h command.h
insert.o : defs.h buffer.h
search.o : defs.h buffer.h
files.o : defs.h buffer.h command.h
utils.o : defs.h.PHOMY : clean
clean :rm edit $(objects)

3.multi target one prerequisites

objects = main.o kbd.o command.o display.o \insert.o search.o files.o utils.oedit : $(objects)cc -o edit $(objects)$(objects) : defs.h
kbd.o command.o files.o : command.h
display.o insert.o search.o files.o : buffer.h

但是这种方式相对于上面的one target multi prerequisite 的方式没那么直观。可以根据自己喜好选择。

clean 的方式

clean有两种写法:

1.

clean :rm edit $(objects)

一般我们都采用这种方式,但是这会引起一个问题,如果存在一个clean文件的话,那么make clean会被混淆,以实际存在的clean文件为target来执行,而不会去rm。所以下面这种方式就是避免了这种问题而存在的。

2.

.PHONY : cleanclean :rm edit $(objects)

.PHONY声明了clean是一个虚拟的目标,并不包含实际文件,当执行make clean时就会把clean当做虚拟目标来执行,不会影响实际存在的文件。

另外需要注意的是,不要把clean写在Makefile的开头,因为我们一般不会把clean当做Makefile的默认goal

GNU Make chapter 2 —— Makefile 介绍相关推荐

  1. Makefile介绍

    Makefile 值得一提的是,在Makefile中的命令,必须要以[Tab]键开始. 什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了 ...

  2. Visual Stdio C++ 编译器 编译 (GSL) GNU Scientific Library 的方法介绍(5)

    编译好的版本放到了这里,包括静态库和动态库.大家直接用吧. http://download.csdn.net/detail/liyuanbhu/9618257 Visual Stdio C++ 编译器 ...

  3. Visual Stdio C++ 编译器 编译 (GSL) GNU Scientific Library 的方法介绍(8)

    编译好的版本放到了这里,包括静态库和动态库.大家直接用吧. http://download.csdn.net/detail/liyuanbhu/9618257 Visual Stdio C++ 编译器 ...

  4. Visual Stdio C++ 编译器 编译 (GSL) GNU Scientific Library 的方法介绍(1)

    编译好的版本放到了这里,包括静态库和动态库.大家直接用吧. http://download.csdn.net/detail/liyuanbhu/9618257 Visual Stdio C++ 编译器 ...

  5. GNU toolchain —— (一)介绍

    GNU工具链(GNU toolchain)是一个包含了由GNU项目所产生的各种编程工具的集合.这些工具形成了一条工具链(串行使用的一组工具),用于开发应用程序和操作系统. GNU工具链中包含的项目有: ...

  6. Makefile文件:Makefile介绍

    本文介绍Makefile的一些基本概念以及简单的用法.本文所用的编译器是Hightec tricore v4.9.1.0. 文章目录 1 Makefile的作用 2 Makefile的规则 3 一个简 ...

  7. Linux操作系统中的make及makefile介绍

    本文主要介绍 Linux 操作系统中 make 及 makefile 的相关知识. 1 What make 是一个在软件开发过程中所使用的工具程序(utility software),通过读取&quo ...

  8. Makefile_03:Makefile介绍(作用、例子、原理)

    一.Makefile 作用 Make 命令执行时,需要一个 Makefile 文件,以告诉 make 命令需要怎么样的去编译和链接程序.make 命令会自动智能地根据当前的文件修改的情况来确定哪些文件 ...

  9. Linux学习:makefile介绍

    一.为什么使用 makefile? makefile 带来的好处就是"自动化编译",一旦写好,只需要一个 make 命令, 整个工程完全自动编译, 极大的提高了软件开发的效率. 同 ...

最新文章

  1. 40个Java多线程问题总结
  2. element table固定表头,表的高度自适应解决方法
  3. xml 属性value换行显示_python 标准库之xml.etree.ElementTree
  4. Server Hard drive mode
  5. git version是什么软件_Deepin 15.11 安装 ZoneMinder 视频监控软件
  6. 2021跨境电商独立站将喷发式增长?你知道怎样运营独立站吗?
  7. Bailian2910 提取数字【DFA】
  8. AHCI和IDE区别,和在目前系统中设置 AHCI - 摘自网络
  9. 项目管理学习流程图-ITTO-PMP
  10. scikit-learn中交叉验证及其用于参数选择、模型选择、特征选择的例子
  11. 对五层网络协议体系结构的理解
  12. coalesce函数的用法
  13. 什么?!NEON还要优化?
  14. 【附源码】Python计算机毕业设计社区志愿者管理系统
  15. python分析链家二手房信息----数据分析实战(一)
  16. Geohash应用——附近乡镇信息挖掘(提升检索召回与准确)
  17. 智能锁方案PCBA原理图PCB单片机开发板源码wifi远程开锁。 提供全套技术资料,包括原理图,PCB图,程序源码,bom清单,说明书等
  18. mac画图工具 OmniGraffle (二)对象的控制
  19. 使用install shield制作安装程序问题集锦
  20. 关系数据库主码、超码、候选码、主码(键)

热门文章

  1. 保持dropdownlist选中值
  2. Linux 命令集锦
  3. sizeof 操作符详解
  4. asp.net中DataGrid性能测试
  5. C语言extern关键字定义外部变量--Redis源码extern使用
  6. 【VirtualBox】VirtualBox使用现有的虚拟盘文件(如VHD)创建虚拟机时,报错:打开虚拟硬盘失败,“UUID already exist”的解决方法
  7. 计算机辅助焊接过程控制,重型车辆计算机辅助焊接工艺自动设计系统.pdf
  8. php数据 文本_php直接调用文本文件内容
  9. xwpftemplate的时间设置_java poi设置生成的word的图片为上下型环绕以及其位置
  10. python中符号计算输出数学_Python科学计算与数据处理—符号运算库.doc