⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 00000001.htm

📁 一份很好的linux入门资料
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<HTML><HEAD>  <TITLE>BBS水木清华站∶精华区</TITLE></HEAD><BODY><CENTER><H1>BBS水木清华站∶精华区</H1></CENTER>发信人:&nbsp;raner&nbsp;(毕设好无聊呀!),&nbsp;信区:&nbsp;Linux&nbsp;<BR>标&nbsp;&nbsp;题:&nbsp;如何写一个简单的Makefile&nbsp;mini-HOWTO&nbsp;<BR>发信站:&nbsp;BBS&nbsp;水木清华站&nbsp;(Fri&nbsp;Jun&nbsp;19&nbsp;09:05:43&nbsp;1998)&nbsp;<BR>&nbsp;<BR>发信人:&nbsp;hey&nbsp;(吟风·魂之利刃),&nbsp;信区:&nbsp;Unix&nbsp;<BR>标&nbsp;&nbsp;题:&nbsp;[HOWTO]&nbsp;如何写一个简单的Makefile&nbsp;<BR>发信站:&nbsp;华南网木棉站&nbsp;(Thu&nbsp;Jun&nbsp;18&nbsp;09:51:56&nbsp;1998),&nbsp;转信&nbsp;<BR>&nbsp;<BR>第一章&nbsp;如何写一个简单的Makefile&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;描述档案(Description&nbsp;File)&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;检查附属档案(Dependency&nbsp;Checking)&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;重建最小化(Minimizing&nbsp;Rebuilds)&nbsp;<BR>&nbsp;<BR>引用make&nbsp;(Invoking&nbsp;make)&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;语法的基本规则(Basic&nbsp;Rules&nbsp;of&nbsp;Syntax)&nbsp;<BR>&nbsp;<BR>当我们在提示符号之下下一个命令:&nbsp;<BR>&nbsp;<BR>$&nbsp;make&nbsp;program&nbsp;<BR>&nbsp;<BR>就是说你要去”make”一个新版本□而且通常是最新版本□的程式.&nbsp;如果这个程式&nbsp;<BR>是一个执行档,你所下的这个命令意思就是说你想要完成有所必须的编译&nbsp;<BR>(compiling)与连结(linking),然后糟出一一个执行档.&nbsp;你可以使用make来使这些程&nbsp;<BR>序自动化,不必不断键入为数可观的gcc(or&nbsp;cc)这些编译器指令.&nbsp;<BR>&nbsp;<BR>当我们讨论make的时候,我们把我们所要建造的程式(program)称做目标(target).&nbsp;<BR>程式是由一个或一个以上的档案汇集在一起所建造出来的,这些档案的关系分为必备&nbsp;<BR>档案(prerequisites)与附属档案(dependents).&nbsp;每一个构成程式的档案依序有他们&nbsp;<BR>自己的必备档案和附属档案.&nbsp;<BR>&nbsp;<BR>例如,你藉由连结建造了可执行档.&nbsp;一旦你的原始档(source&nbsp;file)或标头档(head&nbsp;<BR>file)改变了,你就必须再连结新的可执行档之前重新编译目的档(object&nbsp;file).&nbsp;每&nbsp;<BR>一个原始档都是一个目的档的必备档案.&nbsp;<BR>&nbsp;<BR>Make的优点就是它对附属的阶层关系是非常敏感的,像是原始档-&gt;目的档,目的档-&gt;&nbsp;<BR>可执行档.&nbsp;你负责在描述档(description&nbsp;file)中指定一些附属档案,这个描述档的&nbsp;<BR>档名通常为makefile&nbsp;或是Makefile.&nbsp;但是make也知道自己所在的执行环境,它也会&nbsp;<BR>自己决定许多它自己的附属档案.&nbsp;make会利用档案的档名,这些档案最近修改的时&nbsp;<BR>间,和一些内建的规则,决定编译时要使用哪些档案与如何去建立它们.&nbsp;在这样的技&nbsp;<BR>术背景之下,之前所秀的那个简单的make指令会保证在阶层中所有建造目标时必须存&nbsp;<BR>在的部分都会被更新.&nbsp;<BR>&nbsp;<BR> &nbsp;<BR>&nbsp;<BR>描述档案(Description&nbsp;File)&nbsp;<BR>&nbsp;<BR>假设你写了一个程式,程式由以下部分所组成:&nbsp;<BR>&nbsp;<BR>*用C语言写的原始档□&nbsp;main.c&nbsp;iodat.c&nbsp;dorun.c&nbsp;<BR>&nbsp;<BR>*用组合语言写的程式码□lo.s&nbsp;,此档案被C写成的原始档所呼叫&nbsp;<BR>&nbsp;<BR>*一组位于&nbsp;/usr/fred/lib/crtn.a&nbsp;之中的函式库常式(library&nbsp;routine)&nbsp;<BR>&nbsp;<BR>如果你用手一一下指令建造这个程式,你会在提示符号下打入:&nbsp;<BR>&nbsp;<BR>$cc&nbsp;□c&nbsp;main.c&nbsp;<BR>&nbsp;<BR>$cc&nbsp;□c&nbsp;iodat.c&nbsp;<BR>&nbsp;<BR>$cc&nbsp;□c&nbsp;dorun.c&nbsp;<BR>&nbsp;<BR>$as&nbsp;□0&nbsp;lo.o&nbsp;lo.s&nbsp;<BR>&nbsp;<BR>$cc&nbsp;□o&nbsp;program&nbsp;main.o&nbsp;iodat.o&nbsp;dorun.o&nbsp;lo.o&nbsp;/usr/fred/lib/crtn.a&nbsp;<BR>&nbsp;<BR>当然你也可以在一行cc命令之内就做好编译,组译,连结的工作(要下很长的一串指&nbsp;<BR>令),但是在实际的程式设计环境下这是很少发生的(因为指令实在是又长又复杂),因&nbsp;<BR>为以下原因:&nbsp;首先,每一个原始档都可能被不同的人所建立或测试.&nbsp;第二,一个大程&nbsp;<BR>式会花掉好几小时的编译工作,所以程式设计师一般都会尽可能的使用已经存在的目&nbsp;<BR>的档而不要再重新编译(可以节省时间).&nbsp;<BR>&nbsp;<BR>现在让我们来看看如何透过描述档下指令给make.&nbsp;我们建立了一个新的档案叫做&nbsp;<BR>makefile,这个档案和所有的原始码放在同一个目录之下.&nbsp;为了方便起见,这个描述&nbsp;<BR>档中的每一个指令和附属档案都明显的打出来(后面的章节会告诉你不用写的那么详&nbsp;<BR>细也可以),很多对make来说都是不需要的.&nbsp;这个描述档的内容如下:&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;1.program&nbsp;:&nbsp;main.o&nbsp;iodat.o&nbsp;dorun.o&nbsp;lo.o&nbsp;/usr/fred/lib/crtn.a&nbsp;&nbsp;<BR>&nbsp;&nbsp;2.cc&nbsp;□o&nbsp;program&nbsp;main.o&nbsp;iodat.o&nbsp;dorun.o&nbsp;lo.o&nbsp;<BR>&nbsp;/usr/fred/lib/ctrn.a&nbsp;&nbsp;<BR>&nbsp;&nbsp;3.main.o&nbsp;:&nbsp;main.c&nbsp;&nbsp;<BR>&nbsp;&nbsp;4.cc&nbsp;□c&nbsp;main.c&nbsp;&nbsp;<BR>&nbsp;&nbsp;5.iodat.o&nbsp;:&nbsp;iodat.c&nbsp;&nbsp;<BR>&nbsp;&nbsp;6.cc&nbsp;□c&nbsp;iodat.c&nbsp;&nbsp;<BR>&nbsp;&nbsp;7.dorun.o&nbsp;:&nbsp;dorun.c&nbsp;&nbsp;<BR>&nbsp;&nbsp;8.cc&nbsp;□c&nbsp;dorun.c&nbsp;&nbsp;<BR>&nbsp;&nbsp;9.lo.o&nbsp;:&nbsp;lo.s&nbsp;&nbsp;<BR>&nbsp;10.as&nbsp;□0&nbsp;lo.o&nbsp;lo.s&nbsp;<BR>&nbsp;<BR>在每一行左边的数字并不属于描述档的一部份,只是为了待会解说方便&nbsp;<BR>&nbsp;<BR>这个描述档中包含了五个项目(或说是进入点)(entry).&nbsp;每一个项目由一个含有冒号&nbsp;<BR>(:)(叫做附属列[dependency&nbsp;line]或是规则列[rules&nbsp;line]),和一个或一个以上以&nbsp;<BR>tab(4个字元空白)开头的命令列(command&nbsp;line).&nbsp;在附属行那个冒号左边的叫做目&nbsp;<BR>标(target);冒号左边的就是目标的必备档案.&nbsp;受tab影响的(tab-indented)命令列,&nbsp;<BR>告诉make如何从他们的必须档案中建造出目标.从上面的描述档来看,第1列说明了&nbsp;<BR>program这个目标依靠main.o,iodat.o,dorun.o,lo.o这些目的档,还有依靠函式库&nbsp;<BR>/usr/fred/lib/crtn.a&nbsp;.第2列指定了从必备档案制造program这个目标档案所必须&nbsp;<BR>下的编译器指令.(这些档案都是目的档与函式库,所以实际上并不用编译,只呼叫了&nbsp;<BR>连结器(linker)而已).&nbsp;假设program这的目标档案不存在,你可以下这个指令:&nbsp;<BR>&nbsp;<BR>$make&nbsp;program&nbsp;<BR>&nbsp;<BR>make会去执行第二行的命令.&nbsp;如果其中一个目的档不在该怎么办呢?&nbsp;你能够把这个&nbsp;<BR>目的档当作参数传给make(例如:没有main.o&nbsp;,你可以下指令$make&nbsp;main.o&nbsp;,就可以&nbsp;<BR>得到main.o这个档案),但是几乎不必这样做.&nbsp;Make最重要的贡献就在于它有能力可&nbsp;<BR>以自己决定什么东西必须被建立(例如:在建立program时,如果少了main.o,则他会根&nbsp;<BR>据附属列所指定的内容,自己建立main.o这个档案).&nbsp;<BR>&nbsp;<BR> &nbsp;<BR>&nbsp;<BR>检查附属档案(Dependency&nbsp;Checking)&nbsp;<BR>&nbsp;<BR>当你要求make去建造program这个目标时,make会去参考前面所列出的那一个描述档,&nbsp;<BR>但是,第二列的编译器指令并不会立刻就执行.&nbsp;make所做的动作应该如下:&nbsp;首&nbsp;<BR>先,make先去检查目录下是否有program这个档案,如果有的话,make会去检查main.o&nbsp;<BR>,&nbsp;iodat.o&nbsp;,&nbsp;dorun.o&nbsp;,&nbsp;lo.o&nbsp;,&nbsp;还有/usr/fred/lib/crtn.a&nbsp;这些档案,看看这些档&nbsp;<BR>案有没有比program这个档案更新(更新的意思是说,这些档案比program这个档案建&nbsp;<BR>造的时间更晚).&nbsp;这个动作非常容易,因为作业系统会储存每一个档案最近被修改的&nbsp;<BR>时间,你只要下一个指令ls&nbsp;□l就可以看到这个讯息.&nbsp;如果program的建造时间比它&nbsp;<BR>所有的必备档案的最近修改时间还要晚,make会决定不再重新建造program这个档案,&nbsp;<BR>然后不会发出认何指令就离开(跳回提示符号下).&nbsp;但是在make下这个决定之前,它还&nbsp;<BR>会做一些检查:&nbsp;make会根据附属列所描述的必备档案,去检查每一个&nbsp;.o档案的必备&nbsp;<BR>档案是否有更新的情形.&nbsp;<BR>&nbsp;<BR>例如,从第3列就可以看出main.o的建造必须依靠main.c.&nbsp;因此,如果再main.o被建造&nbsp;<BR>之后,main.c才又被修改,则make就会去执行第4列的指令重新建造一个新的main.o.&nbsp;<BR>只有在program的必备档都被检查而且更新过(这必备档的必备档也要被检查且更新&nbsp;<BR>过.&nbsp;例如:main.o是program的必备档,main.c是main.o的必备档).&nbsp;make才会去执行&nbsp;<BR>第2列的指令建造program这个目标档案.&nbsp;假设自从上一次建造program这个档案之&nbsp;<BR>后,iodat.c是唯一被更新过的档案,所以当我们再次执行$make&nbsp;program&nbsp;<BR>&nbsp;<BR>之后,make所发出的编译器指令实际上只有&nbsp;<BR>&nbsp;<BR>cc&nbsp;□c&nbsp;main.c&nbsp;<BR>&nbsp;<BR>cc&nbsp;□o&nbsp;program&nbsp;main.o&nbsp;iodat.o&nbsp;dorun.o&nbsp;lo.o&nbsp;/usr/fred/lib/crtn.a&nbsp;<BR>&nbsp;<BR>这两行指令而已.&nbsp;<BR>&nbsp;<BR>make命令执行以后,会在标准输出上印出它所发出的指令,因此当你使用make的时候,&nbsp;<BR>你可以从你的萤幕上看到它所发出的命令的顺序.&nbsp;<BR>&nbsp;<BR>总而言之,一个程式的建造包含了顺序正确的指令链结(chain).&nbsp;一般而言,你只要要&nbsp;<BR>求make去建造链结中最后的那个档案即可.&nbsp;make会透过附属档案链结(你在描述档中&nbsp;<BR>所指定的那些必备档案所构成的树状结构构成附属档案链结),自己回朔追踪(traces&nbsp;<BR>back,也就是往树状结构的叶部方向)这个链结,然后找出哪些指令必须被执行.&nbsp;最&nbsp;<BR>后,make会慢慢在链结中前进(moves&nbsp;forward,就是往数状结构的根部移动),执行每&nbsp;<BR>个建造目标所必须要有的指令直到目标建立完成(或被更新).&nbsp;因为这种特性,make是&nbsp;<BR>一个使用反项链结法(backward-chaining:在人工智慧领域中,一种搜索问题答案的&nbsp;<BR>方法,它的搜索方向是由目标状态开始,然后向初始状态前进,最后再慢慢回来)这个&nbsp;<BR>技巧最有名的例子,这个技巧通常仅使用在像是Prolog语言这一类大家比较不知道的&nbsp;<BR>环境上.&nbsp;<BR>&nbsp;<BR> &nbsp;<BR>&nbsp;<BR>重建最小化(Minimizing&nbsp;Rebuilds)&nbsp;<BR>&nbsp;<BR>现在我们来讨论一个可以以各种不同版本形式存在的程式(通常是不同平台,或是不&nbsp;<BR>同作业系统,或是要分散(release)给不同层级使用者的版本),这是一个可以告诉你&nbsp;<BR>make如何节省你的时间,而且可以避免混淆的例子,比前的例子更复杂一点.&nbsp;假设你&nbsp;<BR>写了一个可以绘出资料的程式,它可以在终端机(文字模式)或是图形介面(例如:X&nbsp;<BR>window)之下执行.&nbsp;涉及到计算和档案处理的部分在两个版本之中都相同,而且你把&nbsp;<BR>它们都存放在basic.c这个档案中.&nbsp;处理文字模式下使用者输入的程式放在prompt.c&nbsp;<BR>之中,而处理图形介面上使用者输入的程式放在window.c之中.&nbsp;<BR>&nbsp;<BR>因此,这个程式可以以两种不同的版本被发行(release),当你想要建立这个程式时,&nbsp;<BR>你可以选择要建立你觉得最适合你现在工作环境的版本.&nbsp;以文字模式下的版本来说,&nbsp;<BR>你可以由basic.c与prompt.c这两个档案来产生plot_prompt这个执行档.&nbsp;对图形介&nbsp;<BR>面的版本来说,你就可以使用basic.c与window.c这两个档案来产生叫做plot_win的&nbsp;<BR>执行档.&nbsp;以下产生这两种版本所使用的眠述档:&nbsp;<BR>&nbsp;<BR>plot_prompt&nbsp;:&nbsp;basic.o&nbsp;prompt.o&nbsp;<BR>&nbsp;<BR>cc&nbsp;□o&nbsp;plot_prompt&nbsp;basic.o&nbsp;prompt.o&nbsp;<BR>&nbsp;<BR>plot_win&nbsp;:&nbsp;basic.o&nbsp;window.o&nbsp;<BR>&nbsp;<BR>cc&nbsp;□o&nbsp;plot_win&nbsp;basic.o&nbsp;window.o&nbsp;<BR>&nbsp;<BR>basic.o&nbsp;:&nbsp;basic.c&nbsp;<BR>&nbsp;<BR>cc&nbsp;□c&nbsp;basic.c&nbsp;<BR>&nbsp;<BR>prompt.o&nbsp;:&nbsp;prompt.c&nbsp;<BR>&nbsp;<BR>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -