第15课 - make的隐式规则(上)
第15课 - make的隐式规则(上)
1. 问题
如果把同一个目标的命令拆分的写到不同地方,会发生什么?

执行make all

这个实验表明了:如果同一个目标的命令拆分的写到不同地方,那么 make 会覆盖之前的目标对应的命令,使用最新出现的目标对应的命令。
makefile 中出现同名目标时
— 依赖:
- 所有的依赖将合并在一起,成为目标的最终依赖
— 命令:
- 当多处出现同一目标的命令时,make 发出警告
- 所有之前定义的命令被最后定义的命令取代
注意:当使用 include 关键字包含其它文件时,需要确保被包含文件中的同名目标只有依赖,没有命令;否则,同名目标的命令将被覆盖!
target 的下一行,以 tab 开头,该行也会被当做一条空命令。
下面的示例代码就是当主makefile包含了其它makefile导致目标重名,引发了 bug。


2. 什么是隐式规则(built-in rules)?
(1)make 提供了一些常用的,例行的规则实现
(2)当相应目标的规则未提供时,make 尝试使用隐式规则
思考:下面的 makefile 能成功编译吗?为什么?

对应的源文件如下:
#include <stdio.h> extern void foo(); int main()
{
foo(); return ;
}
main.c
#include <stdio.h> void foo()
{
printf("void foo() : %s\n", "Hello World");
}
func.c
SRCS := $(wildcard *.c)
OBJS := $(SRCS:.c=.o) app.out : $(OBJS)
$(CC) -o $@ $^
$(RM) $^
@echo "Target ==> $@"
Makefile
执行 make app.out 成功得到 app.out 可执行程序。

这个 Makefile 中没有 .o 中间文件对应的规则也没有定义 CC 和 RM 变量,但是 make 成功执行并且生成了最终的 app.out 这个可执行程序。
这表明了 make 调用了隐式规则中的 cc -c -o xx.o xx.c 以及 CC 和 RM 变量。
修改上面的Makefile
SRCS := $(wildcard *.c)
OBJS := $(SRCS:.c=.o) # 这里将 cc 改为 gcc
CC := gcc app.out : $(OBJS)
$(CC) -o $@ $^
$(RM) $^
@echo "Target ==> $@" # 这里手动添加规则,进行验证
%.o : %.c
@echo "my rule"
$(CC) -c -o $@ $^
Makefile(修改)
执行 make app.out 后的输出,这就验证了之前的隐式规则。

3. 总结上面实验的隐式规则
(1)make 提供了生成目标文件的隐式规则
(2)隐式规则会使用预定义变量完成编译工作
make 中的 .VARIABLES 预定义变量中包含了 make 的其它预定义变量
echo "$(.VARIABLES)"

(3)改变预定义变量将部分改变隐式规则的行为
(4)当已经存在自定义规则时,不再使用隐式规则
注:本文整理于《狄泰12月提升计划》课程内容
狄泰QQ群:199546072
第15课 - make的隐式规则(上)的更多相关文章
- 第16课 - make的隐式规则(下)
第16课 - make的隐式规则(下) 1
- makefile如果没有符合的显式规则将会使用隐式规则
举例: 当前目录下有个Makefile和jello.c文件,其中有这样的规则jello.o:%.c %.h Makefile (静态模式规则),表明的含义为:要生成的jello.o目标依赖jello. ...
- 第十五篇 make中的隐式规则概述
前面我们讲到了makefile的依赖拆分的知识,现在可以引申出这样一个问题,如果同一个目标的不同命令拆分的写到不同地方会发生什么?下面我们给出程序和执行结果: 可见后面的命令会覆盖前面的命令, ...
- makefile的隐式规则
target := exe source_code = hello.c OBJS = $(source_code:.c=.o) $(target):$(OBJS) gcc $^ -o $@ clean ...
- 每天多一点(2016.12.04)》Javascript隐式转换
乱想 javascript为什么需要隐式转换?如果没有会出现什么情况? 找了一圈没有看到关于这个的讨论,只好自己研究了,可能不一定正确,自行辨知. 郁闷就是郁闷在好好的,为什么要搞个隐式转换,一般来讲 ...
- Javascript隐式转换
乱想 javascript为什么需要隐式转换?如果没有会出现什么情况? 找了一圈没有看到关于这个的讨论,只好自己研究了,可能不一定正确,自行辨知. 郁闷就是郁闷在好好的,为什么要搞个隐式转换,一般来讲 ...
- C++中的隐式转换和explicit
隐式转换 c++中的数据类型转换分为隐式转换和显示转换: 显示转换即使用static_cast等方法进行转换,相关内容请参考 <C++数据类型转换>: 隐式转换则是编译器完成的,如,boo ...
- 无法执行 varchar 值到 varchar 的隐式转换,原因是,由于排序规则冲突,该值的排序规则未经解析。
SELECT CONVERT(VARCHAR(100), 列名) FROM Table 提示错误: 无法执行 varchar 值到 varchar 的隐式转换,原因是,由于排序规则冲突,该值的排序规则 ...
- Android学习笔记_17_Intent匹配规则(隐式意图)
Android基本的设计理念是鼓励减少组件间的耦合,因此Android提供了Intent (意图) ,Intent提供了一种通用的消息系统,它允许在你的应用程序与其它的应用程序间传递Intent来执行 ...
随机推荐
- web基础(四)严格模式与混杂模式
web基础(四)严格模式与混杂模式 一.介绍 DOCTYPE 标签是一种标准通用标记语言的文档类型声明,它的目的是要告诉标准通用标记语言解析器,它应该使用什么样的文档类型定义(DTD)来解析文档.DO ...
- windows服务器下,mysql运行一段时间之后忽然无法连接,但是mysql服务启动正常
出现这种情况以前都是重启服务器可以解决,但是治标不治本,一段时间之后仍然会出现此问题. 此问题不是mysql应用程序的问题而是windows server system 的配置问题.因此需要修改win ...
- Ubuntu 18.04 安装配置 go 语言
Ubuntu 18.04 安装配置 go 语言 1.下载 下载 jdk 到 Downloands 文件夹下 cd 进入 /usr/local, 创建 go 文件夹, 然后 cd 进这个文件夹 cd / ...
- J20航模遥控器开源项目系列教程(三)开发说明 | 想要自己改造程序,扩充功能,怎么实现?
我们的开源宗旨:自由 协调 开放 合作 共享 拥抱开源,丰富国内开源生态,开展多人运动,欢迎加入我们哈~ 和一群志同道合的人,做自己所热爱的事! 项目开源地址:https://github.com/C ...
- SparkStreaming支持的业务场景
目前而言SparkStreaming 主要支持以下三种业务场景: ➢ 无状态操作:只关注当前的DStream中的实时数据.例如:只对当前DStream中的数据做正确性校验.(下一条与上一条数据无关) ...
- kvm 虚拟机中鼠标不同步的问题解决方法
在<devices>标签下添加 <input type='tablet' bus='usb'/>
- 算法-图(2)Bellman-Ford算法求最短路径
template <class T,class E> void Bellman-Ford(Graph<T,E>&G, int v, E dist[], int path ...
- 从 BIO、NIO 聊到 Netty,最后还要实现个 RPC 框架!
大家好,我是 「后端技术进阶」 作者,一个热爱技术的少年. 觉得不错的话,欢迎 star!ღ( ´・ᴗ・` )比心 Netty 从入门到实战系列文章地址:https://github.com/Snai ...
- 牛客网数据库SQL实战解析(1-10题)
牛客网SQL刷题地址: https://www.nowcoder.com/ta/sql?page=0 牛客网数据库SQL实战解析(01-10题): https://blog.csdn.net/u010 ...
- C#串口通讯,复制粘贴就可用,仅仅介绍怎样最快的搭建一个串口通讯,异常拦截等等需要自己加上
using System; using System.Collections.Generic; using System.IO.Ports; using System.Text; //串口通讯类 pu ...