初学Makefile——基本规则和习惯

13 篇文章 0 订阅
11 篇文章 0 订阅

面试被问到关于Makefile的问题,除了读u-boot和内核的Makefile等机会偶尔接触,根本就不熟悉,说读出个大概意思吧?很多细节不知道又不容易理解,没办法,还是从头动手练一下的好,这个行当,任何时候,不动手都是不行的。

 

可是话说回来,没什么项目什么的怎么找机会练Makefile,干脆就把最简单的程序拆开来,C语言基础知识就不说了,大概意思就是写个小程序,弄几个简单函数比如area()和sum()、print(),分别存在单独的C文件,再让他们都“不辞劳苦”的引用几个基础头文件或者参数设置和宏。

head.h就只直接引用

#include<stdio.h>

parameter.h就是一个

#define PI 3.14

sum是

return a+b;

area是返回圆面积(引用parameter.h)

return PI*D*D;

不怕麻烦的可以自行设计和延展功能,不再赘述。

 

root@v:/usr/local/shellProgram/Project1# ls

 area.c    head.h  main main.c    Makefile  parameter.h sum.c 

 

#Makefile版本一

#定义依赖关系,最终成品main需要依赖如下三个对象

main: main.o sum.o area.o

#上边那个结果的实现过程

       cc -o main main.o sum.o area.o

#同上,main.o对象需要依赖main.c和他引用的head.h,后边跟上实现命令

main.o:main.c head.h

       cc -c main.c

sum.o:sum.c head.h

       cc -c sum.c

area.o:area.c head.h parameter.h

       cc -c area.c

clean:

       rm main main.o sum.o area.o

#注意clean需要单独使用makeclean执行,会删除所有.o文件盒最终的结果main文件

#所有命令都要用tab缩进,注释用#,依赖关系用冒号。依赖多个需要空格分开。

 

 

上边的东西比较简单直观,适合初学者,但是问题也很多,当你打算自己加个print功能进去,打算再加个计算体积函数,在Makefile版本一中要改三处,这在更大的工程中是无法想象的,所以需要进行改进,出现了版本二

 

#Makefile版本二

#定义objects参数(这个参数名自拟,不过为了方便理解,最好是相关单词和简称)

objects = main.o sum.o area.o

 

#引用objects参数,形式为$(objects),把他理解为C语言的宏,文本替换

#将所有用到main.o sum.o area.o的地方直接替换为$(objects)即可

main:$(objects)

       cc -o main $(objects)

main.o:main.c head.h

       cc -c main.c

sum.o:sum.c head.h

       cc -c sum.c

area.o:area.c head.h parameter.h

       cc -c area.c

clean:

       rm main $(objects)

和编程语言类似,所有功能都以人为本,很自然的,这里引入了参数概念,一次定义,多次使用,修改时修改定义即可,是不是很方便呢?

好了,初级Makefile已经完成了,不过如果读过其他的Makefile,会觉得略显冗余,别人的怎么那么简洁呢,这就要提到脚本的潜规则了——引入Makefile版本三

 

#Makefile版本三

 

objects = main.o sum.o area.o

 

main:$(objects)

       cc -o main $(objects)

#除了要你指定最终产出“main”的指令外,其他的CC全都删了

main.o:main.c head.h

sum.o:sum.c head.h

area.o:area.c head.h parameter.h

#伪指令标识.Phony

.Phony:clean

clean:

       -rm main $(objects)


 

潜规则就是那些东西make会自己去寻找自己去编译,不用自己指定命令。

另外就是伪指令了,像clean这种命令你给不依赖其他对象,也不产出任何目标文件,纯粹就是为了执行rm命令而设计。这时候你最好指定clean.Phony

 

最后,两个很重要的需要保持的习惯:

减号“-”,回想u-boot等编译过程,是不是看到一大堆错误出现而脚本依然“风雨无阻”,这就是减号的作用了,他使得即使某处出现错误脚本也能继续运行,对于大型脚本是非常重要的特性,而且加上也没有害处,所以要养成习惯。

如果有一点经验,会发现如果有多个标签,并且不像本例是顺次依赖的,是互相独立的,类似于switch和case的结构,那么脚本默认执行第一个“分支”,为了防止各种意外发生,另外一个好习惯就是永远把clean写最后。

 

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

当然,除了一个目标依赖一群对象以外,也可以一群目标依赖一个对象,比如:

main.o sum.o area.o:head.h

但是回想一下,你又要一对多,又要多对一,眼花缭乱,到时候怎么分辨,可读性太差,就跟你写个C语句不带括号弄了一大堆加减号和星号似的,除非是参加编程大赛,不然害人害己,没有太多现实价值。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值