Makefile 介绍

阅读数:171 评论数:0

跳转到新版页面

分类

Linux

正文

一、概述    

在Linux中使用make命令来编译程序,特别是大程序,而make命令所执行的动作依赖于Makefile文件。make命令根据文件更新的时间戳来决定哪些文件需要重新编译,这可以避免编译已经编译过的、没有变化的程序,可以大大提高编译效率。

    要想完整的了解Makefile的规则,请参考:GNU make手册

二、Makefile文件规则

    一个简单的Makefile文件包含一系列的“规则”,基样式如下:

target...:prerequisites...
    recipe
    ...

//即
目标: 依赖目标序列;生成命令
//或
目标: 依赖目标序列
tab字符 生成命令
...
tab字符  生成命令

    一个target通常是指程序生成的文件的名字;targets可以是执行文件的名字或者object文件的名辽。target还可以是动作的名字,例如“clean”。

    prerequisites是指用来生成target的一些文件,一个target通常依赖一些文件 。

    recipe是指一个操作,该操作由make来执行。一个recipe可能含有多个命令,这些命令都在同一行,也可以各自独立一行。请注意:recipe的每一行都要有tab键!这是为了防止有人粗心大意。

    通常,如果一个依赖发生了变化,就需要规则调用命令以更新或创建目标。但是并不是所有的目标都依赖,例如,目标“clean”的作用是清除文件,它没有依赖。

    例子:

hello: hello.c
    gcc -o hello hello.c
clean: 
    rm -f hello

    对于上面的Makefile,执行make命令时,仅当hello.c文件比hello文件新,才会执行命令gcc -o hello hello.c生成可执行文件hello,如果还没有hello文件,这个命令也会执行。

    运行make clean时,由于目标clean没有依赖,它的命令rm -rf hello将被强制执行。

三、Makefile文件里的赋值方法

    变量的定义语法形式如下:

// 直接赋值,make会将整个makefile展开后,再决定变量的值。也就是说,变量的值将会是整个makefile中最后被指定的值。
变量 = deferred
// 条件赋值,如果没有被赋值过就赋予等号后面的值
变量 ?= deferred
// 覆盖赋值,
变量 := immediate
// 追加赋值,添加等号后面值
变量 += deferred or immediate

define immediate

makefile文件中的变量无需声明类型,可以直接进行初始化。

宏变量 其命名方式一般是由大定字母组成的字符串。
环境变量 一部分是make命令内置的环境变量,另一部分是接收从make命令传递过来的参数而定义的变量。
自定义变量 其命令方式一般是由小写字母组成的字符串。
目标变量 其表示一类具有特定变量名以及特殊含义的变量。
自动化变量  自动化变量用于模式规则中,其中$@表示规则中的目标,$<表示规则中的第一个依赖目标名,$^表示规则中的依赖目标序列。

如果变量被export修饰,则它的取值会传递给子层makefile。如果unexport修饰则变量不会传递给子层makefile使用。如果变量被define修饰,则定义该变量以供后续使用。   

四、Makefile常用内置函数

内置函数的调用是以$为开头进行标识,  函数调用的格式如下:

$(function arguments)

如果有多个参数,它们之间用逗号隔开。内核的Makefile中用到了大量的函数,现在介绍一些常用的。

1、$( subst from,to,text)

    在文本“text”中使用"to"替换每一处“from”。

比如

$(subst ee,EE,fee on the street)

结果为fEE  on the stEEt.

2、$(patsubst pattern,replacement,text)

    寻找text中符合格式pattern的字,用replacement替换它们。pattern和replacement中可以使用通配符。

比如:

$(patsubst %.c,%.o,x.c.c bar.c)

结果为:x.c.o bar.o

3、$(strip string)

    去掉前导和结尾空格,并将中间的多个空格压缩为单个空格

比如

$(strip a  b c)

结果为: "a b c"

4、$(findstring find,in)

    在字符串in中搜寻find,如果找到,则返回值是find,否则返回值为空。

$(findstring a,a b c)
$(findstring a,b c)

将分别产生值“a”和“ ”

5、$(filter pattern...,text)

    返回text中由空格隔开且匹配格式"pattern..."的字,去除不符合格式“pattern...”的字

比如

$(filter %.c %.s,foo.c bar.c baz.s ugh.h)

结果为“foo.c bar.c baz.s”。

6、$(filter-out pattern...,text)

    返回在text中由空格隔开且不匹配pattern...的字,去除符合格式pattern...的字。它是filter的反函数

$(filter-out %.c %.s,foo.c bar.c baz.s ugh.h)

结果为“ugh.h”

7、$(sort list)

    将list中的字按字母的顺序排序,并去掉重复的字。输出由单个空格隔开的字的列表。

比如:

$(sort foo bar lose)

结果为“bar foo lose”

-----------以上是字符串的操作

8、$(dir names...)

    抽取name...中每一个文件名的路径部分,文件名的路径部分包括从文件名的首字符到最后一斜杠(含斜杠)之前的一切字符。

比如

$(dir src/foo.c hacks)

结果: “src/ ./”

9、$(notdir names...)

    抽取names...中每一个文件名中除路径部分外一切字符(真正的文件名

例如

$(notdir src/foo.c hacks)

结果"foo.c hacks"

10、$(suffix names...)

    抽取names...中每一个文件名的后缀

例如

$(suffix src/foo.c src-1.0/bar.c hacks)

结果为“.c .c”

11、$(basename names...)

    抽取names...中每一个文件名除后缀外一切字符。

例如

$(basename src/foo.c src-1.0/bar.c hacks)

结果为“src/foo src-1.0/bar hacks”。

12、$(addsuffix suffix,names...)

    参数names...是一系列的文件名,文件名之间用空格隔开;suffix是一个后缀名。将suffix的值附加在每一个独立文件名的后面,完成后将文件名串联起来,它们之间用单个空格隔开。

$(addsuffix .c,foo bar)

结果为“foo.c bar.c”

13、$(addprefix prefix,names...)

    prefix是一个前缀名,将prefix的值附加到每一个独立文件名的前面,完成后将文件名串联起来,它们之间用单个空格隔开。

$(addprefx src/, foo bar)

结果:“src/foo src/bar”。

14、$(wildcard pattern)

    参数pattern是一个文件名格式,包含有通配符(通配符和shell中的用法一样)。函数wildcard的结果是一行和格式匹配且真实存在文件的名称,文件之间用一个字格隔开。

例如

#比如当前目录下有文件 1.c 2.c 1.h 2.h,则
c_src :=$(wildcard *.c)

结果为“1.c 2.c”

-------------以上是文件的操作

15、$(foreach var,list,text)

    对list中的变量循环处理,每个变量赋值到var上,对每个var执行text操作后,得到新的list

例如

dirs :=a b c d
files :=$(foreach dir,$(dirs),$(wildcard $(dir)/*))

结果为dirs中所有目录下的所有文件的列表。

16、$(if condition,then-part[,else-part])

    如果condition为值,则执行then-part,否则执行else-part,else-part不存在时,返回空。

17、$(origin variable)

    变量variable是一个查询变量的名称,不是对该变量的引用,所以,不能采用$和圆括号的格式书该变量,当然,如果坱要使用非常量的文件名,可以在文件名中使用变量引用。

    结果是一个字符串,结果如下

undefined 变量从来没有定义
default 是默认定义
environment 环境变量,选项-e没有打开
environment override 环境变量,选项-e已打开
file 在Makefile中定义
command line 在命令行中定义
override 在Makefile中用override指令定义
automatic 自动变量

18、$(shell command arguments)

    函数shell是make与外部环境的通信工具。函数shell的执行结果和在控制台上执行command arguments的结果相似。不过如果command arguments的结果含有换行符(和回车符),则在函数shell的返回结果中将它们处理为单个空格,若返回结果最后是换行符(和回车符)则被去掉。

    比如当前目录下有文件1.c 2.c 1.h 2.h,则

c_src :=$(shell ls *.c)

结果为: 1.c 2.c

五、分支判断语句

makefile文件中的分支判断语句有四种:ifeq, ifneq, ifdef和ifndef。每个分支判断语句都与一个结束符 endif相匹配。

ifeq\ifneq (变量1,变量2)

分支判断语句可以嵌套使用,并且其中可以使用else。




相关推荐

在bootloader的帮助下,内核被载入到内存中,内核映像被加载到内存并获得控制权之后,内核启动流程开始。通常,内核映像以压缩形式存储,并不是一个可以执行的内核。因此内核的首要工作是自解压内核映像。

一、概述    Linux内核源码中含有很多个Makefile文件,这些Makefile文件又要包含其他一些文件(比如配置信息、通用规则 等)。这些文件构成了Linux的Makefile体系。

一、概述 makefile文件包含一些规则,告诉make工具编译哪些文件以及怎样编译这些文件。 配置文件.config 是在进行内核配置后生成的中间产物。 是通过make menuconfi

一、概述 configure用于生成makefile,make命令根据makefile文件编译程序,make install 会把可执行程序安装至/usr/local/bin目录。 二、makefil

$@ 目标的名字 $^ 构造所需文件列表所有文件的名字 $< 构造所需文件列表的第一个文件的名字 $? 构造所需文件列表中更新过的文件 (1)- make 在执行命令的时候,如