Makefile

Makefile

一个工程中的源文件不计数,其按类型、功能、 模块分别放在若干个目录中,makefile 定义了一系列的规则来指定,哪些文件需要先编译, 哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 makefile 就像一个 Shell 脚本一样,其中也可以执行操作系统的命令。 makefile 带来的好 处就是——“自动化编译”,一旦写好,只需要一个 make 命令,整个工程完全自动编译, 极大的提高了软件开发的效率。make 是一个命令工具,是一个解释 makefile 中指令的命令 工具。

规则

格式:
TARGET:PREREQUISITES
<tab键>RECIPE    
<tab键>RECIPE    
<tab键>RECIPE    
<tab键>RECIPE    
    .....

.PHONY:clean

clean:

<tab键>-rm *.o


    TARGET  目标(文件名),make要做什么
        你的makefile的最终目的是什么
        
    PREREQUISITES:依赖,完成这个目标依赖的文件(也可以没有)
        第一步看当前目标依赖的文件是否存在。
            a.存在
                按照RECIPE命令列表取完成目标
            b.不存在
                就搜索整个makefile,查找是否有以依赖文件为目标名的目标
                如果有,则先递归的生成该目标....
                如果没有,则报错...
        
        
    RECIPE:生成该目标需要执行的命令
        生成该目标需要执行的命令列表(可以是linux的shell命令)

.PHONY表示后边的都是伪目标

-rm 任何语句加上减号,就算语句错误也会继续执行后面的语句,如果想忽略全部错误,则可以使用make -i

make的用法

make + 目标名字
 如果没有加目标,则默认完成makefile中第一个目标

把其他目标叫做“伪目标”
make运行的时候会自动的到当前目录找Makefile文件
make -C 指定目录
到指定的目录中去执行makefile
make会自动的把执行的命令打印到终端
如果不需要打印命令,则在命令行首加个@,就不会打印该行命令,如果需要全部不打印,则可以用make -s命令
make 是非常智能的,能够根据文件的修改时间,去自动的判断哪一些文件需要重新编译。

如果要指定特定的Makefile文件,则可以用make -f filename

一般默认使用make他会找当前目录的以"Makefile"为名的文件

在makefile文件中,注释是以#标注的,且只能进行行注释,如果需要打印#则需要用\进行转义,如\#

当依赖目标新于目标时,也就是当规则的目标需要被更新时,make 会一条一条的执行 其后的命令。需要注意的是,如果你要让上一条命令的结果应用在下一条命令时,你应该使 用分号分隔这两条命令。比如你的第一条命令是 cd 命令,你希望第二条命令得在 cd 之后的 基础上运行,那么你就不能把这两条命令写在两行上,而应该把这两条命令写在一行上,用 分号分隔。

make 的工作方式 

1、读入所有的 Makefile。

2、读入被 include 的其它 Makefile。  

3、初始化文件中的变量。  

4、推导隐晦规则,并分析所有规则。

5、为所有的目标文件创建依赖关系链。  

6、根据依赖关系,决定哪些目标要重新生成。  

7、执行生成命令。

1-5 步为第一个阶段,6-7 为第二个阶段。第一个阶段中,如果定义的变量被使用了,那么, make 会把其展开在使用的位置。但 make 并不会完全马上展开,make 使用的是拖延战术,如 果变量出现在依赖关系的规则中,那么仅当这条依赖被决定要使用了,变量才会在其内部展开。

自动变量

系统已经帮我们定义好的变量,我们直接使用即可,已经有确定的值(特殊的含义)

            $@    当前完整的目标名字
                main:
                    echo $@      //main
                xxxxx:
                    echo $@     //xxxxx
            
            $+    当前所有的依赖文件,以空格隔开,可能包含重复的依赖文件
                你写到哪一个目标下面,就表示哪一个目标的依赖文件列表
                
                
            $^    当前所有的依赖文件,以空格隔开,不重复的依赖文件
                你写到哪一个目标下面,就表示哪一个目标的依赖文件列表


            $<    第一个依赖的名字
                main:a.c,b.c
                    gcc $<   
                            $<  <===> a.c
        
            $?
                所有时间戳比目标文件晚的依赖文件,并且以空格隔开
                    生成目标后,你又重新更改了文件

 

变量的用法

1 简单赋值 (:=)  简单的进行赋值操作

2 递归赋值 (=)  会向后展开

          比如:foo = $(bar)  

                     bar = $(ugh)  

                     ugh = Huh? 

         打印出来foo的值为Huh?

3 追加赋值  (+=) 在变量当前值后边加上新的值 以空格隔开

4 条件赋值  (?=)  如果没有被定义,才会进行赋值操作

5 变量值的替换  $(var:a=b)  把变量“var”中所有以 “a”字串“结尾”的“a”替换成“b”字串。这里的“结尾”意思是“空格”或是“结束符”。

6 把变量的值再当成变量 比如:x = y

                                                   y = z  

                                                   z = u  

                                                  a := $($($(x)))              此时a的值为u

使用条件判断

libs_for_gcc = -lgnu  

normal_libs =    

foo: $(objects)  

ifeq ($(CC),gcc)  

$(CC) -o foo $(objects) $(libs_for_gcc)  

else  $(CC) -o foo $(objects) $(normal_libs)  

endif

我们可以从上面的示例中看到三个关键字:ifeq、else 和 endif。ifeq 的意思表示条 件语句的开始,并指定一个条件表达式,表达式包含两个参数,以逗号分隔,表达式以圆括 号括起。else 表示条件表达式为假的情况。endif 表示一个条件语句的结束,任何一个条件 表达式都应该以 endif 结束。

1.ifeq  相同为真 不同为假

2 ifneq 相同为假 不同为真

3 ifdef 后加一个值 非空则真

4 ifndef 空为真

函数

函数调用,很像变量的使用,也是以“$”来标识的   $(<function> <arguments>) 

字符串处理函数 

 

1、字符串替换函数——subst

$(subst <from>,<to>,<text>)    

功能:把字串<text>中的<from>字符串替换成<to>。  

返回:函数返回被替换过后的字符串。 

 

2、模式字符串替换函数——patsubst

$(patsubst <pattern>,<replacement>,<text>)

 功能:查找<text>中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符 合模式<pattern>,如果匹配的话,则以<replacement>替换。这里,<pattern>可以包括通 配符“%”,表示任意长度的字串。如果<replacement>中也包含“%”,那么,<replacement> 中的这个“%”将是<pattern>中的那个“%”所代表的字串。(可以用“\”来转义,以“\%” 来表示真实含义的“%”字符)  返回:函数返回被替换过后的字符串。  

 

3、去空格函数——strip

$(strip <string>)      

功能:去掉<string>字串中开头和结尾的空字符。

 返回:返回被去掉空格的字符串值。 

 

4、 查找字符串函数——findstring

$(findstring <find>,<in>)   

 功能:在字串<in>中查找<find>字串。  

返回:如果找到,那么返回<find>,否则返回空字符串。 

 

5、过滤函数——filter

$(filter <pattern...>,<text>)  

功能:以<pattern>模式过滤<text>字符串中的单词,保留符合模式<pattern>的单词。可以 有多个模式。  

返回:返回符合模式<pattern>的字串。  

示例:  sources := foo.c bar.c baz.s ugh.h  

foo: $(sources)  

cc $(filter %.c %.s,$(sources)) -o foo  

$(filter %.c %.s,$(sources))

返回的值是“foo.c bar.c baz.s”。

 

6、反过滤函数——filter-out  (与上函数相反)

 

7、排序函数——sort。  

$(sort <list>)   

功能:给字符串<list>中的单词排序(升序)。

 返回:返回排序后的字符串。  

示例:$(sort foo bar lose)返回“bar foo lose” 。

 备注:sort 函数会去掉<list>中相同的单词。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值