• makefile的隐式规则


    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的写法。

    .

    /************* 社会的有色眼光是:博士生、研究生、本科生、车间工人; 重点大学高材生、普通院校、二流院校、野鸡大学; 年薪百万、五十万、五万; 这些都只是帽子,可以失败千百次,但我和社会都觉得,人只要成功一次,就能换一顶帽子,只是社会看不见你之前的失败的帽子。 当然,换帽子决不是最终目的,走好自己的路就行。 杭州.大话西游 *******/
  • 相关阅读:
    [译文] 实体与值对象到底是不是一回事?
    实现 WebApi 自托管服务宿主于 WinForms 及其交互
    [译文] C# 8 已成旧闻, 向前, 抵达 C# 9!
    [译文] 为什么你在 C# 里总是应该使用 "var" 关键字
    通过设置iis在局域网中访问网页
    windows 10 安装使用kafka
    ASP.NET Core 2.1 中的 HttpClientFactory (Part 4) 整合Polly实现瞬时故障处理
    ASP.NET Core 2.1 中的 HttpClientFactory (Part 3) 使用Handler实现传出请求中间件
    ASP.NET Core 2.1 中的 HttpClientFactory (Part 2) 定义命名化和类型化的客户端
    Asp.net Core 2.0 OpenId Connect Handler缺失Claims?
  • 原文地址:https://www.cnblogs.com/happybirthdaytoyou/p/11678891.html
Copyright © 2020-2023  润新知