makefile 书写规则和书写命令

makefile 书写规则

makefile中应该有一个目标

其他的目标是被这个目标所连带出来的,如果有很多个目标,那么make的第一个目标会称为最终目标

规则举例:

foo.o:foo.c defs.h #foo模块
    cc -c -g foo.c

这个规则告诉我们两件事情:

1.文件的依赖关系foo.o 依赖于foo.c和defs.h沃尔玛可哦啊吗。如果foo.c和defs.h文件日期要比foo.o的文件日期要新,或者是foo.o并不存在,那么发生依赖关系

2.如果生成foo.o文件,也就是那个cc指令,其说明了如何生成foo.o这个文件(当然foo.c文件include了defs.h文件)

5.3在规则中使用通配符

如果我们想定义一系列比较类似的文件。我们很自然而然的使用通配符。make 中支持三种通配符%,×

比如*.c 标识后缀为c的文件

首先来看几个例子

clean:

    rm -f *.o

上面这个例子不多说,这是操作系统的通配符,这是在命令中的通配符

print:*.c
    lpr -p $?
    touch orubt

上面这个例子说明了通配符也在我们的规则中,目标依赖于printf 所有的[.c]文件,其中$是一个自动化变量

objects = *.o

上面这个例子objects并不会展开,如果逆向让他展开需要使用

objects := $(wildcard *.o)

这种用法由关键字wildcard指出

5.4 文件搜索

在一些大的工程中,有大量的源文件,我们通常的做法是把这许多的源文件分类,并存放在不同的目
录中。所以,当 make 需要去找寻文件的依赖关系时,你可以在文件前加上路径,但最好的方法是把一个
路径告诉 make ,让 make 在自动去找。
Makefile 文件中的特殊变量 “VPATH” 就是完成这个功能的,如果没有指明这个变量, make 只会在当前的目录中去找寻依赖文件和目标文件。如果定义了这个变量,那么, make 就会在当当前目录找不到的情况下,到所指定的目录中去找寻文件了。

VPATH = src:../headers

上面的定义指定两个目录src接../headers,make会按照这个顺序来查找,目录由冒号分割。

另一个设置文件搜索的路径是使用的make vpath 关键字,这不是变量,这是一个make的关键字

以下的方法有三种

1.vpath <pattern> <dir>

为符合模式的文件制定搜索目录

2.vpath <pattern>

清除复合模式的的文件的搜索目录

3.vpath

清除所有已经被设置好的文件搜索目录

vpath使用需要包含的%字符。%的意思是匹配若干个字符,例如,”%.h”表示所有以.h文件结尾的文件,而directories定义了要搜索的目录。

5.5伪目标

最早我们提出的clean 就是一个伪目标

clean:
    rm *.o temp

伪目标不是一个文件,只是一个标签

PHONY 指明一个目标是伪目标

PHONY :clean
clean:
    rm *.o temp

5.7 静态模式

我们看一个例子:

    objects = foo.o  bar.o

    all:$(objects)

$(objects):%.o:%.c
    $(CC) -c  $(CFLAGS) $ < -o $@

$< 标识所有的依赖集(也就是 foo.c bar.c)。$@表示目标集(foo.o bar.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

5.8 自动生成依赖性

makefile中-M属性可以自动寻找源文件包含的头文件,并且生成一个依赖关系
比如执行

cc -M main.c

其输出的是

main.o : main.c defs.h

这样可以让编译器自己生成依赖规则

%d:%.c

@set -e;rm -f $@;\
$(CC) -M $(CPPFLAGS) $< >$@.$$$$;
rm -f $@.$$$$

6 书写命令

make默认是/bin/sh

@会隐藏命令输出

exec:
    cd /home/hchen
    pwd

exec:
    cd /home/hchen; pwd

6.3 命令出错

如果我们在指令前加入减号,表示不管命令执行成功与失败都默认为成功

我们make的时候有-k 指令 表示不管指令是否成功都继续执行。

6.4嵌套执行make

我们有时候makefile会被分配到多个目录下面 ,我们的总控makefile可以这样写:

subsystem:
    cd subdir && $(MAKE)

等价于:
subsystem:
$(MAKE) -C subdir

我们把这个makefile叫做主控makefile,总控makefile的变量可以传递到下级的makefile中,但是不会覆盖下面的makefile中定义的变量,除非指定了”-e”参数,如果你想把变量传递到下级makefile中

可以声明

export <variable>

如果你不想让某些变量传递到下级:

unexport <variable ...>

例如:

示例一:

export variable = value

其等价于:

variable = value
export variable

其等价于:

export variable := value

其等价于:

variable := value
export variable

示例二:

export variable += value

其等价于:

variable += value
export variable

如果你要传递所有的变量,那么,只要一个export就可以了

我们要注意两个变量,一个是SHELL,一个是MAKEFLAGS,这两个变量不管你是否export都要传递到下层的makefile中,特别MAKEFLAGS其中包含了make的参数信息如果我们执行总控的makefile,上层定义了这个变量,那么它将会传递到下一层,因为他是一个系统级的变量。

但是makefile的几个参数并不往下传递 -C -f -h -o -w

还有一个执行嵌套比较有用的参数,”-w”或者是”-print-directory”会在make的过程中输出一些信息,让你看到当前的工作目录,比如我们make的下级目录是/home/hchen/gnu/make,如果我们使用make -w来执行,那么进入这个目录的时候,我们会看到

make:Entering directory `/home/hchen/gun/make`

而在完成make 离开目录的时候我们会看到

make: Leaving directory `/home/hchen/gnu/make

当你使用-c参数来指定下层makefile的时候,-w总是会被打开,如果参数中有-s,或者是-no-print-directory,那么-w总是失效的。

6.5 定义命令包

如果makefile中出现了一些相同的命令序列,那么我们可以为这些相同的命令定义一个变量,定义变量从define开始到endef结束,如:

define run-yacc
yacc $(firstw ord $^)
mv y.tab.c $@
endef

我们使用这个命令包

foo.c: foo.y
    $(run-yacc)

命令包中的”run-yacc”中的$^忽悠上古foo.y,$@就是foo.c

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值