分享
 
 
 

全力打造Make程式和重新编译核心技术

王朝other·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

Make通常用来维护程式,使可执行档的内容保持和原始程式的一致性,因其依循唯有变动才需重新编译连结的方式,由各档之间的「依存关系」自动去编译连结,如此可省下了宝贵的时间和系统资源。在Linux中最普遍的例子应是核心(kernel)的重 编,当读者把gcc等程式和核心原始程式安装完後(Slackware中为D套件,SLS中为C和 S套件),便可依实际情况去更新或置换核心的内容。核心是由许多不同的部份所组成 ,如行程的管理、档案系统的支援、周边配备的驱动程式、网路通讯的协定等,当组 成的部分有所更新或是不需要时,就需要重编核心,以便产生符合真实环境的核心程 式,使得PC能得到最佳的利用。如没有SCSI卡的PC便不需要SCSI的驱动程式,而且可 依光碟和音效卡的种类更换不同的驱动程式。如此繁琐的过程,在make的帮助下,可 以作得又快又好,只需透过一连串的选择,其馀就完全交给make去负责,真是省事又 方便。和核心编译有关的细节我们稍後再共同研讨。make的最初目的是帮助程式设计 师作为编译连结时的管理,因此我们先来看看make的用法。

使用时机和环境

当程式写作或是更新後,编连的步骤便是使用make的最好时机。在Linux中,启 动make只消打make便可,make会先去找同目录下的Makefile或是makefile,若找不到 便出现make的参数使用方法。makefile是一个文书档,可用vi或是jed编辑,它可说 是make的script,make就完全依此档的内容来动作。在这个档中,记录了档案的产生 方法、相关性质和一些变数等。在这个档中,凡是以#为开头者,整行都视为注解, 和shell的script

file是相同的。makefile中约略可分成变数区和指令区两部分, 纵贯档案的有依存、字尾等规则,共同构成makefile的语法。

Makefile中的变数

在makefile中可将一字串设定给一变数,需要时可如shell的script

file展开 ,因此也可称为巨集(marco),变数设定的方式为:

变数名称=设定值

除了某些特殊符号外(如#、:、;、=、空白、定位字元、新列字元),其馀都可作 为设定值的内容。一般来说,最好使用英数字,以避免发生不可预料的错误,以下是 一些合法的设定

SOURCE = test1.c test2.c test3.c

OBJ = main.o

当要取用(展开)变数时,只需用()将变数括起来,前头加上$符号即可,如$(OBJ) 这个变数,当make执行至此时,将视为main.o。

依存关系

make的主要工作方式,是依「依存关系」(dependency)来工作的,而所谓的依存关系,就是指两或多个档案间彼此的关系,譬如我们写了一个test.c程式,当我们 编译如下时:

$ gcc -O -o test test.c

便会产生test.o这个目的档,因此test.o便是依於test.c,当test.c改变时, test.o也需重新编译,才能保持程式的最新版本;若test.o是由test1.c和test2.c 所组成的,那test.o同时依存於test1.c及test2.c,依存关系便是相关档案的先後关系,和档案的「生成」方式,如C语言的原始档.c需cc或gcc作编译後才能生成目标档 .o,而且make功能强大,在依存规则中并不限定只能作和编译有关的动作。

接下来就是将依存规则写入makefile中了,依存规则的格式如下:

目标档;依存档;命令

「目标档」就是「依存档」照「命令」的方式造出的档案,如上例便可写成:

test:test.c;gcc -O -o test test.c

或是可将「命令」写在下一行,但是需有定位字元作为前导,因此可写成:

test:test.c

gcc -O -o test test.c

通常以此方式撰写,认为是较好的方式;若「目标档」或「依存档」中有两个以 上的档案,各档案名称间以空白隔开便可,如下:

test:test1.c test2.c

gcc -O -o test test1.c test.c

如此定下规则,那天若是test1.c或test2.c有修改时(日期会比test.o还新) , make便会重新编译,若是test.o为最晚者,那就没有执行命令的必要了。

接下来我们先看范例一:

范例一:

01 #

02 # Makefile for cshow

03 # By Ivor Chen

04 # 08/31/1994

05 #

06

07 CC = gcc

08 OPTIMIZE = -fomit-frame-pointer -O2 -s

09 CFLAGS = $(DEFINES) $(OPTIMIZE)

10 LFLAGS = -N

11

12 PROGS = cshow

13 PROGS_O = cshow.o

14 LIBS = -lvgagl -lvga

15

16 all: progs

17

18 progs: $(PROGS)

19

20 objs: $(PROGS_O)

21

22 .c.o:

23 $(CC) $(CFLAGS) -c -o $*.o $

24

25 .c.s:

26 $(CC) $(CFLAGS) S o $*.s $

27

28 .o:

29 $(CC) $(CFLAGS) $(LFLAGS) o $* $*.o $(LIBS)

30 chmod a+rs,go-w $*

31

32 clean : cleanbin

33 rm f *.o *~

34

35 cleanbin :

36 rm f $(PROGS)

37

38 dep :

39 rm f .depend

40 make .depend

41

42 .depend:

43 echo '# Program dependencies'.depend

44 gcc -MM $(patsubst %.o,%.c,$(PROGS_O)) .depend

45

46 include .depend

范例一是笔者的cshow程式的makefile,其中01至05行以#开头作为注解用;07至 14行是设定变数,其中07-10所设定的是有关编译器及其命令,11至14行则设定被编 译的档案名称及额外需被连结的程式库名称;第16行便是一个依存规则,若是我们在 命令列下只打make,那make便会去寻找makefile中的第一个规则来工作,在此这便是 第一个规则,但这个规则比较特殊:一、本规则并无「命令」,二、本规则中的all 并不是档名,而且其後的progs是下一条规则(第18行)的「目标档」,这样一来,当 我们一去make

all时,由於all是由progs所构成,因此会跳到第18行去,而第18行 的$(PROGS)是cshow,为做本make最终产生的档案,为一可执行档,第20行的cshow.o 便是最终的目的档,那cshow和cshow.o又是如何产生的?这和第22、25、28行有关, 这几行是利用下一节的「字尾规则」,稍後再论。

范例一中第32和35行是makefile中另外常见的规则,其目的不是「产生」目的档 ,而是去「删除」某些档案,35行的动作包含在32之中,35行的目的是删除可执行档 (rm

-f

$(PROGS));而32行会先执行35行的动作,再去删除*.o和*~的档;若是我 们更新了一大群source的部份时,最好要make

clean,否则仍会发生.o和其source 间版本不同的错误。

字尾规则

通常我们会以特定的字尾来表示不同档案的种类,如.c 便是代表c语言的原始档 , 而.o 通常代表此档经特定的编译程式所产生的目的档,由於在同一系统中同一语 言原始档的编译程式皆相同,我们便可为这些原始档定出一定的编译方式,这便是字 尾规则(Suffix

rule)的用意所在,字尾规则通常是在於定义Makefile的内建依存 规则;字尾规则的语法如下:

.字尾一.字尾二:

命令

'

其中的意义是字尾一的档案经「命令」的作用後产生字尾二的档案,如范例一中 的第22和23行:

22 .c.o:

23 $(CC) $(CFLAGS) -c -o $*.o $

这便是一个字尾规则,22阐述.c和.o的关系,23行便是描述.o如何由.c产生,其 中$*和$

gcc -fomit-frame-pointer -O2 -s -c -o test.o test.c

而且因为$

clean,免得同一档名的.o虽比.c新,但真正的内容版本却比.c旧。

「空字尾」规则是字尾规则的特殊形态,所产生的档案便是依存档去掉字尾的情 况,一般情况中用於产生最後的可执行档,如范例一中的第28、29及30行,第29行的 实际作用,便是将.o档连结成最後的档案,第30行再将其权限改变成可执行的形式。

第42行也是「空字尾」规则,主要目的在於产生.depend档,在.depend档中记载 各依存档彼此的关系,make在执行时会参考到此档。

多档案程式

make有一个很方便的特性是对於多档案的程式,能作完善的管理。所谓的多档案 程式,就是程式本身由多个.c所组成,只要在makefile中定好档案间的关系,接下来 就无需挂虑到底那一档需要编译了。对於多档案程式,一般的方式是保留个别对应到 .c的.o档,连结时再把各个.o连在一起,这个方式的好处在於当修改了其中之一的.c 後,make便只需重新编译修改过的即可,真是省时又方便,接下来我们就利用图一的 这个程式来说明。

图一:

main

|

--------------+-------------

| | |

| | |

main.o input.o output.o

| | |

| | |

main.c input.c output.c

图一是main这个程式的结构,主要由main.o、input.o和output.o组成,main.o、 input.o和output.o各自依存於如图的叁个.c档,这般的档案结构是很常见的方式,对 於如此的多档案程式,我们只需修改范例一中的第13行:

PROGS_O = main.o input.o output.o

如此一来,make便能自动的决定何时需要、何时不需重新作编译

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有