您的位置:首页 > 运维架构 > Linux

跟我一起学Makefile

2014-07-21 13:47 246 查看
Makefile介绍:

      make命令属于gnu工具(gcc,g++,gdb,make,cvs,patch,diff,binutils等),make命令会在当前目录下按顺序查找文件“Makefile”、“makefile”、“GNUmakefile”,也可以使用其他的名字来书写Makefile,需要再make后面使用
“-f”、“-file”参数来指定文件名,如:make -f Make.Linux;每条规则中的命令和操作系统 Shell的命令行是一致的。make会一按顺序一条一条的执行命令,每条命令的开头必须以[Tab]键开头,除非 命令是紧跟在依赖规则后面的分号后的。在命令行之间中的空格或是空行会被忽略,但是如果该空格或空行是以Tab键开头的,那么make会认为其是一个空命令。

GNU的make工作时的执行步骤入下:(想来其它的make也是类似)

1)、读入所有的Makefile。

2)、读入被include的其它Makefile。

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

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

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

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

7)、执行生成命令。

一、自动化变量:

$^:代表所有依赖的文件

$@:代表目标

$<:代表第一个依赖的文件

       大多说的c/c++编译器都支持一个”-M“的选项,即自动寻找文件中依赖的头文件,如果使用的是GNU的c/c++编译器,需要使用”-MM“参数,否则”-M“会将

标准库的头文件包含进来

二、静态模式与多目标

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

targets定义了一系列的目标文件,可以有通配符。是目标的一个集合。
target-parrtern是指明了targets的模式,也就是的目标集模式。
prereq-parrterns是目标的依赖模式,它对target-parrtern形成的模式再进行一次依赖目标的定义。

例1:展开:

obj
= foo.o bar.o foo.o:foo.c

all:
$(obj) $(CC) -c $(CFLAGS) foo.c -o foo.o

$(obj):
%.o : %.c =>
bar.o: bar.c

$(CC)
-c $(CFLAGS) $< -o $@ $(CC) -c $(CFLAGS) bar.c -o bar.o

注:上面的例子中,指明了我们的目标从$object中获取,“%.o”表明要所有以“.o”结尾的目标,也就是“foo.o
bar.o”,也就是变量

$object集合的模式,而依赖模式“%.c”则取模式“%.o”的“%”,也就是“foo
bar”,并为其加下“.c”的后缀,于是,我们的依赖目标

就是“foo.c bar.c”。

例2:

files
= foo.elc bar.o lose.o

$(filter
%.o,$(files)): %.o :%.c

$(CC)
-c $(CFLAGS) $< -o $@

$(filter
%.elc,$(files)): %.elc:%.el

emacs
-f batch-byte-compile

注:$(filter
%.o,$(files))表示调用Makefile函数,过滤”$filter“集合,只要其中模式为"%.o"的内容

三、 清空目标文件的规则:

每个Makefile中都应该有一个清空目标文件(.o)的规则,这不仅便于重新编译,也很利于保持文件的清洁;

1、clean:

       rm  edit $(obj)

2、更为稳健的方式

     
.PHONY: clean

clean:

-rm edit $(obj)

      .PHONY表示clean是一个“伪目标”在行前面加上 “-”表示即使出问题,略过,仍要继续后面的操作。clean 最好放在Makefile的最后。”make 

clean" 将清除所有被清除的文件。”cleanobj“ 和 ”cleandiff“这两个伪目标有点像子程序。可以通过输入”make cleanall“和 ”make cleanobj“以

及”makediff“来达到清除不同类文件的目的 

三、引用其他Makefile

  1)include <filename>    #filename  可以是当前操作系统Shell的文件模式(可以保含路径和通配符)

 如: include foo.mk

    注:在include前面可以有一些空字符,但是绝不能是[Tab]键开始。

三、在规则中引用通配符

  和shell相同make支持“*”,“?”,“[...]”三个通配符。

  obj = *.o    #表示obj的值为"*.o",并不是所有的 .o文件,如果想代表所有的.o文件则 obj = $(wildcard *.o)

  注:在Makefile中的命令,必须要以[Tab]键开始,Makefile第一次编译的错误不会为致命错误,会在整个

Makefile编译结束,再次重新编译错误位置,如果还未通过则生成致命错误

4、shell函数 (:来自 《跟我一起写Makefile》)

     shell函数与其他函数不同,它的参数应该就是linux命令。shell函数把执行操作系统命令后的输出作为函数返回值。如:

   contents:=$(shell cat foo)     或者  files:=$(shell echo *.c)

   注意,这个函数会生成一个shell程序执行命令,所以你要注意其运行性能,如果在Makefile中有比较复杂的规则,并且大量使用该函数,那么对于你的系统性能是有害的

特别的是Makefile的隐晦的规则可能会让你的shell函数执行的次数比你想象的多得多。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  makefile linux