Makefile基础

Makefile规则

Target:Prerequisites
    command

Target:规则的目标。通常是最后需要生成的文件名或者为了实现这个目标必须的中间过程文件名。可以是.o文件、也可以是最后的可执行程序的文件名等。另外,目标也可以是make执行的动作的名称,如目标“clean”。
Prerequisites: 规则的依赖。生成规则目标所需要的文件名列表。通常一个目标依赖于一个或者多个文件。
command: 规则的命令行。是规则所要执行的动作(任意的shell命令或者是可在shell下执行的程序)。它限定了make执行这条规则时所需要的动作。每一个命令行必须以[Tab]字符开始。

书写时可以将一个较长行使用反斜线()来分解为多行,但是反斜线之后不能有空格。

clean:
    rm a.o b.o c.o d.o \
        e.o f.o

当在shell提示符下输入make命令以后,make读取当前目录下的Makefile文件,并将Makefile文件中的第一个目标作为其执行的“终极目标”(有两种例外情况,1、目标名以点号“.”开始的并且其后不存在斜线“/”;2、模式规则的目标)。在Makefile中一个规则的目标如果不是“终极目标”所依赖的,那么这个规则将不会被执行,除非明确指定执行这个规则(make clean)。

objects = main.o a.o b.o #变量
all: $(objects)
    command

在使用make编译.c源文件时,编译.c源文件规则的命令可以不用明确给出。这是因为make本身存在一个默认的规则,能够自动完成对.c文件的编译并生成对应的.o文件。它执行命令“cc -c”来编译.c源文件。

all : a.o
    cc -c a.c
    cc -o a.out a.o
all : a.o
    cc -o a.out a.o
#以上两条作用相同
.PHONY : clean \\将clean声明为伪目标,避免当磁盘上存在一个名为clean的文件时,目标clean所在规则的命令无法执行
clean :
    -rm edit $(objects)

在一个完整的Makefile中,包含了5个东西:显式规则、隐含规则、变量定义、指示符和注释。

在使用指示符“define”定义一个多行的变量或者命令包时,其定义体(“define”和“endef”之间的内容)会被完整的展开到Makefile中引用此变量的地方(包含定义体中的注释行)。Makefile中变量的引用和C语言中的宏类似,但是实质并不相同。对一个变量引用的地方make所做的就是将这个变量根据定义进行基于文本的展开,展开变量的过程不涉及到任何变量的具体含义和功能分析。

默认情况下,make会在工作目录下按照文件名顺序寻找makefile文件读取并执行,查找的文件名顺序为:“GNUmakefile”(只有GNU make才可以识别)、“makefile”、“Makefile”。
当makefile文件名不是这三个任何一个时,需要通过-f或者–file来指定一个或者多个文件。

“include”指示符告诉make暂停读取当前的makefile,而转去读取“include”指定的一个或者多个文件,完成以后再继续当前的makefile的读取。形式如下:

 include FILENAMES... #以一个或者多个空格开始,切记不能tab字符开始

如果指示符“include”指定的文件名不是以根目录开始,而且当前目录下也不存在此文件,make将根据文件名试图在以下几个目录下查找:首先,查找使用命令行选项“-l”或者“–include-dir”指定的目录,然后继续搜索以下几个目录:“/usr/gnu/include”、“/usr/local/include”、“/usr/include”。
当在这些目录下都没有找到“include”指定的文件时,make将会提示一个包含文件未找到的告警提示,但是不会立刻退出。当完成读取整个makefile后,make将试图使用规则来创建该文件,当不能创建时,make将提示致命错误并退出:

Makefile:错误的行数:未找到文件名:提示信息(No such file or directory)
Make: *** No rule to make target '<filename>'. Stp

通常我们在makefile中使用“-include”来代替“include”(“-”的意思是告诉make,忽略此操作的错误)

  -include FILENAMES... #只有由于不能正确完成终极目标的重建时,才会提示致命错误并退出

如果在当前环境定义了一个“MAKEFILES”环境变量,make执行时首先将此变量的值作为需要读入的makefile文件,类似使用指示符“include”包含其他文件一样。
和使用“include”的区别:
1.环境变量指定的makefile文件的“目标”不会被作为make执行的“终极目标”。如果在make的工作目录下没有一个名为“Makefile”、“makefile”或者“GNUmakefile”的文件,make同样会提示

make:***No targets specified and no makefile found.Stop.

2.环境变量所定义的文件列表,在执行make时,如果不能找到其中某一个文件。make不会提示错误,也不退出。
3.make在执行时,首先读取的是环境变量“MAKEFILES”所指定的文件列表。

make程序在读取多个makefile文件时,包括由环境变量“MAKEFILES”指定、命令行指定、当前工作目录下的默认以及使用指示符“include”指定包含的,在对这些文件进行解析执行之前make读取的文件名将会被自动依次追加到变量“MAKEFILE_LIST”的定义域中。

name1 := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
include inc.mk
name2 := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
all:
    @echo name1 = $(name1)
    @echo name2 = $(name2)

执行make,则看到的将是如下的结果:
name1 = Makefile
name2 = inc.mk

GNU make支持一个特殊的变量,此变量不能通过任何途径给它赋值。它被展开为一个特定的值。一个重要的特殊变量是“.VARIABLES”。它被展开以后是此引用点之前、makefile文件中所定义的所有全局变量列表。包括:空变量(未赋值的变量)和make的内嵌变量,但不包含目标指定的变量,目标指定变量值在特定目标的上下文有效。

Makefile可由其他文件生成。如果Makefile由其他文件重建,那么在make在开始解析这个Makefile时需要重新读取更新后的Makefile。

在有些情况下,存在两个比较类似的makefile文件,其中一个需要使用另外一个中所定义的变量和规则。通常我们会使用include包含来达到目的。但使用这种方式,如果在两个makefile文件中存在相同目标,而在不同的文件中其描述规则使用不同的命令。这样,相同的目标文件就同时存在两个不同的规则命令,这是makefile所不允许的。因此需要定义一个称之为“所有匹配模式”的规则,它用来描述那些在调用文件中没有给出明确创建规则的目标的重建规则。

foo:
    frobnicate > foo
%:force #如果执行make bar,因为没有对应规则,将使用此所有匹配模式规则,其依赖force,保证即使目标文件已经存在也会执行
    @$(MAKE) -f Makefile $@
force:; #使用空命令为了防止make程序试图寻找一个规则去创建目标force时,又使用所有匹配模式规则而陷入无限循环
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值