第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 中间文件对应的规则也没有定义 CCRM 变量,但是 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的隐式规则(上)的更多相关文章

  1. 第16课 - make的隐式规则(下)

    第16课 - make的隐式规则(下) 1

  2. makefile如果没有符合的显式规则将会使用隐式规则

    举例: 当前目录下有个Makefile和jello.c文件,其中有这样的规则jello.o:%.c %.h Makefile (静态模式规则),表明的含义为:要生成的jello.o目标依赖jello. ...

  3. 第十五篇 make中的隐式规则概述

      前面我们讲到了makefile的依赖拆分的知识,现在可以引申出这样一个问题,如果同一个目标的不同命令拆分的写到不同地方会发生什么?下面我们给出程序和执行结果:   可见后面的命令会覆盖前面的命令, ...

  4. makefile的隐式规则

    target := exe source_code = hello.c OBJS = $(source_code:.c=.o) $(target):$(OBJS) gcc $^ -o $@ clean ...

  5. 每天多一点(2016.12.04)》Javascript隐式转换

    乱想 javascript为什么需要隐式转换?如果没有会出现什么情况? 找了一圈没有看到关于这个的讨论,只好自己研究了,可能不一定正确,自行辨知. 郁闷就是郁闷在好好的,为什么要搞个隐式转换,一般来讲 ...

  6. Javascript隐式转换

    乱想 javascript为什么需要隐式转换?如果没有会出现什么情况? 找了一圈没有看到关于这个的讨论,只好自己研究了,可能不一定正确,自行辨知. 郁闷就是郁闷在好好的,为什么要搞个隐式转换,一般来讲 ...

  7. C++中的隐式转换和explicit

    隐式转换 c++中的数据类型转换分为隐式转换和显示转换: 显示转换即使用static_cast等方法进行转换,相关内容请参考 <C++数据类型转换>: 隐式转换则是编译器完成的,如,boo ...

  8. 无法执行 varchar 值到 varchar 的隐式转换,原因是,由于排序规则冲突,该值的排序规则未经解析。

    SELECT CONVERT(VARCHAR(100), 列名) FROM Table 提示错误: 无法执行 varchar 值到 varchar 的隐式转换,原因是,由于排序规则冲突,该值的排序规则 ...

  9. Android学习笔记_17_Intent匹配规则(隐式意图)

    Android基本的设计理念是鼓励减少组件间的耦合,因此Android提供了Intent (意图) ,Intent提供了一种通用的消息系统,它允许在你的应用程序与其它的应用程序间传递Intent来执行 ...

随机推荐

  1. 区分多个web driver实例

    固然可以用加载不同cookie的办法,让3个帐号共享一个web driver登陆,但总感觉切换麻烦,干脆用了3个web driver实例.问题来了,如何区分?不是说程序里如何区分,机器比人聪明,知道外 ...

  2. 基于ABP做一个简单的系统——实战篇:4.基于富文本编辑器,Razor模板引擎生成内容并导出Word 填坑记录

    起因 需求是这样的,有一种协议需要生成,协议的模板是可配置的,在生成过程中,模板中的内容可以根据约定的标记进行替换(就像mvc的razor模板一样).生成后的内容还需要导出成word或pdf. 常见的 ...

  3. SpringMVC关于拦截器的使用

    这个是基于之前的视图定位进行的. @ 目录 拦截器类:IndexInterceptor 配置拦截器 修改 index.jsp 效果 拦截器类:IndexInterceptor package inte ...

  4. MySQL数据库时间字段按年月日显示并多字段去重查询

    应用服务长久运行,难免要导出一些统计报表. 现在有一个日志表,记录了各种日志,需要导出十月份的登录日志,要求时间按日期显示,且每天用户登陆要去重. 先看日志表的字段构成: logType等于2的是登陆 ...

  5. 操作系统-I/O(2)设备的分配

    作业执行前对设备提出申请时,指定某台具体的物理设备会让设备分配变得简单,但如果所指定设备出现故障,即便计算机系统中有同类设备也不能运行 设备独立性:用户通常不指定物理设备,而是指定逻辑设备,使得用户作 ...

  6. 关于ACID,BASE和CAP定理的探究

    前言 当我看到"根据CAP理论,由于分布式系统必须保证分区容错性,所以只能选择AP原则或者CP原则"这种结论时,我感到很疑惑: 什么是分区容错性? 为什么分布式系统必须保证分区容错 ...

  7. python open函数初习

    open("路径","打开方式")  打开方式:'r'只读模式,‘w’写模式,‘a’追加模式 ‘b’二进制模式,‘+’读/写模式.例: fh=open(&quo ...

  8. 微信支付宝个人免签约即时到帐接口开发附demo

    支付界面: 扫码支付界面: 付成功后可以跳转到你程序指定的地址! demo: http://likeyunba.com/WeChat-Pay/

  9. 区块链入门到实战(35)之Solidity – 变量作用域

    局部变量的作用域仅限于定义它们的函数,但是状态变量可以有三种作用域类型. Public – 公共状态变量可以在内部访问,也可以通过消息访问.对于公共状态变量,将生成一个自动getter函数. Inte ...

  10. asyncio系列之Lock实现

    import types import select import time import socket import functools import collections class Futur ...