您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 其它行业文档 > Linux基础-Makefile
嵌入式教育Linux基础–Makfile徐永宏Linux编译流程编译流程:预处理-编译-汇编-链接每个编译的环节都会产生不同类型的文件,对于C程序:预处理-.i文件(-E)编译-.s文件(-S)汇编-.o文件=.a文件.so文件(-c)链接-可执行文件每个环节都有自己的依赖,即若想生成.o文件,那么需要.s、.i、.c文件。Linux编译思考对于庞大的工程项目,比如内核源码中存在成千上万个源文件,那么编译的时候,如何实现自动化编译,即源头文件与头文件或者静、动态库之间找到彼此的依赖关系进行编译,最终生成目标文件。大多数的Winodws的程序员不需要深入了解自动化编译流程,因为Windows的IDE(IntegratedDevelopmentEnvironment)已经做了相关的工作,比如VC,VB等。而Linux下没有这样的IDE,通常需要程序员做用脚本自行书写。要做一个好的professional程序员,尤其是linux程序员,至少需要懂得设计该脚本-Makefile。LinuxMakefile的介绍认识Makefile和make。Makfile是一种纯文本的编译脚本,在其中可以指定需要编译哪些文件,哪些先编译,哪些后编译,哪些需要重新编译,最终需要生成怎么样的应用程序。make是一种命令,它用来解释Makefile脚本,并根据脚本中的指定内容,进行操作。LinuxMakefile的命名及执行方式使用make命令执行Makefile文件。在默认情况下,make会执行当前目录下的Makefile文件。若当前目录下找不到相关的Makefile文件,则会出现错误:make:***Notargetsspecifiedandnomakefilefound.Stop.Makefile文件的命名可以为“Makefile或makefile。如果使用非标准命名的makefile,必须用命令开关-f或“--file”。参数“-fname”或“--filenane”告诉make读入name作为makefile文件。LinuxMakefile的好处Makefile带来的好处——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。另一个好处,某工程有10万个源文件,如果其中某一个源文件发生改变,不需要重新编译整个工程,但是我们生成应用程序前需要将所有的源文件生成.o文件。makefile会根据文件更新时间而判断,是否需要重新编译源文件成.o文件,在生成应用程序时,只需要将所有的.o文件做链接即可。LinuxMakefile简单的练习有三个源程序程序fun1.c:程序fun2.c:程序main.c:使用gcc编译出应用程序test:#gccfun1.cfun2.cmain.c-otest接下来,我们使用Makefile来写一个脚本。LinuxMakefile简单的练习#samplemakefilescriptCC=gccSRCS=fun1.cfun2.cmain.cEXEC=testall:$(CC)$(SRCS)-o$(EXEC)编写完后,保存,在当前目录下执行make命令,生成可执行程序testLinuxMakefile的组成Makefile里主要包含了五种类型的语句:显式规则、隐式规则、变量定义、文件指示、注释注:Makefile中可以直接调用shell命令。显式规则:显式规则说明了如何生成一个或多的的目标文件。这是由Makefile的书写者明显指出,要生成的文件,文件的依赖文件,生成的命令隐式规则:由于make有自动推导的功能,所以隐式的规则可以让程序员比较简略地书写Makefile,这是由make所支持,例如,makefile发现.o文件,程序就会自动去找.c文件,并编译成.o文件。LinuxMakefile的组成变量的定义:在Makefile中可定义一系列的变量,变量一般都是字符串,当Makefile被执行时,其中的变量都会被扩展到相应的引用位置上文件指示:包括了三个部分。在一个Makefile中引用另一个Makefile根据某些情况指定执行Makefile中的有效部分定义一个多行的命令。注释:Makefile注释使用#,若Makefile需要用到“#”,则需要做转义“\#”。LinuxMakefile的组成#samplemakefilescriptincludeother.makeCC=gccSRCS=fun1.cfun2.cmain.cEXEC=testall:$(CC)$(SRCS)-o$(EXEC)文件指示,包含其他文件,其他文件中的变量会被包含进来CC,SRCS,EXEC为变量,都是字符串,使用时会完全被替换。makefile命令部份,变量在被引用时需要加上$()或者${}注释Makefile与程序或其它脚执行顺序一样,都是自上到下。引用未定义的变量时,不会出错,但其值为空,即什么都没有。LinuxMakefile的规则(命令)规则解释如何编译文件,make根据依赖关系执行产生或更新目标;规则也说明如何和何时执行动作。有的规则看起来很复杂,但都符合下述模式。target:dependcommand1command2……target是一个目标文件,可以是可执行文件或.o文件,也可以是执行动作。depend目标的依赖,目标若需要成立,必须有依赖。一个target可以拥有多个depend。command是make执行动作,一个目标依赖关系中可以包含多个命令,但是每个command前面不能是空格或者其它的字符,只可以一个制表符Tab键。注:若target缺少depend,那么command会直接被执行。LinuxMakefile的工作原理当执行make的时候,make程序从当前目录读入makefile开始处理上述的makefile中,缺省目标是all,由于目标all缺少depend,所以这个规则中的命令会被直接执行。在执行make的时候,也可以指定目标执行,如makeclean,那么make会直接读入执行目标clean,跳过all。若执行makeall,那么与make功能相同。#samplemakefilescriptCC=gccSRCS=fun1.cfun2.cmain.cEXEC=testall:$(CC)$(SRCS)-o$(EXEC)clean:rm-rf$(EXEC)LinuxMakefile的规则练习#makefileruleexampleA:B@echoAB:C@echoBC:D@echoCD:@echoDG:@echoG分别执行make、makeB、makeG。查看结果,并分析结果。@:命令前面加@,执行该命令语句时,语句不会被打印出来LinuxMakefile自动检测更新工程若干个源文件中,某一个文件发生了改变,我们希望只重新编译被修改的那一个文件,其它的文件不重新编译。make在执行时,会确认所有target是否都是最新的,若target的某一个depend的时间比target新,那么make会重新根据依赖关系来执行相应的命令。对于例子中的Makefile,all没有依赖所以命令总是会执行。这里需要修改Makefile#samplemakefilescriptCC=gccSRCS=fun1.cfun2.cmain.cEXEC=testall:$(CC)$(SRCS)-o$(EXEC)clean:rm-rf$(EXEC)LinuxMakefile自动检测更新#samplemakefilescriptCC=gccOBJS=fun1.ofun2.omain.oEXEC=testall:$(OBJS)$(CC)$(OBJS)-o$(EXEC)fun1.o:fun1.c$(CC)-cfun1.cfun2.o:fun2.c$(CC)-cfun2.cmain.o:main.c$(CC)-cmain.cfun1.hfun2.hclean:rm-rf$(EXEC)LinuxMakefile隐式规则由于make有自动推导的功能,所以隐式的规则可以让程序员比较简略地书写Makefile。make在解释Makefile时,若目标是.o文件,那么他会自动的去寻找相应的.c文件,并隐式的进行编译。LinuxMakefile隐式规则-简化#samplemakefilescriptCC=gccOBJS=fun1.ofun2.omain.oEXEC=testall:$(OBJS)$(CC)$(OBJS)-o$(EXEC)clean:rm-rf$(EXEC)简化2:使用隐式规则,目标文件为.o文件,make自动推导搜索.c文件,并编译。LinuxMakefile的变量替换在Makefile中通常指定需要编译的.c文件,我们可以将多个.c文件名保存在变量SRCS中,再定义另一个变量OBJS使其保存.o文件名。我们可以直接使用变量的替换方式,将SRCS中的.c字符串替换成.o,赋值OBJS变量。其格式为:foo=$(var:a=b),将var变量中的a替换成b,并返回给foo。例:SRCS=fun1.cfun2.cmain.cOBJS=$(SRCS:.c=.o)那么变量OBJS值为fun1.ofun2.omain.oLinuxMakefile优化#samplemakefilescriptCC=gccSRCS=fun1.cfun2.cmain.cOBJS=(SRCS:.c=.o)EXEC=testall:$(OBJS)$(CC)$(OBJS)-o$(EXEC)clean:rm-rf$(EXEC)LinuxMakefile的变量追加在定义一个变量之后,我们可以继续在变量后面加上新的值。追加的语法与C语言中复合运算的“+=”类似。如:CFLAGS=-WallCFLAGS+=-O2那么最终CFLAGS的值为-Wall-O2LinuxMakefile预定义变量不管是显式规则还是隐式规则,makefile都有一些预定义的变量,这些变量有些会在隐式规则中自动带入,有些则是约定俗成的具有特殊意义的变量。部份预定义变量:CC:编译器类型CFLAGS:编译选项,通常为-O2-Wall-I-LLDFLAGS:额外链接库EXEC或APP:应用程序名SRCS:源代码OBJS:目标文件LinuxMakefile(隐式规则)自动推导GNU的make很强大,它可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必要去在每一个[.o]文件后都写上类似的命令,因为,我们的make会自动识别,并自己推导命令。#samplemakefilescriptCC=gccOBJS=fun1.ofun2.omain.oEXEC=testall:$(OBJS)$(CC)$(OBJS)-o$(EXEC)fun1.o:fun1.cfun2.o:fun2.cmain.o:main.cfun1.hfun2.hclean:rm-rf$(EXEC)LinuxMakefile通用版(基本版)#makefileexampleCC=gccCFLAGS=-Wall-O2CFLAGS+=-I./-L./LFLAGS=-lpthread-lmSRCS=fun1.c\fun2.c\main.cOBJS=$(SRCS:.c=.o)EXEC=testall:${EXEC}${EXEC}:$(OBJS)$(CC)$(CFLAGS)$(OBJS)-o$(EXEC)$(LFLAGS)fun1.o:fun1.cfun2.o:fun2.cmain.o:main.cfun1.hfun2.hclean:rm-rf$(EXEC)$(OBJS)
本文标题:Linux基础-Makefile
链接地址:https://www.777doc.com/doc-3356315 .html