target := exe

source_code = hello.c

OBJS = $(source_code:.c=.o)

$(target):$(OBJS)
gcc $^ -o $@ clean:
$(RM) $(target) $(OBJS)

一上来直接展示一份makefile代码。

功能: 从功能角度来说,这份makefile代码可以编译出对应的目标文件,并且顺利执行。

思考: 这其实是一份质量不合格的makefile代码。请仔细观察。

。。。。 什么 ?  你看着这个makefile却一点都不觉得奇怪吗?(好吧,难道你平时写makefile都是这样写的?  )

下面我们通过实验来讲解。

做点简单修改,还是上面这份makefile,只修改编译器, 更换为交叉编译器来试试,贴代码:

target := exe

source_code = hello.c

OBJS = $(source_code:.c=.o)

$(target):$(OBJS)
/usr/external-toolchain/bin/arm-linux-gnueabi-gcc $^ -o $@ clean:
$(RM) $(target) $(OBJS)

功能:请问现在更换为交叉编译器,还能编译出正确的目标文件吗?

编译观察:

令人吃惊的答案:编译报错!

解答:

 当前截图make报错显示:不是有效格式的.o文件。 
这里的玄机是makefile的一个暗黑操作:隐式规则。 

做一下简单修改即可:使用预定义的CC 这会改变隐式规则的行为。修改为如下图所示代码:

target := exe

CC := /usr/external-toolchain/bin/arm-linux-gnueabi-gcc

source_code = hello.c

OBJS = $(source_code:.c=.o)

$(target):$(OBJS)
$(CC) $^ -o $@
clean:
$(RM) $(target) $(OBJS)

这样就能顺利编译出目标文件了。

虽然可以通过增加CC变量进行简单修改,达到顺利生成目标文件的目的,但是这样的makefile仍旧不被推荐使用,因为使用了有可能产生隐式规则行为的代码

这里通过使用CC变量能够顺利编译出目标文件, 本质还是使用了隐式规则,即makefile在执行make对应的规则内的命令时,发现却没有有效的汇编文件:

于是通过默认的gcc编译器尝试将本地的XX.c文件去编译为XX.o文件。

如果本地没有XX.c文件,有一个XX.p或者XX.cpp文件,make的这种隐式规则也会去将其编译为汇编文件。

如果XX.p和XX.cpp同时存在,是选择XX.p还是XX.cpp,这由make的隐式规则决定。

可以通过 make -p|grep "文件格式" 查看隐式规则的这部分相关内容:

 上面是正面讲解makefile隐式规则, 下面我侧面证明一下makefile隐式规则的存在。 
还是使用这份代码来分析。注意:我们使用的编译器是交叉编译器哦!
 
 虽然make这个makefile时报错,但还是生成了hello.o(我自己先写一个hello.c放在与makefile的同一路径下), 我们来打印一下这个hello.o的部分二进制:
 
 完成了上面的步骤,我们直接手动使用gcc编译出一个汇编文件: 
 
 观察总结:
我们这份makefile内根本就没有出现使用gcc的代码啊,我们使用的是交叉编译器啊!,竟然出现了gcc编译出来的汇编文件! 这说明什么?
这说明当前的这份makefile在make后发生了隐式规则的执行!
makefile的隐式规则是大型makefile工程应注意极力避免的,这很可能导致无法解决的bug!大家需要了解一下makefile的隐式规则,避免写下的makefile出现隐式规则的行为
 
这也是本博客最开头的例子使用gcc没暴露出问题的原因,换成交叉编译器去尝试后,就会发现问题所在。
 
总结:
 
重点是要先生成有效的依赖。本例的最佳改进是再增加一条包含%.o:%.c 的规则去得到有效的汇编文件。参考我之前的makefile博客,那里有正规的makefile的写法。

.

makefile的隐式规则的更多相关文章

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

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

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

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

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

    第15课 - make的隐式规则(上) 1. 问题 如果把同一个目标的命令拆分的写到不同地方,会发生什么? 执行make all 这个实验表明了:如果同一个目标的命令拆分的写到不同地方,那么 make ...

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

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

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

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

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

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

  7. MySQL隐式转化整理

    MySQL隐式转化整理 前几天在微博上看到一篇文章:价值百万的 MySQL 的隐式类型转换感觉写的很不错,再加上自己之前也对MySQL的隐式转化这边并不是很清楚,所以就顺势整理了一下.希望对大家有所帮 ...

  8. 利用UICollectionViewFlowLayout的隐式动画实现UICollectionView的layout的动画调整(外加放大指定cell效果)

    前几天在gitHub看到个不错的效果,就是DaiExpandCollectionView,效果如图:   所以赶紧下下来源码看看他怎么实现的,打开源码看了半天,发现他没写什么关于动画的代码啊... 经 ...

  9. 深入理解javascript原型和闭包(4)——隐式原型

    注意:本文不是javascript基础教程,如果你没有接触过原型的基本知识,应该先去了解一下,推荐看<javascript高级程序设计(第三版)>第6章:面向对象的程序设计. 上节已经提到 ...

随机推荐

  1. 网站seo整站优化有什么优势

    http://www.wocaoseo.com/thread-314-1-1.html       现在很多企业找网络公司做网站优化,已经不再像以前那样做目标关键词,而是通过整站优化来达到企业营销目的 ...

  2. 把Autofac玩的和javaSpring一样6

    大家好,今天来介绍我开源的一个autofac.Annotation项目 源码:https://github.com/yuzd/Autofac.Annotation 本项目是autofa的一个扩展组件, ...

  3. Python错误,pip安装包或更新时因超时而报错误

    报错原因 想要使用pip,结果出下以下警告: 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做案例的人,却不知道如何去学习更加高 ...

  4. playable

    探索TimelinePlayableAPI,让Timeline为所欲为 https://blog.csdn.net/qq826364410/article/details/80534892 Playa ...

  5. IOS 打包相关

    Unity 导出的Xcode工程 http://gad.qq.com/article/detail/29330 [Unity3D]Unity 生成的XCode工程结构 http://blog.163. ...

  6. vue学习笔记一

    vue 颠覆式的开发方式 解疑 为什么要学习vue? 降低项目的复杂度 就业需要 vue难不难? 特别简单 相比于React,vue有什么优势? 前端三大框架:Angular.React.Vue Vu ...

  7. java初探(1)之防止库存为负以及防超买

    在秒杀业务中,会出现当只剩一个库存时,但有多个人仍然秒杀成功,且都减库存成功,因此,在减库存,更新数据库的时候,需要在sql语句上进行判断,是否库存大于0. @Update("update ...

  8. 一个后端开发的 Vue 笔记【入门级】

    一 前言 最近找了些教程,顺带着趴在官网上,看了看 Vue 的一些内容,入门的一些概念,以及基础语法,还有一些常用的操作,瞄了一眼,通篇文字+贴了部分代码 9000 多字,入门语法什么的还是很好理解的 ...

  9. SSM整合+WebUpload使用(spring+springmvc+mybatis+maven)

      SSM框架整合以及webupload的集成与使用 在项目中最近用到了webupload.js,也方方面面遇到了不少问题,比如上传文件前对表单参数校验,当校验失败不予提交,及在文件上传成功后,选择同 ...

  10. 19_Python算法

    1.冒泡算法 list = [1, 5, 2, 6, 9, 3, 4, 0] print(len(list)) # conunt = 1 while conunt < len(list): fo ...