Makefile 学习整理

Makefile的规则:
target ... : prerequisite...
    command
    ...
    ...
    
target是一个目标文件,可以说object file ,也可以是执行文件,也可是标签
prerequisite使生成target所需要的文件或者是目标
command也就是make需要执行的命令

Makefile的书写命令:
    每条规则中的命令和操作系统shell的命令行是一致的。
    每条命令的开头必须以[Tab]开头,除非命令是紧跟在以来规则后面。
  1.显示命令
    @字符在命令行前面的时候,这个命令将不被make显示出来
    如果带入make参数“-n”或“--just-print”,那么只是显示命令,但不会执行命令
    make参数“-s”或者“--slient”则是全面禁止命令的显示
  
  2.执行命令
    当规则的目标需要被更新时,make会一条一条执行其后面的命令。
    如果需要让上一条命令的结果应用在下一条命令时,应该将两条命令写在同一行
并且用分号隔开。

  3.命令出错
    每当命令运行完之后,make会检测每个命令的返回码,如果命令返回成功,则会继续执行
下一条命令,当规则中所有的命令成功返回后,这个规则就是成功完成。
    忽略一些非错误性出错可以在Makefile的命令行前面加一个“-”号(在Tab键之后),标记为
不管命令是否出错,均认为成功。

  4.嵌套执行make
    大工程中,在每个功能目录里面下一个Makefile。最终由一个总控Makefile来进行控制。
    总控makefile书写格式:
        subsystem:
                cd subdir && $(MAKE)
    
    等价于
        subsystem:
                $(MAKE) -C subdir
                
    
    传递变量到下级Makefile中的声明:
        export <variable ...>
    
    不想让某些变量传递到下级Makefile中,声明:
        unexport <variable ...>
        
    示例一:
        export variable = value

    其等价于:
        variable = value
        export variable
        
    其等价于:
        export variable := value

    其等价于:
        variable := value
        export variable
    
    如果需要传递所有变量,那么只要一个export就可以。注意:SHELL MAKEFLAGS总传递到下层
    make命令中有几个参数并不往下传递
    -c, -f, -h, -o, -W
    
  5.定义命令包
  如果Makefile中出现一些相同命令序列。语法:
  
  define run-yacc
  yacc $(firstword $^)   #运行Yacc程序
  mv y.tab.c $@          #将这个文件改名字
  endef
  
  其中,run-yacc 为命令包,不能与Makefile中的变量重名。
  示例:
        foo.c : foo.yacc
                $(run-yacc)
    
    在具体示例中,命令包中$^就是foo.y   $@就是foo.c
    
  
变量的使用:
    变量的命名可以包含字符、数字、下划线,但能含有 “:”“#”“=”或者空字符
    变量区分大小写,建议使用大小写搭配的变量名
    
一、变量基础
    变量在声明时需要给予初值,在使用的时候需要在变量名前面加上“$”,如果需要使用真实的$,那么写作$$
    
二、变量中的变量
    1.  利用“=”。在“=”左侧是变量,右侧是变量的值。右侧变量的值可以定义在文件的任何一处。
    注意:这种方法有可能会让make陷入无限的变量展开过程中去。
    2.  利用“:=”操作符
    例如:
        x:=foo
        y:=$(x)bar
        x:=later
    等价于:
        y:=foo bar
        x:=later
    这种方法,前面的变量不能够使用后面的变量,只能使用前面已经定义好了的变量。
    3. 如果我们需要定义一个变量值为一个空格,可以如下定义:
    nullstring  := 
    space := $(nullstring)#end of the line
    利用“#”注释符来标识变量定义的终止
    4. “?=”操作符  
        FOO ?= bar  #如果FOO没有被定义过,那么变量FOO的值就是bar,如果FOO先前定义过,那么跳过
        
三、变量高级用法
    1.变量值的替换
    替换变量中共有的部分   $(var:a=b) 或者 ${var:a=b}  #把变量var中所有以“a”字串结尾的“a”替换位“b”
    
    2.把变量的值再当成变量
    简单例子 
    x = y
    y = z
    a := $($(x))
    推导出: $(a)的值为z
    复杂例子
    x = variable1
    variable2 := Hello
    y = $(subst 1, 2, $(x))    #将variable1的1替换成2, y = variable2
    z = y
    a := $($($(z)))      #$($(y)) -> $(variable2) -> Hello

四、追加变量
    利用“+=”操作符来给变量追加值,如:
    objects = main.o 
    objects += another.o  # $(objects)的值即 “main.o another.o”
    如果变量之前没有定义过,那么"+="自动转化为"="
    如果前面有变量定义,那么"+="会继承于前次操作的赋值符

五、override指示符

六、多行变量
    使用define关键字设置的值可以有换行,这有利于定义一系列的命令

七、环境变量    

八、目标变量
    以上所有的变量定义都是“全局变量”,在整个文件中,都可以访问。“自动化变量”除外。
    如“$<”等这种变量的自动化变量就属于“规则型变量”,这种变量的值依赖于规则的目标和依赖目标的定义。
    可以为某个目标设置局部变量,这种变量称为“Target-specific Variable”,可以和全局变量同名,作用范围只在这条
规则以及连带规则中。
    语法:
        <target ...>:<variable-assignment>
        <target ...>:override<variable-assignment>
        
        
使用条件判断
    语法:
    <conditional-directive> #条件关键字 ifeq(<arg1>,<agr2>) 或者 ifneq(<arg1>,<arg2>) 或者 ifdef<variable-name>或者ifndef(<arg1>,<arg2>)
    <text-if-true>
    else
    <text-if-false>
    endif

函数的调用语法
    函数的调用以"$"来标识,语法如下:
    $(<function> <arguments>)或者${<function> <arguments>}
#function是函数名,arguments是参数,参数间用“,”分隔,函数名与参数之间以“空格”分隔。

字符串处理函数
    $(subst <from>, <to>, <text>)
    名称:字符串替换函数----subst
    功能:把字串<text>中的<from>字符串替换成<to>
    返回:函数返回被替换过后的字符串
    
    $(patsubst <pattern>,<replacement>,<text>)
    名称:模式字符串替换函数---patsubst
    功能:查找<text>中的单词是否符合模式<pattern>,如果匹配,则以<replacement>替换
        这里,<pattern>可以包括通配符%,表示任意长度的字串。
    返回:函数返回被替换过后的字符串
    
    $(strip <string>)  去掉空格
    $(finding <find>,<in>) 查找字符串函数
    $(fileter <pattern...>,<text>) 过滤函数,保留符合 模式pattern 的单词
    $(fukter-out <pattern...>,<text>) 反过滤,去除符合 模式pattern的单词
    $(sort <list>) 排序,默认升序
    $(word <n>,<text>) 取单词函数
    $(wordlist <s>,<e>,<text>) 取单词串函数
    $(words <text>) 单词个数统计函数
    $(furstword <text>) 首个单词函数

文件名操作函数
    $(dir <names...>)  取目录函数
    $(notdir <names...>) 取文件函数
    $(suffix <names...>) 取后缀函数
    $(basename <names...>) 取前缀函数
    $(addsuffix <suffix> <names...>) 加后缀函数
    $(addprefix <prefix>,<names...>) 加前缀函数
    $(join <list1>,<list2>) 连接函数
    
隐含规则:
    编译C程序的隐含规则
    “<n>.o”的目标依赖目标会自动推导为“<n>.c”,并且其生成命令是  $(CC) -c $(CPPFLAGS) $(CFLAGS)
    
    链接object文件的隐含规则
    “<n>”目标依赖于“<n>.o”,通过运行C的编译器来运行链接程序生成,其生成命令是 $(CC) $(LDFLAGS) <n>.o $(LOADLIBES) $(LDLIBS)
    注意:这个规则对于只有一个源文件的工程有效,同时也对多个object文件的有效
    
隐含规则使用的变量
    C语言编译程序。默认命令是 “CC”,如果把变量“$(CC)”重定义为“gcc”,“$(CFLAGS)”重定义为“-g”,那么隐含规则中
的命令全部都会以“gcc -c -g $(CPPFLAGS)”来执行
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值