一、Makefile介绍
make命令执行时,需要一个makefile文件,告诉make命令需要怎样去编译和链接程序。Makefile是一个文件,用来管理项目,Makefile文件里面保存的就是对文件的编译规则。make是一个可执行程序,一个工具,用来解析Makefile。
二、makefile
1、Makefile体验版本
all: //标签
gcc *.c -o app //编译所有的.c文件
clern: //标签
rm app //删除可执行文件app编译:make 或者 make all
make clern (删除上一次编译得到的可执行程序)
2、Makefile格式
目标 :依赖
命令
eg:
APP:func1.o fun2.o main.o
gcc fun1.o fun2.o main.o -o APP
//目标:APP 依赖:fun1.o fun2.o main.o
fun1.o:fun1.c
gcc -c fun1.c -o fun1.o
//目标:fun1.o 依赖:fun1.c
fun2.o:fun2.c
gcc -c fun2.c -o fun2.o
//目标:fun2.o 依赖:fun2.c
main.o:main.c
gcc -c main.c -o main.o
//目标:main.o 依赖:main.c
clern:
rm *.o APP //删除所有的.o文件
3、Makefile中变量的引用
$(var) 或者 ${var}
(1)变量的赋值---- ‘=’
eg:
var1=abc
var2=$(var1)
var1=defall:
echo var1=$(var1) var2=$(var2)
//结果 var1=def var2=def
//如果一个变量后面被重新赋值,那么Makefile编译会取最新的值
(2)直接赋值----‘:=’
:= 如果一个变量的值在后面被更新,会取当前的值
eg:
var1 := abc
var := $(var1)
var1 := def
all:
echo var1=$(var1) var2=$(var2)
结果:var1=def var2=abc
(3)询问赋值---'?='
?= 再赋值之前会询问一下以前赋值过没有,如果赋值过,那么此时赋值无效,没有赋值过就采用当前的赋值
eg:
var1=abc
var1 ?= def
all:
echo var1 = $(var1)
结果 var1=abc,如果屏蔽var1=abc则结果为var1=def
(4)追加赋值-----'+='
+=
eg:
str=abc
str1=def
str += $(str1)
结果:str1=abc def
(5)特殊变量:
$@:目标
$^:第一个依赖
$< :所有的依赖
eg:
CC = gcc
TARGET = APP
OBJS = func1.o func2.o main.o
FLAGS = -c -o
$(TARGET):$(OBJS)
$(CC) $(OBJS) -o $@ //gcc fun1.o fun2.o main.o -o APP
func1.o:fun1.c
$(CC) $(FLAGS) $@ $< // gcc -c fun1.c -o fun1.o
func2.o:fun2.c
$(CC) $(FLAGS) $@ $< //gcc -c fun2.c -o fun2.o
main.o:main.c
$(CC) $(FLAGS) $@ $< // gcc -c main.c -o main.o
clern:
rm -r $(OBJS) $(TARGET) //删除所有的.o文件
用通配符进行简写:
Linux中的通配符
所有------'*'
Makefile中的通配符
所有-----'%'
eg:
CC = gcc
TARGET = APP
OBJS = func1.o func2.o main.o
FLAGS = -c -o
$(TARGET):$(OBJS)
$(CC) $(OBJS) -o $@ //gcc fun1.o fun2.o main.o -o APP
%.o:%.c // gcc -c fun1.c -o fun1.o
$(CC) $(FLAGS) $@ $^ //gcc -c fun2.c -o fun2.o
// gcc -c main.c -o main.o
clern:
rm -r $(OBJS) $(TARGET) //删除所有的.o文件
三、Makefile的一些相关试题
1、下面关于Makefile中定义包命令的描述,不正确的是( D )
A.定义包语法是以“define”开始,以“endef”结束B.在使用定义包时,需要给包起一个名字,这个名字是紧跟在define后面的C.定义包的使用方法同变量相同,比如$(包名称)D.定义包和变量不同,因此定义包和变量可以重名解析:
定义和变量之间是有区别的,但是二者的使用方法相同,当重名的时候,系统无法判断该使用哪一个
2、 在Makefile中写入以下函数,则foo的值是( B )
reverse = $(2) $(1)
foo = $(call reverse,a,b)
A.a,bB.b,aC.a bD.b a解析:
call函数是唯一一个可以用来创建新的参数化的函数。
其语法是:
$(call <expression>,<parm1>,<parm2>,<parm3>...)
当make执行这个函数时,<expression>参数中的变量,如$(1),$(2),$(3)等,会被参数<parm1>,<parm2>,<parm3>依次取代。而<expression>的返回值就是call函数的返回值.
3、 在Makefile中,定义了三个变量“foo”、“Foo”和“FOO”,这三个变量的关系正确是( D )
A.foo和Foo相同B.foo和FOO相同C.Foo和FOO相同D.互不相同。解析:
在Makefile中,变量是大小写是非常敏感的,区分大小写。
4、 在Makefile中,有个目标target有两个依赖target1和target2(target:target1 target2),target1和target2又是其他规则中的目标,那么当执行make target时,( )对应的命令最先执行,( )对应的最后命令后( A )
A.target1 targetB.target2 targetC.随机的D.target target1解析:
执行循序:先按依赖中的顺序执行,再到目标
5、 在Makefile中有三个变量的定义,分别是var = test1 ,var2 = var,和var3 = $($(var2)),下列选项中关于var3的描述,正确的是( B )
A.var3在定义时,使用了嵌套的方式,这种目前在Makefile中不支持B.var3最后的值是test1C.make系统中无法识别var3的定义方式,导致var3最后为空D.var3最后的值是var2解析:
Makefile中变量的引用 $(var) 或者 ${var}
6、下列关于makefile描述正确的有?(ABC)
A.makefile文件保存了编译器和连接器的参数选项B.主要包含了五个东西:显式规则、隐晦规则、变量定义、文件指示和注释C.默认的情况下,make命令会在当前目录下按顺序找寻文件名为“GNUmakefile”、“makefile”、“Makefile”的文件, 找到了解释这个文件D.在Makefile不可以使用include关键字把别的Makefile包含进来解析:
Makefile里主要包含了五个东西:显式规则、隐晦规则、变量定义、文件指示和注释。
1、显式规则。显式规则说明了,如何生成一个或多的的目标文件。这是由Makefile的书写者明显指出,要生成的文件,文件的依赖文件,生成的命令。2、隐晦规则。由于我们的make有自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写Makefile,这是由make所支持的。
3、变量的定义。在Makefile中我们要定义一系列的变量,变量一般都是字符串,这个有点你C语言中的宏,当Makefile被执行时,其中的变量都会被扩展到相应的引用位置上。
4、文件指示。其包括了三个部分,一个是在一个Makefile中引用另一个Makefile,就像C语言中的include一样;另一个是指根据某些情况指定Makefile中的有效部分,就像C语言中的预编译#if一样;还有就是定义一个多行的命令。有关这一部分的内容,我会在后续的部分中讲述。
5、注释。Makefile中只有行注释,和UNIX的Shell脚本一样,其注释是用“#”字符,这个就像C/C++中的“//”一样。如果你要在你的Makefile中使用“#”字符,可以用反斜框进行转义,如:“\#”。在Makefile使用include关键字可以把别的Makefile包含进来
7、在Makefile使用中,如果想把别的Makefile包含进来,使用哪个关键字(A)
A.includeB.externalC.importD.in解析:
在Makefile使用include关键字可以把别的Makefile包含进来
include的语法是: include <filename>
以上试题来源于牛客网。