当前位置:  技术问答>linux和unix

关于如何写make file

    来源: 互联网  发布时间:2015-11-01

    本文导语:  各位兄弟姐妹帮帮忙,我写了个c程序,想要在unix上用make file编译,请问如何写一个make file文件,以前没写过,不知道怎么入手,请各位帮帮忙,谢了先。 | 如何写一个简单的Makefile 当我们...

各位兄弟姐妹帮帮忙,我写了个c程序,想要在unix上用make file编译,请问如何写一个make file文件,以前没写过,不知道怎么入手,请各位帮帮忙,谢了先。

|
如何写一个简单的Makefile
当我们在提示符号之下下一个命令:

$ make program

就是说你要去”make”一个新版本—而且通常是最新版本—的程序. 如果这个程序是一个可执行文件,你所下的这个命令意思就是说你想要完成有所必须的编译(compiling)与连结(linking),然后得出一一个可执行文件. 你可以使用make来使这些程序自动化,不必不断输入为数可观的gcc(or cc)这些编译器指令.当我们讨论make的时候,我们把我们所要建造的程序(program)称做目标(target). 程序是由一个或一个以上的文件汇集在一起所建造出来的,这些文件的关系分为必要文件(prerequisites)与附属文件(dependents). 每一个构成程序的文件依序有他们自己的必要文件和附属文件.

例如,你由连结建造了可执行文件. 一旦你的原始文件(source file)或头文件(head file)改变了,你就必须再连结新的可可执行文件之前重新编译目标文件(object file). 每一个原始文件都是一个目标文件的必要文件.Make的优点就是它对附属的隶属关系是非常敏感的,像是原始文件->目标文件,目标文件->可可执行文件. 你负责在描述文件(description file)中指定一些附属文件,这个描述文件的文件名通常为makefile 或是Makefile. 但是make也知道自己所在的执行环境,它也会自己决定许多它自己的附属文件. make会利用文件的文件名,这些文件最近修改的时间,和一些內建的规则,决定编译时要使用哪些文件与如何去建立它们. 在这样的技术背景之下,之前所做的那个简单的make指令会保证在隶属中所有建造目标时必须存在的部分都会被更新.

描述文件(Description File)

假设你写了一个程序,程序由以下部分所組成:

*用C语言写的原始文件— main.c iodat.c dorun.c

*用其它语言写的程序码—lo.s ,此文件被C写成的原始文件所调用

*一組位于 /usr/fred/lib/crtn.a 之中的函数库方法(library routine)

如果你用手一一下指令建造这个程序,你会在提示符号下打入:

$cc –c main.c

$cc –c iodat.c

$cc –c dorun.c

$as –0 lo.o lo.s

$cc –o program main.o iodat.o dorun.o lo.o /usr/fred/lib/crtn.a

当然你也可以在一行cc命令之內就做好编译,连结的工作(要下很长的一串指令),但是在实际的程序设计环境下这是很少发生的(因为指令实在是又长又复杂),因为以下原因: 首先,每一个原始文件都可能被不同的人所建立或测试. 第二,一个大程序会花掉好几小时的编译工作,所以程序设计师一般都会尽可能的使用已经存在的目标文件而不要再重新编译(可以节省时间).现在让我们来看看如何透过描述文件下指令給make. 我们建立了一个新的文件叫做makefile,这个文件和所有的原始码放在同一个目录之下. 为了方便起见,这个描述文件中的每一个指令和附属文件都明显的打出来,很多对make来说都是不需要的. 这个描述文件的內容如下:

program : main.o iodat.o dorun.o lo.o /usr/fred/lib/crtn.a 

cc –o program main.o iodat.o dorun.o lo.o /usr/fred/lib/ctrn.a 

main.o : main.c 

cc –c main.c 

iodat.o : iodat.c 

cc –c iodat.c 

dorun.o : dorun.c 

cc –c dorun.c 

lo.o : lo.s 

as –0 lo.o lo.s

在每一行左边的数字并不属于描述文件的一部份,只是为了待会解释方便这个描述文件中包含了五个项目(或说是入口点)(entry). 每一个项目由一个含有冒号(:)(叫做附属列[dependency line]或是规则列[rules line]),和一个或一个以上以tab(4个字元空白)开头的命令列(command line). 在附属行那个冒号左边的叫做目标(target);冒号左边的就是目标的必要文件. 受tab影响的(tab-indented)命令列,告诉make如何从他们的必须文件中建造出目标.从上面的描述文件来看,第1列说明了program这个目标依靠main.o,iodat.o,dorun.o,lo.o这些目标文件,还有依靠函数库/usr/fred/lib/crtn.a .第2列指定了从必要文件构造program这个目标文件所必须下的编译器指令.(这些文件都是目标文件与函数库,所以实际上并不用编译,只调用了连结器(linker)而已). 假设program这的目标文件不存在,你可以下这个指令:

$make program

make会去执行第二行的命令. 如果其中一个目标文件不在该怎么办呢? 你能够把这个目标文件当作参数传給make(例如:没有main.o ,你可以下指令$make main.o ,就可以得到main.o这个文件),但是几乎不必这样做.Make最重要的贡献就在于它有能力可以自己决定什么东西必须被建立(例如:在建立program时,如果少了main.o,则他会根据附属列所指定的內容,自己建立main.o这个文件).

检查附属文件(Dependency Checking)

当你要求make去建造program这个目标时,make会去参考前面所列出的那一个描述文件,但是,第二列的编译器指令并不会立刻就执行. make所做的动作应该如下: 首先,make先去检查目录下是否有program这个文件,如果有的话,make会去检查main.o , iodat.o , dorun.o , lo.o , 还有/usr/fred/lib/crtn.a 这些文件,看看这些文件有没有比program这个文件更新(更新的意思是说,这些文件比program这个文件建造的时间更晚). 这个动作非常容易,因为操作系统会储存每一个文件最近被修改的时间,你只要下一个指令ls –l就可以看到这个信息. 如果program的建造时间比它所有的必要文件的最近修改时间还要晚,make会决定不再重新建造program这个文件,然后不会发出任何指令就离开(跳回提示符号下). 但是在make下这个决定之前,它还会做一些检查: make会根据附属列所描述的必要文件,去检查每一个 .o文件的必要文件是否有更新的情况.例如,从第3列就可以看出main.o的建造必须依靠main.c. 因此,如果再main.o被建造之后,main.c才又被修改,则make就会去执行第4列的指令重新建造一个新的main.o. 只有在program的必要文件都被检查而且更新过(这必要文件的必要文件也要被检查且更新过. 例如:main.o是program的必要文件,main.c是main.o的必要文件). make才会去执行第2列的指令建造program这个目标文件. 假设自从上一次建造program这个文件之后,iodat.c是唯一被更新过的文件,所以当我们再次执行$make program之后,make所发出的编译器指令实际上只有

cc –c main.c

cc –o program main.o iodat.o dorun.o lo.o /usr/fred/lib/crtn.a

这两行指令而已.

make命令执行以后,会在标准输出上显示出它所发出的指令,因此当你使用make的时候,你可以从你的屏幕上看到它所发出的命令的顺序.总而言之,一个程序的建造包含了顺序正确的指令连接(chain). 一般而言,你只要要求make去建造连接中最后的那个文件即可. make会透过附属文件连接(你在描述文件中所指定的那些必要文件所构成的树状結构构成附属文件连接),自己回朔跟踪(traces back,也就是往树状結构的叶子方向)这个连接,然后找出哪些指令必须被执行. 最后,make会慢慢在连接中前进(moves forward,就是往数状結构的根部移动),执行每个建造目标所必须要有的指令直到目标建立完成(或被更新). 因为这种特性,make是一个使用后序方法(backward-chaining:在人工智能领域中,一种搜索问题答案的方法,它的搜索方向是由目标状态开始,然后向初始状态前进,最后再慢慢回来)这个技巧最有名的例子,这个技巧通常仅使用在像是Prolog语言这一类大家比较不熟悉的环境上.

重建最小化(Minimizing Rebuilds)

现在我们来讨论一个可以以各种不同版本形式存在的程序(通常是不同平台,或是不同操作系统,或是要分散(release)給不同层级使用者的版本),这是一个可以告诉你make如何节省你的时间,而且可以避免混淆的例子,比前的例子更复杂一点. 假设你写了一个可以绘出文件的程序,它可以在终端(文字模式)或是图形界面(例如:X window)之下执行. 涉及到计算和文件处理的部分在两个版本之中都相同,而且你把它们都存放在basic.c这个文件中. 处理文字模式下使用者输入的程序放在prompt.c之中,而处理图形界面上使用者输入的程序放在window.c之中.因此,这个程序可以以两种不同的版本被发行(release),当你想要建立这个程序时,你可以选择要建立你觉得最适合你现在工作环境的版本. 以文字模式下的版本来说,你可以由basic.c与prompt.c这两个文件来产生plot_prompt这个可执行文件. 对图形界面的版本来说,你就可以使用basic.c与window.c这两个文件来产生叫做plot_win的可执行文件. 以下产生这两种版本所使用的自述文件:


|
makefile根据make的生产厂商的不同,区别还是比较大的。比如m$的nmake和gnu的make。不知道你想学哪种,这个东东可是没有标准规范的。不过原理是一样的,学原理就查下msdn吧,至少中文的。

gnu的make文档在www.gnu.org上有。洋洋大观,打印出来数百页。gcc本身也能产生makefile,根据指定目录可以自动分析依靠关系,生成一个超级眩晕的大型makefile,很是有趣。

不过,在gnu支持的系统上,还是使用automake和autoconf吧。特别在多应用、多库系统中,想自己写个makefile实在太晕了。

    
 
 
 
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • 有关make all; make clobber; make depend; make debug 的区别?
  • 我要缩减LINUX内核,make menuconfig时把一些选项去掉,再make dep没错,但再make bzImage时却会提错,但我make menuconfig时不改变任何选现(
  • 我已经用make clean编译成功了内核但是在make moduals时候处错误,然后又make menuconfig,我还需要make zImage吗?
  • make perl 模块的时候出错,make: *** No rule to make target,帮忙看看,谢谢。
  • 如何写出兼容于BSD MAKE、GNU MAKE、SOLARIS MAKE的条件编译Makefile?
  • 在solaris8.0我装了make3.81,下载了make-3.81-sol8-sparc-local.gz,为什么不能在任何目录下输入make?
  • 怎样验证自己的make是不是GNU的make?
  • 问一个很低级的问题:怎样卸载用make;make install方法安装的软件?
  • configure make make install 新手问题...
  • cygwin make操作,出现no rule to make target all
  • 请教 make gdb-6.4 出现 make[4]: Entering directory `/tmp/gdb-6.4/gdb/doc'
  • make zImage和make modules等问题请教~
  • debian下安装bind用./configure时提示安装bind时./configure提示whether make sets $(MAKE)... no
  • 第一次写make文件,报makefile:2: *** missing separator. Stop.错,make文件只有两行
  • jquery iis7站长之家
  • 50分的问题!make文件找不到? You don't seem to have 'make' or 'gmake' in your PATH
  • make;make install放在script裡
  • make oldconfig 和 make defconfig有何区别?
  • 求linux下 ./configure;make;make install一系列命令的详解
  • make -f makefile 时提示 Make: Must be a separator on rules line 5. Stop. 为什么,makefile 如下


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3