makefile学习笔记

make处 理Makefile的过程也分为两个阶段:

· 首先从前到后读取所有规则,建立起一个完整的依赖关系图

·然后从缺省目标或者命令行指定的目标开始,根据依赖关系图选择适当的规则执行,执 行Makefile中的规则并不是从前到后按顺序执行,也不是所有规则 都要执行一遍。首先更新它的所有条件;所有 条件中只要有一个条件被更新了,目标也必须随之被更新。

写Makefile都是以目标为中心,一个目标依赖于若干条件,现在换个角度,如下以条件为中 心 (makefile目的是让make建立依赖关系图,只要把所有的依赖关系描 述清楚就ok)

  main.o stack.o:stack.h

  main.o stack.o maze.o:main.h

  main.o maze.o:maze.h

注:在make的命令行中指定一个目标(例如clean),则更新这个目标,如果不指定目标则更 新Makefile中第一条规则的目标(缺省目标)。

小常识:命令前面加@和-字符:如果make执行的命令前面加了@字符,则 不显示命令本身而只显示它的结果;make执行的命令如果出错就 立刻终止,不再执行后续命令,但如果命令前面加了-号,即使这条命令出错,make也会继续执 行后续命令。通常rm命令和mkdir命令前面要加-号。

 

Makefile(里主要包含了五个东西:显式规则、隐晦规则、变量定义、文件指示和注释。)

默认情况,make命令会在当前目录下按顺序找寻文件名为“GNUmakefile”、“makefile”、“Makefile”的文件,找到了解释这个文件。在这三个文件名中,最好使用“Makefile”这个文件名,第一个字符为大写有一种显目的感觉。最好不要用“GNUmakefile”,这个文件是GNU的make识别的。有另外一些make只对全小写的“makefile”文件名敏感,但是基本上来说,大多数的make都支持“makefile”和“Makefile”这两种默认文件名。

当然,你可以使用别的文件名来书写Makefile,比如:“Make.Linux”,“Make.Solaris”,“Make.AIX”等,如果要指定特定的Makefile,你可以使用make的“-f”和“--file”参数,如:make -f Make.Linux或make --file Make.AIX。

一: 显式规则。

  显式规则说明如何生成一个或多的的目标文件。这是由Makefile的书写者明显指出,要生成的文件,文件的依赖文件,生成的命令。

  规则包含两个部分,一个是依赖关系,一个是生成目标的方法。

  target.o : target.c target.h

    gcc -c target.c -o target.o

  文件target.o依赖于target.c和target.h的文件,如果target.c和target.h的文件日期比target.o文件日期新,或是target.o不存在,那么依赖关系发生。

 

二、隐晦规则(make的隐含规则 数据库可以用make -p命令打印)。

  一个目标依赖的所有条件不一定非得写在一条规则中,也可以拆开写(若一个目标拆开写多条规则,其中只允许一条规则有命令列表,其它规则应该没有命令列 表,否则make会报警告并且采用最后一条规则的命令列表)。

  target.o : target.h

  target.o : target.c

      gcc  -c  target.c  -o  target.o

  make有自动推导的功能,利用隐晦规则可以简略书写Makefile。

  上述等价于:target.o:target.h (没有编译命令时,makefile会尝试内建的隐含命令)

  隐含规则中使用的变量分成两种:一种是命令相关的,如“CC”;一种是参数相的关,如, “CFLAGS”。

关于命令的变量:AR  函数库打包程序。默认命令是“ar”。  AS  汇编语言编译程序。默认命令是“as”。 CC  C语言编译程序。默认命令是“cc”。 CXX  C 语言编译程序。默认命令是“g ”。 CO  从 RCS文件中扩展文件程序。默认命令是“co”。 CPP  C程序的预处理器(输出是标准输出设备)。默认命令是“$(CC) –E”。 FC  Fortran 和 Ratfor 的编译器和预处理程序。默认命令是“f77”。 GET  从SCCS文件中扩展文件的程序。默认命令是“get”。  LEX  Lex方法分析器程序(针对于C或Ratfor)。默认命令是“lex”。 PC  Pascal语言编译程序。默认命令是“pc”。 YACC  Yacc文法分析器(针对于C程序)。默认命令是“yacc”。 YACCR  Yacc文法分析器(针对于Ratfor程序)。默认命令是“yacc –r”。 MAKEINFO  转换Texinfo源文件(.texi)到Info文件程序。默认命令是“makeinfo”。 TEX  从TeX源文件创建TeX DVI文件的程序。默认命令是“tex”。 TEXI2DVI  从Texinfo源文件创建军TeX DVI 文件的程序。默认命令是“texi2dvi”。 WEAVE  转换Web到TeX的程序。默认命令是“weave”。 CWEAVE  转换C Web 到 TeX的程序。默认命令是“cweave”。 TANGLE  转换Web到Pascal语言的程序。默认命令是“tangle”。 CTANGLE  转换C Web 到 C。默认命令是“ctangle”。 RM  删除文件命令。默认命令是“rm –f”。

关于命令参数的变量: 下面的这些变量都是相关上面的命令的参数。如果没有指明其默认值,那么其默认值都是空。
ARFLAGS  函数库打包程序AR命令的参数。默认值是“rv”。 ASFLAGS  汇编语言编译器参数。(当明显地调用“.s”或“.S”文件时)。  CFLAGS  C语言编译器参数。 CXXFLAGS  C 语言编译器参数。 COFLAGS  RCS命令参数。  CPPFLAGS  C预处理器参数。( C 和 Fortran 编译器也会用到)。 F, FLAGS  Fortran语言编译器参数。 GFLAGS  SCCS “get”程序参数。 LDFLAGS  链接器参数。(如:“ld”) LFLAGS  Lex文法分析器参数。 PFLAGS  Pascal语言编译器参数。 RFLAGS  Ratfor 程序的Fortran 编译器参数。 YFLAGS  Yacc文法分析器参数。

三、变量的定义。

  在Makefile中我们要定义一系列的变量,当Makefile被执行时,其中的变量都会被扩展到相应的引用位置。

  3.1  如环境中定义了环境变量MAKEFILES,make会把这个变量中的值做一个类似于include的动作。这个变量中的值是其它的Makefile,用空格分隔。它和include不同的是,从这个环境变中引入的Makefile的“目标”不会起作用,如果环境变量中定义的文件发现错误,make也会不理。建议不要使用这个环境变量,这个变量被定义后,当你使用make时,所有的Makefile都会受到它的影响。

  3.2 常规变量(“替代”原理)

 

    变量声明时需要赋初值,在使用时,要在变量名前加“$”符号,最好"()"或是“{}”把变量给包括起来。若要使用真实的“$”字符,需用“$$”表示。

    有如下3种:1、变量赋值成一个常量(vars =  program.o foo.o utils.o);2 变量赋值成变量(变量是可以使用后面的变量来定义)(vars1 = $(vars2));3 变量赋值成变量(变量只能使用前面的变量来定义)(vars1 := $(vars));4根据条件赋值(以前不存在赋值则赋值)(vars3 ?= $(vars))

    注:"="和还有追加的意思。变量之前没被定义,“ =”会自动变成“=”,如果有,那么“ =”会继承前次操作的赋值符。若前次是“:=”,那么“ =”会以“:=”作为其赋值符。

    上述已经说明了:makefile第一步是建立起一个完整的依赖关系图(“=”在第一步只建立关系,“:=”在第一步遇值展开)

    一个变量的值从定义它的’=‘或者’:=‘后边的第一个非空字符开始,直到注释或者换行前结束。(如下定义空格)

        nullstring :=

        space := $(nullstring) #end 

  3.3 自动变量

    $@:规则中的目标文件集

    $%:规则中的目标是函数库文件集(如果一个目标是"foo.a bar.o",那么,"$%"就是"bar.o","$@"就是"foo.a")

    $<:规则中的目标依赖的第一个依赖。如果依赖目标是以模式(即"%")定义的,那么"$<"将是符合模式的一系列的文件集(其实是一个一个取出来的)。

    $?:规则中的所有比目标新的依赖目标的集。

    $^:规则中的所有的依赖目标的集合。以空格分隔。如果在依赖目标中有多个重复的,那个这个变量会去除重复的依赖目标,只保留一份。

    $ :规则中的所有的依赖目标的集合。同"$^",只是它不去除重复的依赖目标。

    $*:规则中目标模式中"%"及其之前的部分。如果目标是"dir/a.foo.b",并且目标的模式是"a.%.b",那么,"$*"的值就是"dir/a.foo"。

      注:如果目标中没有模式的定义,那么"$*"也就不能被推导出。如果目标文件的后缀是make所识别的那么"$*"就是除了后缀的那一部分。

          若目标是"foo.c",".c"是make所能识别的后缀名,"$*"的值就是"foo"。这个特性是GNU make的,可能不兼容其它版本make,应尽量避免使用"$*"。

    在上述所列出来的自动量变量中。四个变量($@、$<、$%、$*)在扩展时只会有一个文件,而另三个的值是一个文件列表。这些自动化变量还可以取得文件的目录名或    是在当前目录下的符合模式的文件名,只需要搭配上"D"或"F"字样。这是 GNU make中老版本的特性,在新版本中,我们使用函数"dir"或"notdir"就可以做到了。"D"的含义就是Directory,就是目录,"F"的 含义就是File,就是文件。例:$(@D)"相当于函数"$(notdir $@)"。、$(@F)

  3.4 make命令行设置参数

    若变量是make的命令行参数设置的,那么Makefile中对这个变量的赋值会被忽略。想在Makefile中设置这类参数的值,可以使用“override”指示符。其语法是:

    override para=value 或者override :para=value

    例子:

    (1)override gao += abc    (2)  gao += abc
        all:                all:
            @echo $(gao)            @echo $(gao)

    同时执行:make gao=12345 (1)结果是  12345 abc;(2)结果是 12345

   3.5 目标变量和模式变量

      目标变量为某个目标设置局部变量(作用范围只在这条规则以及连带规则中,不会影响规则链以外的全局变量的值)。

      模式变量是我们可以给定一种“模式”,可以把变量定义在符合这种模式的所有目标上(make的“模式”一般是至少含有一个“%”的)。

      target: PATA = -g 不管全局的$(PATA)的值是什么,在prog目标,以及其所引发的所有$(CFLAGS)的值都是“-g”。

      %.o : PATA= -O  所有符合以[.o]结尾的目标中规则中$(PATA)的值都是“-O”。

  3.6  变量高级用法

      1.替换变量中共有部分,格式:“$(var:a=b)”或是“${va:a=b}”。含义:把变量“var”中所有以“a”字串“结尾”(“结尾”即“空格”或者“结束符”)的“a”替换成“b”字串。

      2.“静态模式”替换。 $(val:%.o=%.c),这依赖于被替换字串中的有相同的模式.

四、文件指示

  1.在一个Makefile中引用另一个Makefile,就像C语言中的include一样

    在Makefile中引用其他Makefile文件的方法是,使用inclue   filename.mk.

  2.根据某些情况指定Makefile中的有效部分,就像C语言中的预编译#if一样

    “函数”与“条件语句”一同使用

     ifdef

       do_sort func := sort

     else

       func := strip endif

     bar := a d b g q c

      foo := $($(func) $(bar))

    这个示例中,如果定义了“do_sort”,那么$(foo)意思就是对%(bar)排序。没有定义“do_sort”,那么%(foo)意思就是对bar调用strip函数。

  3.还有就是定义一个多行的命令(define和endef)

    define指示符后面跟的是变量的名字,其工作方式和“=”操作符一样。变量的值可以包含函数、命令、文字,或是其它变量。因为命令需要以[Tab]键开头,所以如果你用define定义 的命令变量中没有以[Tab]键开头,那么make就不会把其认为是命令。

    define two-lines
      echo foo
      echo $(bar)
    endef

5、注释。Makefile中只有行注释,和UNIX的Shell脚本一样,其注释是用“#”字符,如果你要在你的Makefile中使用“#”字符,可以用反斜框进行转义,如:“\#”。

 

 

转载于:https://www.cnblogs.com/holens/p/5487984.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值