Makefile规则

Makefile规则的样式如下:

目标(target)... : 依赖(prerequiries)... 

<Tab>命令(command)

  命令被执行的两个条件:依赖文件比目标文件新,或者目标文件未生成。

(一)Makefile语法

1、通配符%(%.c表示所有.c文件,%.o表示所有.o文件

      $@表示目标

      $<表示第一个依赖文件

      $^表示所有的依赖文件

例如:

 2、假想目标:.PHONY

例如:

当该目录下有名为clean的文件的时候,执行make clean并不会起效果,如图:

 

现在我们的目录里面有名为“clean”的文件,目标文件是有的,并且没有依赖文件,没有办法判断依赖文件的时间。这种写法会导致:有同名的"clean"文件时,就没有办法执行make clean操作。解决办法:我们需要把目标定义为假象目标,用关键子PHONY

(注意:执行make[目标],也可以不带目标名,若无目标则默认第一个目标。直接执行make的时候,会在makefile里面找到第一个目标然后执行下面的命令来生成第一个目标;当执行make clean时,会在makefile中找到clean目标,然后执行里面的命令。)

 3、变量(即时变量,延时变量)

A := xxx   # A的值即刻确定,再定义时即确定。

B = xxx    # B的值使用到的时候才确定

:=  定义为即时变量

=   定义为延时变量

?= 定义为延时变量,是第一次定义才起效,若在前面该变量已定义则忽略这句

+= 定义为附加,它是即时变量还是延时变量取决于前面的定义

例如:

 

执行make,结果如下:

 

 分析:1)A := $(C)

                A为即时变量。定义时即确定,由于刚开始时C的值为空,所以A的值也为空。

            2)B = $(C)

                B为延时变量,只有使用到时它的值才会被确定下来,执行make时,会解析Makefile里面所有的变量,首先解析C = abc,然后解析C += 123,此时C = abc 123,所以B的值为abc 123

            3)D ?= ounijiang

                D变量在前面未定义,所以D的值为ounijiang,若在前面添加D=100ask,则最后D的值为100ask(还可以通过命令行存入变量的值,例如:make D = ???,这样Makefile中的D ?= ounijiang就不起作用了)

 (二)Makefile常用函数

函数调用的格式:$(函数名        函数参数)或者$(函数名 函数参数)

函数名与参数之间是用Tab或者空格隔开,若有多个参数,则用逗号隔开。这些空格和逗号不是参数值的一部分。

(字符串替换和分析函数)

1、$(subst        from,to,text)

        解析:在文本"test"中使用‘to’来替换每一处的‘from’

        例如:$(subst        ee,EE,feet on the street)

        结果为‘fEEt on the strEEt’

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,cwy.c dxt.c dxt.s cwy.h)

        结果为:'cwy.c dxt.c dxt.s'

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

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

        例如:$(filter-out        %.c %.s,cwy.c dxt.c dxt.s cwy.h)

        结果为:'cwy.h'

7、$(sort        list)

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

        例如:$(sort        ttl cmos rss)

        结果为:'cmos rss ttl'

(文件名函数)

1、$(dir        names...)

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

        例如:$(dir        src/foo.c hacks)

        结果为:'src/  ./'

2、$(notdir        names...)

        解析:抽取‘names...’中每一个文件名中除路径部分外一切字符(真正的文件名)。

        例如:$(notdir        src/foo.c hacks)

        结果为:'foo.c hacks'

3、$(suffix        names...)

        解析:抽取‘names...’中每一个文件名的后缀。

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

        结果为:'.c .c'

4、$(basename        names...)

        解析:抽取‘names...’中每一个文件名中除后缀外一切字符。

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

        结果为:'src/foo src-1.0/bar hacks'

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

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

        例如:$(addsuffix        .c,foo bar)

        结果为:'foo.c bar.c'

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

        解析:参数‘names’是一系列的文件名,文件名之间用空格隔开;prefix 是一个前缀名。将 preffix(前缀)的值附加在每一个独立文件名的前面,完成后将文件名串联起来,它们之间用单个空格隔开。

        例如:$(addprefix        src/,foo bar)

        结果为:'src/foo src/bar'

7、$(wildcard        pattern)

        解析:参数‘pattern’是一个文件名格式,包含有通配符(通配符和 shell 中的用法一样)。函数 wildcard 的结果是一列和格式匹配的且真实存在的文件的名称,文件名之间用一个空格隔开。当该目录下有1.c、2.c、1.h、2.h时

        例如:c_src := $(wildcard        *.c)

        结果为:'1.c 2.c'

(其他函数)

1、$(foreach        var,list,text)

        解析:前两个参数,‘var’和‘list’,将首先扩展,注意最后一个参数 ‘text’ 此时不扩展;接着,对每一个 ‘list’ 扩展产生的字,将用来为 ‘var’ 扩展后命名的变量赋值;然后 ‘text’ 引用该变量扩展;因此它每次扩展都不相同。结果是由空格隔开的 ‘text’。在 ‘list’ 中多次扩展的字组成的新的 ‘list’。‘text’ 多次扩展的字串联起来,字与字之间由空格隔开,如此就产生了函数 foreach 的返回值。

        例如:

 

        结果:

 

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

首先把第一个参数‘condition’的前导空格、结尾空格去掉,然后扩展。如果扩展为非空字符串,则条件‘condition’为‘真’;如果扩展为空字符串,则条件‘condition’为‘假’。 如果条件‘condition’为‘真’,那么计算第二个参数‘then-part’的值,并将该值作为整个函数 if 的值。 如果条件‘condition’为‘假’,并且第三个参数存在,则计算第三个参数‘else-part’的值,并将该值作为整个函数 if 的值;如果第三个参数不存在,函数 if 将什么也不计算,返回空值。 注意:仅能计算‘then-part’和‘else-part’二者之一,不能同时计算。这样有可能产生副作用(例如函数 shell 的调用)。

3、$(origin        variable)

变量‘variable’是一个查询变量的名称,不是对该变量的引用。所以,不能采用‘$’和圆括号的格式书写该变量,当然,如果需要使用非常量的文件名,可以在文件名中使用变量引用。 函数 origin 的结果是一个字符串,该字符串变量是这样定义的:

 

4、$(shell        command arguments)

        解析:函数 shell 是 make 与外部环境的通讯工具。函数 shell 的执行结果和在控制台上执行‘command arguments’的结果相似。不过如果‘command arguments’ 164 / 566 的结果含有换行符(和回车符),则在函数 shell 的返回结果中将把它们处理为单个空格,若返回结果最后是换行符(和回车符)则被去掉。比如当前目录下有文件 1.c、2.c、1.h、2.h,则:

        例如:c_src := $(shell        ls *.c)

        结果:'1.c 2.c'

(Makefile规则使得能够根据文件更新的时间戳来决定哪些文件需要重新编译,这使得可以避免编译已经编译过的、没有变化的程序,可以大大提高编译效率。)

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有才华是油菜花

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值