Linux下Makefile简单教程.docx

上传人:b****2 文档编号:3224516 上传时间:2023-05-05 格式:DOCX 页数:24 大小:25.19KB
下载 相关 举报
Linux下Makefile简单教程.docx_第1页
第1页 / 共24页
Linux下Makefile简单教程.docx_第2页
第2页 / 共24页
Linux下Makefile简单教程.docx_第3页
第3页 / 共24页
Linux下Makefile简单教程.docx_第4页
第4页 / 共24页
Linux下Makefile简单教程.docx_第5页
第5页 / 共24页
Linux下Makefile简单教程.docx_第6页
第6页 / 共24页
Linux下Makefile简单教程.docx_第7页
第7页 / 共24页
Linux下Makefile简单教程.docx_第8页
第8页 / 共24页
Linux下Makefile简单教程.docx_第9页
第9页 / 共24页
Linux下Makefile简单教程.docx_第10页
第10页 / 共24页
Linux下Makefile简单教程.docx_第11页
第11页 / 共24页
Linux下Makefile简单教程.docx_第12页
第12页 / 共24页
Linux下Makefile简单教程.docx_第13页
第13页 / 共24页
Linux下Makefile简单教程.docx_第14页
第14页 / 共24页
Linux下Makefile简单教程.docx_第15页
第15页 / 共24页
Linux下Makefile简单教程.docx_第16页
第16页 / 共24页
Linux下Makefile简单教程.docx_第17页
第17页 / 共24页
Linux下Makefile简单教程.docx_第18页
第18页 / 共24页
Linux下Makefile简单教程.docx_第19页
第19页 / 共24页
Linux下Makefile简单教程.docx_第20页
第20页 / 共24页
亲,该文档总共24页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

Linux下Makefile简单教程.docx

《Linux下Makefile简单教程.docx》由会员分享,可在线阅读,更多相关《Linux下Makefile简单教程.docx(24页珍藏版)》请在冰点文库上搜索。

Linux下Makefile简单教程.docx

Linux下Makefile简单教程

目录

一:

Makefile基本规则

1.1示例

1.2隐式规则

1.3伪目标

1.4搜索源文件

二:

变量

2.1使用变量定义变量值

2.2追加变量

三:

条件判断

四:

函数

Linux下Makefile总结

——一步

MakeFile可以看做是一种简单的编程语言,其诞生的本质目的是实现自动化编译。

以Linux下gcc-c编译器为例,编译一个c语言程序需要经过以下几个步骤:

1.将c语言源程序预处理,生成.i文件;

2.预处理后的.i语言编译成汇编语言,生成.s文件;

3.汇编语言经过汇编,生成目标文件.o文件;

4.将各个模块的.o文件链接起来,生成一个可执行程序文件。

我们知道,在VisualC++6.0中,可以新建一个工程,在一个工程当中能够包含若干个c语言文件,则编译的时候直接编译整个工程便可。

Linux下无法为多个c语言文件新建工程,但可以通过MakeFile实现它们的整合编译。

如上gcc-c编译步骤,如果使用Makefile则过程为:

.C文件——>.o文件——>可执行文件

当然,Makefile中也加入了自己的设置变量方法与集成了一些函数,能够更有效地方便用户使用。

 

/**************************分隔符********************************/

一:

Makefile基本规则

1.1示例

target...:

prerequisites...

command

...

...

target也就是一个目标文件,可以是ObjectFile,也可以是执行文件。

prerequisites就是,要生成那个target所需要的文件或是目标。

command也就是make需要执行的命令。

(任意的Shell命令)

为了方便理解,我们来看一个示例:

/*Makefile示例*/

edit:

main.okbd.ocommand.odisplay.o/

insert.osearch.ofiles.outils.o

gcc-oeditmain.okbd.ocommand.odisplay.o/

insert.osearch.ofiles.outils.o

main.o:

main.cdefs.h#生成main.o

gcc-cmain.c

kbd.o:

kbd.cdefs.hcommand.h#生成kdb.o

gcc-ckbd.c

command.o:

command.cdefs.hcommand.h#生成command.o

gcc-ccommand.c

display.o:

display.cdefs.hbuffer.h#生成display.o

gcc-cdisplay.c

insert.o:

insert.cdefs.hbuffer.h#生成insert.o

gcc-cinsert.c

search.o:

search.cdefs.hbuffer.h#生成search.o

gcc-csearch.c

files.o:

files.cdefs.hbuffer.hcommand.h#生成files.o

gcc-cfiles.c

utils.o:

utils.cdefs.h#生成utils.o

gcc-cutils.c

clean:

rmeditmain.okbd.ocommand.odisplay.o/

insert.osearch.ofiles.outils.o

/*END*/

执行输入:

make-sedit

反斜杠(/)是换行符的意思。

我们来回忆一下一个c语言编译的过程:

c语言文件:

main.c

1.gccmain.c-cmain.o

2.gccmain.o-omain

经过这两步便可以编译出可执行文件:

main。

现在我们再看上面的Makefile:

main.o:

main.cdefs.h#生成main.o

gcc-cmain.c

这两句便生成main.o文件(main.c与defs.h为用到的源文件)。

之后

edit:

main.o...

gcc-oeditmain.o...

便会生成main可执行文件;同理,其他几个文件亦是。

“edit”便是最终编译出的可执行文件名。

可以看到Makefile只是整合了编译过程,也可以同时编译多个文件,其诞生的本质目的确实是为了实现自动化编译。

 

1.2隐式规则

make工具会自动使用gcc-c命令,将一个扩展名为.c的c语言程序源文件编译成一个同名的.o目标文件。

因此,在上例中,将:

main.o:

main.cdefs.h#生成main.o

gcc-cmain.c

改为:

main.o:

defs.h

(即去掉源同名c语言文件名,其他几个文件亦是如此。

)这样便使用了隐式规则,隐式规则只是节省了敲代码的数量。

1.3伪目标

可以注意到上述示例中末尾有几行代码:

clean:

rmeditmain.okbd.ocommand.odisplay.o/

insert.osearch.ofiles.outils.o

这几行代码并不会编译生成文件,可以把它们看成是Makefile里附加的实现小功能的程序(Makefile里藏了shell小程序),

这个名称为clean的目标便叫做伪目标。

我们可以直接输入:

makeclean来运行这个伪目标。

显然,此伪目标可以清除之前生成的.o目标文件以及edit执行文件。

为了防止命名的重复,可以使用.PHONY来显式地指明一个伪目标:

.PHONYclean

clean:

rmeditmain.okbd.ocommand.odisplay.o/

insert.osearch.ofiles.outils.o

这样就不会对clean这个目标的性质定义产生混乱了。

 

/*********看完上面应该基本知道Makefile用途了******************/

 

1.4搜索源文件

在一些大的工程中,有大量的源文件,我们通常的做法是把这许多的源文件分类,并存放在不同的目录中。

所以,当make需要去找寻这些相关源文件时,需要在文件前加上路径,但最好的方法是把一个路径告诉make,让make自动去找。

Makefile文件中的特殊变量“VPATH”就是完成这个功能的,如果没有指明这个变量,make只会在当前的目录中去找寻依赖文件和目标文件。

如果定义了这个变量,那么,make就会在当前目录找不到的情况下,到所指定的目录中去找寻文件了。

VPATH=src:

../headers

上面的的定义指定两个目录,“src”和“../headers”,make会按照这个顺序进行搜索。

目录由“冒号”分隔。

(当然,当前目录永远是最高优先搜索的地方)。

另一个设置文件搜索路径的方法是使用make的“vpath”关键字(注意,它是全小写的),这不是变量,这是一个make的关键字,这和上面提到的那个VPATH变量很类似,但是它更为灵活。

它可以指定不同的文件在不同的搜索目录中。

这是一个很灵活的功能。

它的使用方法有三种:

1.vpath

为符合模式的文件指定搜索目录

2.vpath

清除符合模式的文件的搜索目录。

3.vpath

清除所有已被设置好了的文件搜索目录。

vpath使用方法中的需要包含“%”字符。

“%”的意思是匹配零或若干字符,例如,“%.h”表示所有以“.h”结尾的文件。

指定了要搜索的文件集,而则指定了的文件集的搜索的目录。

例如:

vpath%.h../headers

该语句表示,要求make在“../headers”目录下搜索所有以“.h”结尾的文件。

(如果某文件在当前目录没有找到的话)我们可以连续地使用vpath语句,以指定不同搜索策略。

如果连续的vpath语句中出现了相同的,或是被重复了的,那么,make会按照vpath语句的先后顺序来执行搜索。

如:

vpath%.cfoo

vpath%.cblish

vpath%.cbar

其表示“.c”结尾的文件,先在“foo”目录,然后是“blish”,最后是“bar”目录。

vpath%.cfoo:

bar

vpath%.cblish

而上面的语句则表示“.c”结尾的文件,先在“foo”目录,然后是“bar”目录,最后才是“blish”目录。

 

/**************************分隔符*******************************/

二:

变量

为了增强Makefile的功能与增加程序的可移植性,Makefile中也使用了变量。

看个例子:

/*Makefile示例*/

#此处为变量设置

CC=gcc

FLAGS=-c

objects=main.okbd.ocommand.odisplay.o/

insert.osearch.ofiles.outils.o

edit:

$(objects)

CC-oedit$(objects)

main.o:

main.cdefs.h#生成main.o

CCFLAGSmain.c

kbd.o:

kbd.cdefs.hcommand.h#生成kdb.o

CCFLAGSkbd.c

command.o:

command.cdefs.hcommand.h#生成command.o

CCFLAGScommand.c

display.o:

display.cdefs.hbuffer.h#生成display.o

CCFLAGSdisplay.c

insert.o:

insert.cdefs.hbuffer.h#生成insert.o

CCFLAGSinsert.c

search.o:

search.cdefs.hbuffer.h#生成search.o

CCFLAGSsearch.c

files.o:

files.cdefs.hbuffer.hcommand.h#生成files.o

CCFLAGSfiles.c

utils.o:

utils.cdefs.h#生成utils.o

CCFLAGSutils.c

.PHONYclean

clean:

rmedit$(objects)

/*END*/

此时,程序便有了很好的可修改性与移植性。

 

2.1使用变量定义变量值

可以用变量定义变量的值,Makefile中有三种方式:

1.使用'='操作符

/*Makefile程序*/

you=$(me)

me=$(he)

he=she

all:

echo$(you)

/*END*/

执行:

make-sall

输出:

she

程序将变量me的值赋给you,而变量me的值为变量he的值,he的值为she,因此变量you的值为she。

Makefile中的变量值是可以使用后面的变量来定义的。

但这样有危险,例如:

a=$(b)

b=$(a)

将陷入无限的变量赋值过程。

2.使用’:

=‘操作符

这样定义时,前面的变量不能使用后面的变量,只能使用前面已经定义好的变量。

如果使用前面未定义的变量,

则该值为空,例如:

y:

=$(x)me

x:

=you

all:

echo$(y)

执行:

make-sall

输出:

me(注:

如果提示“遗漏分隔符”提示则是代码少敲了键)

由于变量x未定义,则为空值,只输出me。

后面x已经赋值为you,但是y已经赋值过了。

3.使用‘?

='操作符

如果变量之前没有被定义过,则变量的值此时被定义,如果变量的值已经被定义过,则此时赋值语句什么也不做。

例如:

a:

=hello

b?

=world

a?

=HELLO

all:

echo$(a)

echo$(b)

执行:

make-sall

输出:

hello

world

由于a值之前被赋为hello,之后:

a?

=HELLO并不会再给变量a赋值,以此a保持hello值。

2.2追加变量值

由于Makefile当中的变量本质上是一个字符串,因此可以追加变量的值,用‘+=’操作符。

例如:

objects:

=main.ofoo.o

则objects+=another.o结果为:

objects:

=main.ofoo.oanother.o

 

/**************************分隔符********************************/

 

三:

条件判断

条件表达式的语法为:

endif

以及:

else

endif

 

其中表示条件关键字,如“ifeq”。

这个关键字有四个,如下:

1.“ifeq”

ifeq(,

ifeq''''

ifeq""""

ifeq""''

ifeq''""

比较参数“arg1”和“arg2”的值是否相同,相同则为真。

2.第二个条件关键字是“ifneq”。

语法是:

ifneq(,

ifneq''''

ifneq""""

ifneq""''

ifneq''""

其比较参数“arg1”和“arg2”的值是否相同,如果不同,则为真。

3.第三个条件关键字是“ifdef”。

语法是:

ifdef

如果变量的值非空,则表达式为真。

否则,表达式为假。

4.第四个条件关键字是“ifndef”。

其语法是:

ifndef

如果值为空,则表达式为真。

 

/**************************分隔符********************************/

 

四:

函数

函数调用,很像变量的使用,也是以“$”来标识的,其语法如下:

$(

或是

${}

这里,就是函数名,make支持的函数不多。

是函数的参数,参数间以逗号“,”分隔,而函数名和参数之间以“空格”分隔。

函数调用以“$”开头,以圆括号或花括号把函数名和参数括起。

例如:

$(subst,,

名称:

字符串替换函数——subst。

功能:

把字串中的字符串替换成

返回:

函数返回被替换过后的字符串。

示例:

$(substee,EE,feetonthestreet),

把“feetonthestreet”中的“ee”替换成“EE”,返回结果是“fEEtonthestrEEt”。

 

/**************************分隔符********************************/

 

Makefile支持的函数并不多,例举如下:

(摘自:

陈皓《跟我一起写Makefile》)

★字符串处理函数

名称:

字符串替换函数——subst。

$(subst,,

功能:

把字串中的字符串替换成

返回:

函数返回被替换过后的字符串。

示例:

$(substee,EE,feetonthestreet),

把“feetonthestreet”中的“ee”替换成“EE”,返回结果是“fEEtonthestrEEt”。

名称:

模式字符串替换函数——patsubst。

$(patsubst,,

功能:

查找中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式,如果匹配的话,则以替换。

这里,可以包括通符“%”,表示任意长度的字串。

如果中也包含“%”,那么,中的这个“%”将是中的那个“%”所代表的字串。

(可以用“\”来转义,以“\%”来表示真实含义的“%”字符)

返回:

函数返回被替换过后的字符串。

示例:

$(patsubst%.c,%.o,x.c.cbar.c)

把字串“x.c.cbar.c”符合模式[%.c]的单词替换成[%.o],返回结果是“x.c.obar.o”

备注:

这和我们前面“变量章节”说过的相关知识有点相似。

如:

“$(var:

=)”

相当于

“$(patsubst,,$(var))”,

而“$(var:

=)”

则相当于

“$(patsubst%,%,$(var))”。

例如有:

objects=foo.obar.obaz.o,

那么,“$(objects:

.o=.c)”和“$(patsubst%.o,%.c,$(objects))”是一样的。

名称:

去空格函数——strip。

$(strip

功能:

去掉字串中开头和结尾的空字符。

返回:

返回被去掉空格的字符串值。

示例:

$(stripabc)

把字串“abc”去到开头和结尾的空格,结果是“abc”。

名称:

查找字符串函数——findstring。

$(findstring,

功能:

在字串中查找字串。

返回:

如果找到,那么返回,否则返回空字符串。

示例:

$(findstringa,abc)

$(findstringa,bc)

第一个函数返回“a”字符串,第二个返回“”字符串(空字符串)

名称:

过滤函数——filter。

$(filter,

功能:

模式过滤字符串中的单词,保留符合模式的单词。

可以有多个模式。

返回:

返回符合模式的字串。

示例:

sources:

=foo.cbar.cbaz.sugh.h

foo:

$(sources)

cc$(filter%.c%.s,$(sources))-ofoo

$(filter%.c%.s,$(sources))返回的值是“foo.cbar.cbaz.s”。

名称:

反过滤函数——filter-out。

$(filter-out,

功能:

模式过滤字符串中的单词,去除符合模式的单词。

可以有多个模式。

返回:

返回不符合模式的字串。

示例:

objects=main1.ofoo.omain2.obar.o

mains=main1.omain2.o

$(filter-out$(mains),$(objects))返回值是“foo.obar.o”。

名称:

排序函数——sort。

$(sort

功能:

给字符串中的单词排序(升序)。

返回:

返回排序后的字符串。

示例:

$(sortfoobarlose)返回“barfoolose”。

备注:

sort函数会去掉中相同的单词。

名称:

取单词函数——word。

$(word,

功能:

取字符串中第个单词。

(从一开始)

返回:

返回字符串中第个单词。

如果中的单词数要大,那么返回空字符串。

示例:

$(word2,foobarbaz)返回值是“bar”。

名称:

取单词串函数——wordlist。

$(wordlist,,

功能:

从字符串中取从开始到的单词串。

是一个数字。

返回:

返回字符串中从的单词字串。

如果中的单词数要大,那么返回空字符串。

如果大于的单词数,那么返回从开始,到结束的单词串。

示例:

$(wordlist2,3,foobarbaz)返回值是“barbaz”。

名称:

单词个数统计函数——words。

$(words

功能:

统计中字符串中的单词个数。

返回:

返回中的单词数。

示例:

$(words,foobarbaz)返回值是“3”。

备注:

如果我们要取中最后的一个单词,我们可以这样:

$(word$(words),)。

名称:

首单词函数——firstword。

$(firstword

功能:

取字符串中的第一个单词。

返回:

返回字符串的第一个单词。

示例:

$(firstwordfoobar)返回值是“foo”。

备注:

这个函数可以用word函数来实现:

$(word1,)。

以上,是所有的字符串操作函数,如果搭配混合使用,可以完成比较复杂的功能。

这里,举一个现实中应用的例子。

我们知道,make使用“VPATH”变量来指定“依赖文件”的搜索路径。

于是,我们可以利用这个搜索路径来指定编译器对头文件的搜索路径参数

CFLAGS,如:

overrideCFLAGS+=$(patsubst%,-I%,$(subst:

,$(VPATH)))

如果我们的“$(VPATH)”值是“src:

../headers”,那么“$(patsubst%,-I%,$(subst:

,$(VPATH)))”将返回“-Isrc-I../headers”,这

展开阅读全文
相关搜索
资源标签

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2