规则明确在什么情况下,使用什么方法,重构文件,该文件称为目标。

  make的唯一目的是重构终极目标。终极目标默认是第一个目标。

1.

2.规则语法

TARGETS : PREREQUISITES
COMMAND
或者:
TARGETS : PREREQUISITES ; COMMAND
COMMAND

  TARGETS 和 PREEQUISITES 可以是多对多的关系,但通常TARGETS 只代表单个目标。

  每一行COMMAND(没有用;链接情况),make会fork一个进程去执行该命令,命令运行在shell系统之上。  

  规则的中心思想是: 目标文件的内容是由依赖文件文件决定, 依赖文件的任何一处改动,都将导致已经存在的目标文件过期。

  $是特殊字符,代表变量或函数,$$表示$字符。

3.依赖类型

  依赖类型分为普通类型和 order-only 类型。

  普通类型依赖,当这种依赖文件被改动或新增,则认为目标文件已过期。

  order-only类型依赖,这种依赖文件被改动,不会认为目标文件过期。

  格式如下

TARGETS : NORMAL-PREREQUISITES | ORDER-ONLY-PREREQUISITES

  示例

LIBS = libtest.a
foo : foo.c | $(LIBS)
$(CC) $(CFLAGS) $< -o $@ $(LIBS)

4.文件名使用通配符

  可用的通配符有:*,[...],?

  意义和shell的通配符相同。

  make的通配符只能用在两个场景:

(1)目标和依赖处,make在解析阶段展开目标和依赖处的通配符

(2)规则处,在make执行阶段展开。

  其他上下文不能使用通配符,只能用 函数 $(wildcard ) 实现。

5.目录搜索

  (1)VPATH变量(一般性搜索)

  make搜索文件时,现在当前目录搜索,若没有,则在VPATH指定的目录搜索。

  定义VPATH,目录间用空格或冒号分隔

VPATH = src:../headers

  通过VPATH指定的目录,对所有文件都有效,当需要为特定类型文件指定搜索路径时,应使用 vpath

  (2)vpath关键字(选择性搜索)

  vpath不是变量,而是关键字,path有3种使用方式

1、 vpath PATTERN DIRECTORIES
为所有符合模式“ PATTERN”的文件指定搜索目录“ DIRECTORIES”。多个目
录使用空格或者冒号(:)分开。类似上一小节的“ VPATH”变量。
2、 vpath PATTERN
清除之前为符合模式“ PATTERN”的文件设置的搜索路径。
3、 vpath
清除所有已被设置的文件搜索路径。

  PATTERN 表示模式,其中可以使用%,%表示匹配一个或多个字符,如%.h表示所有以.h结尾的文件。如果PATTERN中没有包含%,那他就是明确的文件名。

  vpath示例

vpath %.h ../headers
vpath %.c foo
vpath % blish
vpath %.c bar
表示对所有的.c 文件, make 依次查找目录:“ foo”、 blish”、“ bar”。
而:
vpath %.c foo: bar
vpath % blish
对于所有的.c 文件 make 将依次查找目录:“ foo”、“ bar”、“ blish”

  (3)-INAME(依赖库)

  -INAME 表示以目录搜索的方法添加依赖。

  来看一下详细的过程。 1. make 在执行规则时会在当前目录下搜索一个名字为“ libNAME.so”的文件;

2. 如果当前工作目录下不存在这样一个文件,则make 会继续搜索使用“ VPATH”或者“ vpath”指定的搜索目录。

3. 还是不存在, make将搜索系统库文件存在的默认目录,顺序是:“ /lib”、“ /usr/lib”和“ /usr/local/lib”

                                         如果“ libNAME.so”通过以上的途径最后还是没有找到的话,那么 make 将会按照以上的搜索顺序查找名字为“ libNAME.a”的文件。 

  可以这样使用:

假设你的系统中存在“ /usr/lib/libcurses.a”(不存在“ /usr/lib/libcurses.so”)这个
库文件。看一个例子:
foo : foo.c -lcurses
cc $^ -o $@

  如果libcurses.a更新了,make就会认为 foo过期需要更新。

  之所以 -INAME 会先寻找 libNAME.so ,若没找到再寻找 libNAME.a,是因为环境变量 .LIBPATTERNS

  .LIBPATTERNS 默认值为 lib%.so lib%.a

6.伪目标

  伪目标的目的:

  (1)避免make的目标(只为了执行命令,不生成文件)和工作目录的文件重名。

  (2)提高make的工作效率

   当一个规则的目标为伪目标时,当运行到该规则时,规则的命令一定会被执行。

   且make不会查找伪目标的隐含规则,意味提高了效率。

  伪目标用于并行

SUBDIRS = foo bar baz
subdirs:
for dir in $(SUBDIRS); do \
$(MAKE) -C $$dir; \
done

  上面的make无法并行,因为只有一行,且$(MAKE)出错也不知道。

SUBDIRS = foo bar baz
.PHONY: subdirs $(SUBDIRS)
subdirs: $(SUBDIRS)
$(SUBDIRS):
$(MAKE) -C $@
foo: baz

  如此就能多线程。

  foo: baz 只是为了确定 foo 和 baz的执行顺序,所以无需命令。

7.强制目标

  一个规则没有命令或依赖,并且他的目标不是存在的文件名。在执行此规则时,目标总被认为是最新的,即刚更新过。

  将这个刚更新过的目标做其他目标的依赖,其他目标就一定会被更新。

clean: FORCE
rm $(objects)
FORCE:

  强制目标和.PHONY效果一样,不过.PHONY更好。

8.

9.

10.

11.

12. 静态规则

  语法

TARGETS ...: TARGET-PATTERN: PREREQ-PATTERNS ...
COMMANDS
TAGET-PATTERN”和“ PREREQ-PATTERNS”说明了如何为每一个目标文件
生成依赖文件。从目标模式( TAGET-PATTERN)的目标名字中抽取一部分字符串(称
为“茎”)。使用“茎”替代依赖模式( PREREQ-PATTERNS)中的相应部分来产生对
应目标的依赖文件。下边详细介绍这一替代的过程。

  示例

objects = foo.o bar.o
all: $(objects)
$(objects): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
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 $<
bigoutput littleoutput : %output : text.g
generate text.g -$* > $@
当执行此规则的命令时,自动环变量“ $*”被展开为“茎”。在这里就是“ big”和“ little”。

静态规则通常被其他makefile重复使用,

通常的做法是将生成同一类目标的模式定义在一个 make.rules 的文件中。在工程各个模块的 Makefile 中包含此文件。 

 

13. 双冒号规则

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

  当foo.c更新时,第一个规则的命令会被执行,当bar.c更新时,第二条规则的命令会被执行。

  而如果使用单冒号,则会报错,必须将这两条规则合并,意味只能一种执行命令路线。

《GNU_Makefile》第4章——makefile规则的更多相关文章

  1. Makefile规则③规则语法、依赖、通配符、目录搜寻、目标

    规则语法 通常规则的语法格式如下: TARGETS : PREREQUISITES COMMAND ... 或者: TARGETS : PREREQUISITES ; COMMAND COMMAND ...

  2. Makefile 规则的使用

    1.Makefile格式 //最终目标 all: led.o //依赖 arm-linux-ld -Tled.lds -o led.elf led.o //命令 arm-linux-objcopy - ...

  3. 编写Makefile规则

    一个工程中的源文件不计其数,其按类型.功能.模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作 ...

  4. makefile规则整理

    makefile规则整理 实际开发中,makefile改的多,写的少. 为了后面不要在编译链接这种地方花费太多的时间,在这里系统性的整理其规则: 基本格式 TARGET : PREREQUISITES ...

  5. 《GNU_makefile》第五章——为规则书写命令

    1. 使用make的命令行参数-n或--just-print,make会只显示要执行的命令,不执行,这样方便调试makefile. 2.执行命令 每写一行命令,make会fork出一个shell进程来 ...

  6. 《GNU_makefile》第七章——makefile的条件执行

    条件执行即,通过变量的值,来控制make的执行和忽略. 条件执行只能控制makefile的make语法部分,不能控制shell部分 1.一个例子 - libs_for_gcc = -lgnu norm ...

  7. make的使用和Makefile规则和编程及其基本命令(简单)

      转自:http://blog.chinaunix.net/uid-23929712-id-2650328.html   概述: make从Makefile中文件中获取模块间的依赖关系,判断哪些文件 ...

  8. 【ASM C/C++】 Makefile 规则说明

    make 命令会自动读取当前目录下的 Makefile 文件[31],完成相应的编译步骤.Makefile 由一组规则(Rule)组成,每条规则的格式是:target ... : prerequisi ...

  9. 自动构建Makefile(1)--C/C++编译流程&Makefile规则简介

      前言: 大家在Windows上使用VS构建C/C++程序时,不需要自己编辑略显晦涩的Makefile文件,而对于初学者而言, 他们甚至没意识到它的存在.VS是自动生成Makefile文件, 并构建 ...

随机推荐

  1. linux centos 05

    centos7安装mariadb 1.yum  得配置yum源,配置阿里云的 两个 yum源  ,阿里云的yum源中,会有 mariadb的软件包 阿里云的yum仓库中,mariadb版本如下 mar ...

  2. PHP 超级全局变量 $_GET

    https://www.php.cn/php/php-superglobals.html https://m.php.cn/code/11853.html

  3. spring boot:spring security用mysql实现动态权限管理(spring boot 2.3.3)

    一,动态权限管理的优点和缺点 1,优点: 因为控制权限的数据保存在了mysql或其他存储系统中, 可以动态修改权限控制,无需改动代码和重启应用,  权限变更时灵活方便 2,缺点: 权限的设置需要保存在 ...

  4. spring boot:单文件上传/多文件上传/表单中多个文件域上传(spring boot 2.3.2)

    一,表单中有多个文件域时如何实现说明和文件的对应? 1,说明和文件对应 文件上传页面中,如果有多个文件域又有多个相对应的文件说明时, 文件和说明如何对应? 我们在表单中给对应的file变量和text变 ...

  5. java反射原来是这么玩的(反射一开,谁都不爱)

    反射的发展历史 1996年01月23日,jdk 1.0版本发布,代号为Oak(橡树). 这个代号为Oak(橡树)的版本,在发布后的第二年,1997年02月19日,发布jdk 1.1版本,这次版本发布中 ...

  6. linux硬盘分区及挂载

    今天买的一台服务器发现其硬盘容量与购买界面的描述不符,于是我去问了客服才知道有一块硬盘需要自己挂载,所以记录自己硬盘分区以及挂载操作得此文. 测试环境 ​ 由于时间限制,本人仅在centos 8下测试 ...

  7. 学了那么多 NoSQL 数据库 NoSQL 究竟是啥

    NoSQL 简史 NoSQL 一词最早出现于 1998 年,是 Carlo Strozzi 开发的一个轻量.开源.不提供 SQL 功能的关系数据库. 2009 年,Last.fm 的 Johan Os ...

  8. SPI、I2C、I2S、UART、GPIO、SDIO、CAN、JTAG的区别及使用方法。

    SPI 全称及由来:SPI接口的全称是"Serial Peripheral Interface",意为串行外围接口,是Motorola首先在其MC68HCXX系列处理器上定义的. ...

  9. day77:luffy:导航栏的实现&DjangoRestFramework JWT&多条件登录

    目录 1.导航栏的实现 2.登录前戏:用户表初始化 3.DjangoRestFramework JWT 4.多条件登录 5.登录状态的判断和退出登录 1.导航栏的实现 1.设计导航栏的model模型类 ...

  10. 谈谈nginx和lvs各自的优缺点以及使用

            在最开始呢,咱们先说一下什么叫负载均衡,负载均衡呢,就是将一批请求,根据请求的内容,分发到不同的后端去进行相应的处理,从而提供负载分担,主备切换等功能.                 ...