[make]makefile使用积累
【注】:文中所指手册皆为GNU make Version 4.1
1、make的一般特性
1.1、Makefiles的构成
Makefiles包含五种元素: 显式规则(explicit rules), 隐式规则(implicit rules), 变量定义(variable definitions),指令(directives), 和注释(comments)。其中没有提到函数,函数应该归于变量之中吧。
- 显式规则:指导何时和怎样更新一个或多个文件(targets)。
- 显式规则
- 隐式规则
1.2、make如何读入makefile【手册3.7节】
GNU通过两步完全分离的步骤来完成这项工作。(其实我觉得是三步,因为第一步明显地分成两个阶段)第一阶段(read-in),make读所有相关的makefile(包括include makefiles),建立起其中的变量和规则(makefile就是由变量和规则组成的?);然后构建target和prerequisites的依赖关系;第二阶段(target-update),make利用前一步整理的关系决定哪个target需要重建,从而调用相应的规则。
make的这种“两步”工作方式决定了变量和函数的两种不同的展开方式:立即展开、延迟展开。立即展开是在第一阶段前期做的,(个人理解就是边读边展开);延迟展开是在第一阶段后期甚至第二阶段才做的(个人理解是在所有makefile都读入以后,整理各变量和规则依赖关系时展开)
变量赋值
- immediate = deferred
- immediate ?= deferred
- immediate := immediate
- immediate ::= immediate
- immediate += deferred or immediate
- immediate != immediate
变量名都是理解展开的,变量值则分情况了。
规则定义(规则都是一种展开方式,不管它是什么形式的)
immediate : immediate ; deferred
deferred
2、变量
一般规则:
- 变量是一个字符序列,这个序列绝对不能包含‘:’, ‘#’, ‘=’,和空白这四类字符,除数字、字母、下划线的自它字符也要小心使用;
- 变量名区分大小写;
- 变量引用使用变量引用符号'$'加圆括号或大括号。如‘$(foo)’ or ‘${foo}’都是对foo变量的引用;
- 如果变量名只有一个字符,引用变量时括号可以省去,譬如$x,但官方不建议这样做,这个做法是保留给自动变量使用的;
两种变量:递归变量、简单变量 (非常重要)
- 递归展开变量是用“=”符号或define指令定义的变量;
- 简单展开变量是用‘:=’ or ‘::=’符号定义的变量,这两种符号对GNU是一样的,但POSIX只认‘::=’
- 简单变量在定义时就对它的值进行展开,而递归变量只有在需要展开时才对它的值进行展开;
- 递归变量的优点在于它可以引用后面定义的变量,因为它的展开在make读makefile的第二阶段
【例1】:递归变量与简单变量定义
3、规则
3.1、规则一般特性:
targets(目标) ... : prerequisites (依赖)... ; recipes
recipes
...
- recipe在prerequisites的下一行以tab键开始(tab键可以使用.RECIPEPREFIX变量的第一个值代替,【手册6.14节】);
- recipe还可以紧跟在prerequisites的同一行,以“;”分隔。这个方法在定义“空recipe”时非常有效;
- 规则除了用于编译程序,还能用来干其它事情,见【手册2.7节】;
3.1、规则分类
- 规则分显式规则、隐式规则;
- 隐式规则又分为内建隐式规则(built-in implicit rules)和自定义隐式规则,又叫模式规则(pattern rules)【手册10】;
- 自定义隐式规则还有一种方法叫后缀规则(Suffix rules)【手册10】;
- 和模式规则相比,后缀规则有使用限制,但它是老技术,使用它可以保留兼容性【手册10】;
- 隐式规则可以链式调用(譬如:a.c -> a.y -> a.o)【手册10】;
3.3、显式规则
3.4、隐式规则
- 很多文件的remake工作都是标准的,依照惯例的,所以我们可以不用为这些文件的更新制定规则,这就是隐式规则;
- 我们想要target使用隐式规则,唯一要做的就是不要给target指定recipe(空recipe规则)甚至不给target写规则;
- 事实上,很多时候我们要做的是阻止隐式规则发挥作用;
规则做什么
规则还能做什么
3.2、Prerequisites
4、符号
4.1、@
@出现在recipe的最前面用于关闭recipe回显,见【手册5.2节】
$@
4.2、$
变量的引用符号
4.3、通配符
- 跟Bourne Shell一样,make的通配符也是‘*’, ‘?’ and ‘[...]’(...表示[]中的内容很丰富);
- 规则中的通配符:targets和prerequisites中的通配符展开是由make来完成的;recipes中的通配符展开则是由shell来完成的;
- 变量中的通配符make是不展开的;
- 但含有通配符的变量用在规则中,变量和通配符都会被展开;
- 要让变量中的通配符生效,可以使用wildcard函数;
- 文件名中的通配符'*',譬如*.o
- 代表匹配所有的“o”文件;
- 如果搜索目录里没有任何一个“o"文件,则“*.o”代表它的字面意思;
- 如果搜索目录里也没有“*.o”文件(几乎是一定的),则make可能会报错;
- wildcard函数
- 可以用于make不进行通配符展开的地方,譬如变量和函数参数;
- 跟直接使用通配符相比,它也有优势,当没有匹配时它输出空,不会出现使用字面含义的情况;
【4.3例1】
objects = *.o
解释: 由于通配符是在变量的值中,所以这个变量就是字面的意思,而不是代表所有的“o”文件,但是,如果这个变量出现在prerequisites,“*”就是通配符。
【4.3例2】
objects := $(wildcard *.o)
4、依赖
依赖类型
[make]makefile使用积累的更多相关文章
- 【转】Linux makefile 教程 非常详细,且易懂
From: http://blog.csdn.net/liang13664759/article/details/1771246 最近在学习Linux下的C编程,买了一本叫<Linux环境下的C ...
- Makefile经典教程(掌握这些足够)
makefile很重要 什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员 ...
- Linux makefile 教程 非常详细,且易懂
最近在学习Linux下的C编程,买了一本叫<Linux环境下的C编程指南>读到makefile就越看越迷糊,可能是我的理解能不行. 于是google到了以下这篇文章.通俗易懂.然后把它贴出 ...
- 【原+转】用CMake代替makefile进行跨平台交叉编译
在开始介绍如何使用CMake编译跨平台的静态库之前,先讲讲我在没有使用CMake之前所趟过的坑.因为很多开源的程序,比如png,都是自带编译脚本的.我们可以使用下列脚本来进行编译: ./configu ...
- [转] Makefile经典教程(掌握这些足够)
目录(?)[-] Makefile 介绍 1 Makefile的规则 2 一个示例 3 make是如何工作的 4 makefile中使用变量 5 让make自动推导 6 另类风格的makefile 7 ...
- 【转载】Linux下makefile详解--跟我一起写 Makefile
概述 —— 什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makef ...
- Makefile 如何轻松搞定
最近在学习Linux下的C编程,买了一本叫<Linux环境下的C编程指南>读到makefile就越看越迷糊,可能是我的理解能不行. 于是google到了以下这篇文章.通俗易懂.然后把它贴出 ...
- Linux makefile 教程 非常详细,且易懂 (转)
概述—— 什么是makefile?或许很多Winodws的程序员都不知道这 个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makef ...
- Make和Makefile编写(详见GCC手册)
Makefile和Make Rules 多模块软件.依赖树和Make 默认规则 Make使用程序对简单变量的支持 内建变量 虚目标 特殊目标 一般性语法错误及其纠正措施 命令行的使用和调试 Makef ...
随机推荐
- typedef与#define的区别
1. typedef typedef故名思意就是类型定义的意思,但是它并不是定义一个新的类型而是给已有的类型起一个别名,在这一点上与引用的含义类似,引用是变量或对象的别名,而typedef定义的是类 ...
- JavaScript实现输入验证(简单的用户注册)
1.先写用户注册页面userrAdd.jsp <body> <center> <form name="f1" id="f1" ac ...
- SPSS数据分析—对数线性模型
我们之前讲Logistic回归模型的时候说过,分类数据在使用卡方检验的时候,当分类过多或者每个类别的水平数过多时,单元格会划分的非常细,有可能会导致大量单元格频数很小甚至为0,并且卡方检验虽然可以分析 ...
- SPSS数据分析—二分类Logistic回归模型
对于分类变量,我们知道通常使用卡方检验,但卡方检验仅能分析因素的作用,无法继续分析其作用大小和方向,并且当因素水平过多时,单元格被划分的越来越细,频数有可能为0,导致结果不准确,最重要的是卡方检验不能 ...
- Sprint three
登录界面: 首页: 点餐界面: 查看购物车: 结账: 经历了一个月的时间,我们小组做出了我们的餐厅点餐系统APP.对于这次团队合作,我们的小组成员分工合作做出了我们的餐厅点餐系统APP,通过这次的项目 ...
- OPENGL半透明图像产生黑色光环
OPENGL提供了多种多样的混合方法,我们很容易就能实现诸如 叠加.变亮等图像混合. 我们知道一般带透明度的图像是RGBA四个通道来存储,最常的glBlendFunc是 glBlendFunc(GL_ ...
- php gettext 注释
//setlocale(LC_ALL, "en_US.UTF-8"); setlocale(LC_ALL, "zh_CN.UTF-8"); bindtextdo ...
- hg0088新2网址
封装通俗的说,就是我有一些秘密不想让人知道,就通过私有化变量和私有化方法,这样外界就访问不到了.hg0088新2网址然后如果你有一些很想让大家知道的东西,你就可以通过this创建的属性看作是对象共有属 ...
- 版本控制简介,git使用----使用GitHub托管代码
关于版本控制: 很久以前,人们苦于对写过的代码进行版本的管理,经常过了一段时间想恢复原来写过的代码却又忘了不知道丢到哪儿去了,有的人用加上时间后缀来命名文件的方法,便于后期维护,但是这样做的麻烦也很大 ...
- 深入浅出Mybatis系列(四)---配置详解之typeAliases别名(mybatis源码篇)
上篇文章<深入浅出Mybatis系列(三)---配置详解之properties与environments(mybatis源码篇)> 介绍了properties与environments, ...