makefile

来源:互联网 发布:ntfs for mac 激活 编辑:程序博客网 时间:2024/04/18 17:55

综述:

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

  1、显式规则。显式规则说明了,如何生成一个或多的的目标文件。这是由Makefile的书写者明显指出,要生成的文件,文件的依赖文件,生成的命令。
  2、隐晦规则。由于我们的make有自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写Makefile,这是由make所支持的。
  3、变量的定义。在Makefile中我们要定义一系列的变量,变量一般都是字符串,这个有点你C语言中的宏,当Makefile被执行时,其中的变量都会被扩展到相应的引用位置上。
   4、文件指示。其包括了三个部分,一个是在一个Makefile中引用另一个Makefile,就像C语言中的include一样;另一个是指根据某些 情况指定Makefile中的有效部分,就像C语言中的预编译#if一样;还有就是定义一个多行的命令。
  5、注释。Makefile中只有行注释,和UNIXShell脚本一样,其注释是用“#”字符,这个就像C/C++中的“//”一样。如果你要在你的Makefile中使用“#”字符,可以用反斜框进行转义,如:“#”
  最后,还值得一提的是,在Makefile中的命令,必须要以[Tab]键开始。

 

1Makefile中的显示规则

Makefile的执行规则:
  1)如果这个工程没有编译过,那么我们的所有C文件都要编译并被链接。
  2)如果这个工程的某几个C文件被修改,那么我们只编译被修改的C文件,并链接目标程序。
  3)如果这个工程的头文件被改变了,那么我们需要编译引用了这几个头文件的C文件,并链接目标程序。

 

Makefile的书写规则:

      target file1 file2 file 3…..

      command1(得到这个目标文件需要执行的命令)

 

      file1 file4   file 5 file 6……

      command2

      target : prerequisites ; command

 

注:目标文件的依赖关系是一种层次的结构。

     如果冒号后面没接任何文件,makefile不会自动执行这个目标下面的命令。除非在命令窗口显示指定这个目标。Make clean这个功能就是用它实现的。当然,也可以实现其他的一些功能,比如归档。

 

2.隐晦规则

      makefile的自动推导功能

 

 

3变量

     makefile中的变量

     定义变量:Variabae_name = ……..(等号后面是一个字符串,一般是文件的列表或其他)

     使用变量:$(variable_name)  

 

(1) 多行变量

    使用关键字 define,可以定义多行变量,即变量的值不止一行。结束时加上关键字endef。格式:

    define two-lines
  echofoo
  echo$(bar)
    endef

定义了一个变量 two-lines

(2)目标变量

    即只在一个目标和其所引发的规则中起作用,且会覆盖全局的变量。

    target : variable_name = …

(3)系统预定义变量

$@           表示着目前规则中所有的目标的集合, 就像一个数组,“$@”依次取出目标,并执于命令

-$(name,..,..)       执行makefile函数。name是函数名,后面是参数。

$<             表示当前目标的依赖文件集,它从整个依赖文件集里依次取出依赖文件。

$^             表示整个的依赖文件集,除掉重名的文件。

 

4.文件包含

      Makefile使用include关键字可以把别的Makefile包含进来,这很像C语言的#include,被包含的文件会在当前文件的包含位置展开。include的语法是:
  include<filename list>

例子:

        include foo.make  *.mk  $(bar)

        例子中变量bar定义了一个文件名字。*.mk指在所有后缀为mk的文件都会包含(在当前目录、命令行指定的目录、<prefix>/include)。由此可以看出,makefile的文件命名很灵活。如果‘makefile’不是定义的make文件的名字,在使用这个文件时,需要在命令行指定。格式如下:   make  –f filename

       如果有文件没有找到的话,make会生成一条警告信息,但不会马上出现致命错误。它会继续载入其它的文件,一旦完成makefile的读取,make会再重试这些没有找到,或是不能读取的文件,如果还是不行,make才会出现一条致命信息。如果你想让make不理那些无法读取的文件,而继续执行,你可以在 include前加一个减号“-”。如:

  -include<filename>
  其表示,无论include过程中出现什么错误,都不要报错继续执行。和其它版本make兼容的相关命令是sinclude,其作用和这一个是一样的。‘-’可以加到makefile文件中任何处,表达的含义相同。

 

5.其他

 

(1)嵌套执行:进入其他目录并执行目录下的makefile文件

     subsystem:
  cd subdir && $(MAKE)
或:
     subsystem:
     $(MAKE) -C subdir

     其中,subdir是下一级目录的名字。$(MAKE)是进入目录可能需要的参数。

 

    传递变量到下一级目录,

     export variable_name                                             传递变量

     export variable_name = value                                 赋值后再传递变量

     export                                                                     传递所有的变量

    有两个变量,一个是SHELL,一个是MAKEFLAGS,总是要传递到下层Makefile中,特别是MAKEFILES变量,其中包含了make的参数信息。

(2)赋值

   =       右边的值可以是在后面才赋值的变量

  :=       对变量赋值时,只使用在此前已赋值的变量

 +=       将值追加到变量的最后

 ?=      如果左边的变量已定义,则这条语句不做任何动作;否则将右边的值赋给左边变量

(3)伪目标

     不生成目标文件的目标。格式:

      target :

      command

     .PHONY : target

      target :

      command

 

(4)命令执行顺序

      如果你要让上一条命令的结果应用在下一条命令时,你应该使用分号分隔这两条命令。比如你的第一条命令是cd命令,你希望第二条命令得在cd之后的基础上运行,那么你就不能把这两条命令写在两行上,而应该把这两条命令写在一行上,用分号分隔。

(5)命令行

      如果有变量是通常make的命令行参数设置的,那么Makefile中对这个变量的赋值会被忽略。如果你想在Makefile中设置这类参数的值,那么,你可以使用“override”指示符。

     在命令行中可以改变makefile文件中对变量值的设置,格式如下:

      make “variable_name = new_value”

(6)静态模式

    静态模式使用自动变量和通配符,可以将几百个目标的编译规则用很少的代码来实现。很强大的功能。格式,

 

 <targets ...>: <target-pattern>:<prereq-patterns ...>

 

 targets定义了一系列的目标文件,可以有通配符。是目标的一个集合。
 target-parrtern是指明了targets的模式,也就是的目标集模式。

 prereq-parrterns是目标的依赖模式,它对target-parrtern形成的模式再进行一次依赖目标的定义。
  如果我们的<target-parrtern>定义成“%.o”,意 思是我们的<target>集合中都是以“.o”结尾的,而如果我们的<prereq-parrterns>定义成“%.c” 意思是对<target-parrtern>所形成的目标集进行二次定义,其计算方法是,取<target-parrtern> 模式中的“%”(也就是去掉了[.o]这个结尾),并为其加上[.c]这个结尾,形成的新集合。

 

例子:

  objects = foo.o bar.o
  all:$(objects)
  $(objects):%.o: %.c
  $(CC)-c $(CFLAGS) $< -o $@

等效为,

  foo.o : foo.c
  $(CC) -c $(CFLAGS) foo.c -o foo.o
  bar.o : bar.c
  $(CC) -c $(CFLAGS) bar.c -o bar.o

     如果待编译的目标很多,静态模式可以发挥很大的威力。

     %不是通配符。通配符包括:*       

 

通配符在规则中可以自动扩展,但设置在变量中或在函数的参数中通配符一般不能正常扩展

 
原创粉丝点击