Makefile基础

原创 2016年08月28日 14:49:27

基础

运行make命令之后,make程序会在当前目前下寻找Makefile文件,根据Makefile文件中的内容执行具体的操作。


执行make命令后的结果如下:

Makefile的基础是如下的部分:
targets:prerequisites
  commands
如上例所示:
a.out是targets,目标
main.c是prerequisites,依赖
剩余的部分开头是一个TAB,他们是命令
make执行命令的条件是依赖比目标要新。
如果在上例执行后再运行make,结果如下:

这是因为main.c没有修改过,它比a.out要旧。
需要注意,目标和依赖都可以是多个,而只要任意依赖新于目标,都会导致命令重新执行。

以上示例中,目标是一个文件,但是它还可以是其它的。比如一个标签:

all就是一个标签。
标签永远比依赖要旧,即其下的命令一直会执行:

甚至可以没有依赖:

all对应命令也会一直执行。
标签可以有多个,但是它并不是顺序执行,make只会执行第一个遇到的标签。如下面的Makefile文件:

执行make的结果如下:

可以看到只有all标签会被执行。如果要执行bll,就需要显式地指定:

标签之间可以互相依赖:

执行的结果如下:

因为all依赖于bll,而bll又依赖于main.c,因此这里的执行顺序就是先执行bll对应的命令,然后再执行all对应的命令。

还有一种情况,如果在标签之前加上“.”,则make的时候会跳过它,即使它是第一个遇到的标签:

make执行结果如下:


标签在Makefile文件中又称为伪目标,不应该与真正的目标文件具有相同的名字,而为了避免这种情况,Makefile提供了一个关键字.PHONY,用于声明伪目标。
像下面这个样子:


变量

Makefile文件中的变量就是一个个的字符串
访问变量使用$(xx),其中xx是变量名。
下面是一个例子:

执行的结果是:

变量的赋值可以使用普通的"=",它有一个特点,如下例所示:

执行的结果是:

即,Makefile中使用=定义的变量可以访问到之后定义的变量。使用=得到的变量称为recursively expanded variable。
它有一个缺点就是会导致循环赋值,比如下面的例子:


为了避免这种情况,Makefile提供了另一个赋值操作符":=",称为Simply expanded variables。
它更接近于一般意义上的赋值,当:=右边引用了其它的变量,而该变量还没有定义或者要到之后才会定义,那么返回的就是空字符串。
另外的赋值操作符还有:
+=”:这是给变量追加值。
"?=":首先判断变量是否存在,如果不存在就赋值成右边的值,如果存在了,就什么也不做。

与变量赋值相关的还有几个指示符:
override:这个指示符出现的原因是,一般定义的变量会被make命令行中的参数覆盖,而使用了override的变量则不会。下面是一个例子:
在未使用override的情况下:


可以看到FLAG参数被make命令行中的参数替代了。
如果在定义变量的时候使用了override的话:


变量的值将不会受到make命令行参数的影响。
export:用于向下层的Makefile文件传递参数。默认情况下,只有在make命令行中的参数才会向下传递,但是使用export之后,在当前Makefile文件中定义的变量也会向下传递了。

Makefile中还存在几类特殊的变量:
系统环境变量:make执行时会引入部分的环境变量,它们在Makefile中可以访问:


从结果可以看到Makefile中可以识别HOME这个系统环境变量。
需要注意的是,并不是所有的系统环境变量都可以在Makefile中使用,比如BASH就不行。具体怎么区分的,不知道。
目标变量:它是针对某一个目标存在的变量,可以算作是局部变量。它的定义如下:
targets:xx=yy
下面是一个例子:


从中可以看到FLAG只针对all存在,在bll中无法访问到。
还需要注意,FLAG不仅只在all中生效,它引发的所有的规则中FLAG都存在。
模式变量:它其实是目标变量的延伸。其中定义的变量对满足模式的所有目标都可见。下面是一个例子:


上例中的a.out满足%.out的模式,所以FLAG有效,而对于main.o就无效了。
自动化变量:它们是一组样式奇怪的变量,也属于局部变量,下面是其中的几个:
$@ :表示目标集;
$< :表示依赖中的第一个名字,如果依赖是模式的话,则表示满足模式的所有依赖;
$? :表示所有比目标新的依赖集;
$^ :表示依赖集;
$(@D) :表示$@的目录部分;(还有其它版本的,如$(<D),略)
$(@F) :表示$@的文件部分;(还有其它版本的,如$(<F),略)
自动化变量还有很多,不一一介绍了。
还有一个类型的变量,属于make执行时可以使用的与命令相关的变量,比如如下的:

执行的结果如下:

这类变量还有很多,这里不一一说明。

函数

函数的格式如下:
$(<fucn><params>)
函数名与参数间用空格隔开,参数之间用逗号隔开。
以下是一个简单的示例:

make后得到的结果是goodbye world。
Makefile中的函数将在Makefile基础——函数中详细介绍。

控制语句

Makefile中的控制语句有以下的一些:
ifeq/ifneq
else
endif
举例:
ifdef/ifndef
else
endif
举例:


版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jiangwei0512/article/details/52345657

【Linux基础】万能MAKEFILE模板

############################################################## # # Generic Makefile for C/C++ Prog...
  • u010926630
  • u010926630
  • 2013-06-06 11:40:08
  • 675

Makefile基础---自动处理头文件的依赖关系

Makefile基础---自动处理头文件的依赖关系  现在我们的Makefile写成这样: all: main main: main.o stack.o maze.o gcc $^ -o ...
  • dl0914791011
  • dl0914791011
  • 2013-12-30 11:22:30
  • 1125

Makefile学习

  • 2011年11月30日 19:32
  • 920KB
  • 下载

makefile 编写指南(基础)

  • 2012年04月13日 10:04
  • 85KB
  • 下载

实验一.linux命令与编程基础实验

(没有上传图片)实验一   Linux命令与编程基础实验实验目的:了解远程登录,学习putty这个软件,会运用它进行远程登录。学习和掌握Linux命令,了解GCC编译器及VI文字编辑器的运用,会简单的...
  • xiao0908
  • xiao0908
  • 2008-04-25 23:08:00
  • 1087

Makefile学习示例

  • 2013年06月10日 15:31
  • 8KB
  • 下载

Makefile 入门与基本语法

在我看来,学会写简单的Makefile,阅读较复杂的makefile,是每一个Linux程序员都必须拥有的基本素质。Makefile可以自动识别哪些源文件被更改过,需要重新编译,那些不需要。从而节省大...
  • Paul_C_V
  • Paul_C_V
  • 2015-05-18 11:16:09
  • 7873

跟我一起写_Makefile

  • 2010年06月29日 19:22
  • 26KB
  • 下载

Makefile Manual

  • 2010年12月17日 19:35
  • 1.08MB
  • 下载

跟我一起写Makefile

  • 2013年03月27日 17:02
  • 1.02MB
  • 下载
收藏助手
不良信息举报
您举报文章:Makefile基础
举报原因:
原因补充:

(最多只允许输入30个字)