makefile(06)_隐式规则

15.Make的隐式规则

15.1.命令覆盖

问题1:通过各目标的命令拆分写到不同的地方,会发生什么?
Makefile中出现同名目标时:
依赖:所有的依赖将合并到一起,成为目标的最终依赖
命令:当多处出现同一目标的命令时,make发出警告,所有之前定义的命令被最后的命令取代。
注意:
当使用include包含其他文件(makefile)时,需要确保被包含的文件中的同名目标只有依赖,没有命令;否则,同名目标的命令将被覆盖!

15.2.隐式规则

Make中提供了一些常用的,例行的规则实现,当目标的规则未提供时,make尝试使用隐式规则
下面的代码可以编译成功吗?为什么?
SRCS := $(wildcard *.c)
OBJS := $(SRCS:.c=.o)

app.out : $(OBJS)
$(CC) -o [email protected] $^
$(RM) $^
@echo "Target ==> [email protected]"

%.o : %.c
@echo "my rule"
$(CC) -c -o [email protected] $^
根据我们的初步分析,上面的Makefile中存至少两个问题:
1.没有定义CC 和RM变量而直接使用
2.没有定义生成.o文件的规则(只有链接没有编译)
运行结果:

为什么可以成功运行,原因在于make中的隐式规则。
Make中提供了生成目标文件的隐式规则,会使用预定义变量完成编译工作;
改变预定义变量间部分改变隐式规则的行为,当存在自定义规则时,不再使用隐式规则。

16.Make的隐式规则

16.1.隐式规则的弊端

目标的依赖不存在时,make会尝试通过依赖名逐一查找隐式规则,并通过依赖名推导出可能的源文件。

这种行为看起来简化了makefile的写法,但可能会带来意想不到的问题。
隐式规则副作用:
编译行为难以控制,大量使用隐式规则可能产生意想不到的编译行为
编译效率低下:make从隐式规则和自定义规则中选择最终的规则
举例说明:
makefile:
app.out : main.o func.o
$(CC) -lstdc++ -o [email protected] $^
main.c:
#include <stdio.h>
extern void greeting();
int main()
{
greeting();

return 0;

}
由于我们并没有定义greeting这个函数,所以我们猜测编译时会报告链接错误,找不到greeting这个符号。
实际输出结果:

我们看到这里直接使用func.p文件生成func.o文件,但由于我的环境中没有安装pc这个软件,所以报错。整个过程完全和我们预期不同。
隐式规则链:
当依赖的目标文件不存在时,make会极力组合各种隐式规则对目标进行创建,进而产生意料之外的编译行为!
例:需要名为N.o的目标:N.y --> N.c --> N.o
我们可以直接使用make -p命令来查看所有的隐式规则,

16.2.隐式规则的禁用

1.局部禁用:在Makefile中自定义规则,如定义一个只有目标和依赖,没有命令的规则,如:
%.o : %.p
这样就可以使用我们自定义的规则,而非隐式规则
2.全局禁用
make -r
显然这种简单实用,推荐使用

16.3.后缀规则

后缀规则时旧式的“模式规则”,可以通过后缀描述的方式自定义规则
1.双后缀规则:定义一对文件后缀(依赖文件后缀和目标文件后缀)
如: .cpp <---> %.o : %.cpp
2.单后缀规则:定义单个文件后缀(源文件后缀)
如: .c <---> % : %.c
注意:
后缀规则中不允许有依赖,后缀规则必须有命令,否则无意义
已经逐步被模式规则替代,建议直接使用模式规则

原文地址:http://blog.51cto.com/11134889/2108284

时间: 2024-11-13 21:56:07

makefile(06)_隐式规则的相关文章

Makefile中的隐式规则

Makefile中的隐式规则 1.隐式规则中的变量 隐式规则中使用的变量分成两种:一种是命令相关的,如"CC":一种是参数相关的,如"CFLAGS". 与命令相关的变量 变量 含义 AR 函数库打开包程序.默认命令是"ar" AS 汇编语言编译程序.默认命令是"as" CC C语言编译程序.默认命令是"cc" CXX C++语言编译程序.默认命令是"g++" CO 从RCS文件中扩展文件

make 的隐式规则(十一)

如果我们将同一个目标的命令拆分的写到不同地方,会发生什么呢?我们来看看下面的代码 .PHONY : all all :     @echo "command-1" VAR := test          all :     @echo "all : $(VAR)" 我们来分析下,这份代码中有两个目标 all,那么我们在执行 make 的时候.它到底是执行哪个呢?一个可能是两个都执行,另一个就是执行第一个,因为默认的是执行第一个目标.下来我们来看看执行结果 我们看到

第15课 - make的隐式规则(上)

第15课 - make的隐式规则(上) 1. 问题 如果把同一个目标的命令拆分的写到不同地方,会发生什么? 执行make all 这个实验表明了:如果同一个目标的命令拆分的写到不同地方,那么 make 会覆盖之前的目标对应的命令,使用最新出现的目标对应的命令. makefile 中出现同名目标时 - 依赖: 所有的依赖将合并在一起,成为目标的最终依赖 - 命令: 当多处出现同一目标的命令时,make 发出警告 所有之前定义的命令被最后定义的命令取代 注意:当使用 include 关键字包含其它文

C# - 接口_隐式接口实现

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 接口_隐式接口实现 7 { 8 // 定义接口1 : IChineseGreeting 9 interface IChineseGreeting 10 { 11 void SayHello(); 12 } 13 14 // 定义接口2 : IAmericanGreeting 15 i

数往知来 JQuery_选择器_隐式迭代_链式编程 &lt;二十&gt;

一.通过js实现页面加载完毕执行代码的方式与jquery的区别 1.通过jquery的方式可以 让多个方法被执行,而通过window.onload的方式只能执行最后一个, 因为最后一次注册的方法会把前面的方法覆盖掉 1. window.onload需要等待页面的所有元素资源比如说img里的图片一些连接等等都下载完毕后才会触发: 2. 而jquery只要页面的标签元素都下载完毕就会触发了 二.$.map(数组,function(ele,index){})函数对数组进行遍历,遍历之后会返回一个新的数

make--隐式规则 路径搜索及实例

一.隐式规则 问题一 .PHONY : all all: @echo "command-1" VAR:=test all: @echo "all:$(VAR)" make之后的结果如图所示可以得出的结论是A.makefile中出现同名目标时依赖:所有的依赖将合并在一起,成为目标的最终依赖命令:当多处出现同一目标时,make发出警告:所有之前定义的命令被最后定义的命令取代注意:当使用include关键字包含其他文件时,需要确保被包含文件中的同名目标只有依赖,没有命令:

oracle数据类型及其隐式转换

oracle有三种最基本的数据类型,即字符型.数值型.日期型. oracle提供的单行函数中,针对不同的数据类型,提供大量实用的函数,同时提供一系列数据类型转换函数,如下: 1)to_char     数值.日期->字符型     语法:to_char(num|date,[format mask],[nls_parameters])     参数:num|date 待转换的数值或者日期             format mask:可选参数 数字->字符型的可用格式 格式元素 元素说明 格式

转载:深入理解Scala的隐式转换系统

摘要: 通过隐式转换,程序员可以在编写Scala程序时故意漏掉一些信息,让编译器去尝试在编译期间自动推导出这些信息来,这种特性可以极大的减少代码量,忽略那些冗长,过于细节的代码. 使用方式: 1.将方法或变量标记为implicit 2.将方法的参数列表标记为implicit 3.将类标记为implicit Scala支持两种形式的隐式转换: 隐式值:用于给方法提供参数 隐式视图:用于类型间转换或使针对某类型的方法能调用成功 隐式值: 例1:声明person方法.其参数为name,类型String

Scala隐式转换

概述 简单说,隐式转换就是:当Scala编译器进行类型匹配时,如果找不到合适的候选,那么隐式转化提供了另外一种途径来告诉编译器如何将当前的类型转换成预期类型.本文原文出处: http://blog.csdn.net/bluishglc/article/details/50866314 严禁任何形式的转载,否则将委托CSDN官方维护权益! 隐式转换有四种常见的使用场景: 将某一类型转换成预期类型 类型增强与扩展 模拟新的语法 类型类 语法 隐式转换有新旧两种定义方法,旧的定义方法指是的"impli