makefile知识点归纳

我会带着你远行 2022-08-14 01:36 300阅读 0赞

以一个例子开始,文件目录结构如下
-————(当前目录)—————-main.c
|
|————add目录
| |———-add_int.cpp
| |———-add_float.cpp
|
|————sub目录
|————sub_int.cpp
|————sub_float.cpp

makefile文件如下:







#example 
CXX=g++
CXXFLAGS=-Iadd -Isub
OBJSDIR=.objs
VPATH=add:sub:.
OBJS=add_int.o add_float.o sub_int.o sub_float.o \



main.o



TARGET=cacu

$(TARGET):$(OBJSDIR) $(OBJS)


$(CXX) $(OBJSDIR)/.o $(CXXFLAGS) -o $@



$(OBJS):%.o:%.cpp


$(CXX) $< $(CXXFLAGS) -c -o $(OBJSDIR)/$@



$(OBJSDIR):


mkdir -p ./$@



.PHONY:clean
clean:
-$(RM) $(TARGET)
-$(RM) $(OBJSDIR)/
.o

(一)makefile的规则
规则的基本格式:







TARGET… : DEPENDES…


COMMAND




TARGET:规则所定义的目标,可以是Object File,也可以是执行文件。还可以是一个标签(Label)。
DEPENDES:执行此规则所必须的依赖条件。
COMMAND:规则所执行的命令(任意的shell命令)。

1.命令行必须以一个Tab键开始。
2.注释用“#”字符。
3.用反斜杠(\)可以将较长的行分解为多行。

(二)make是如何工作的
1.make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
2.如果找到,它会找文件中的第一个目标文件,并把这个文件作为最终的目标文件。定义在Makefile中的目标可能会有很多,但是 第一条规则中的目标将被确立为最终的目标。如果第一条规则中的目标有很多个,那么第一 个目标会成为最终的目标。
3.make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
例如







OBJS=add_int.o add_float.o
$(OBJS):%.o:%.cpp


$(CXX) $< -c -o $@


上面makefile只会编译add_int.cpp,如果要编译所有,可以加一个标签。







OBJS=add_int.o add_float.o
all:$(OBJS)
$(OBJS):%.o:%.cpp


$(CXX) $< -c -o $@


(三)搜索路径
指定需要搜索的目录后,make会自动找到指定文件的目录并添加到文件上。有两种指定搜索目录的方法.
方法一:







VPATH=path1:path2: …

例如
VPATH=add:sub:.
add_int.o:%.o:%.cpp

$(CXX) $< -c -o $@

会自动扩展成
add_int.o: add/ add_int.cpp

g++ add/add_int.cpp -c -o add_int.o

方法二:







vpath <pattern> <directories>

为符合模式的文件指定搜索目录
例如:
vpath %.h ../headers
make会在“../headers”目录下搜索所有以“.h”结尾的文件。

(四)伪目标







.PHONY:name

当执行“make name”时一定是执行makefile中的这个伪目标,而不管是否存在一个叫name的文件。

(五)makefile中的部分预定义变量


































 变量名  含义  默认值
 CC C语言编译器的名称  cc
 CXX C++ 语言编译器的名称  g++
 CFLAGS C语言编译器的编译选项  无
 CXXFLAGS C++语言编译器的编译选项  无
 RM  删除文件程序的名称  rm -f

(六)makefile中的自动变量




























 变量  含义
 $@  目标项中目标文件的名称
 $<  依赖项中第一个依赖文件的名称
 $^  所有不重复的依赖文件
 $*  目标文件的名称,不包含扩展名
 $?  依赖项中,所有目标文件时间戳晚的依赖文件

(七)静态模式







 < targets … >: < target-pattern >: < prereq-patterns … >


<command>


target-parrtern是指明了targets的模式
prereq-parrterns是目标的依赖模式,它对target-parrtern形成的模式再进行一次依赖目标的定义。
例子:







objects = foo.o bar.o
all: $(objects)
$(objects): %.o: %.c


$(CC) -c $(CFLAGS) $<  -o $@

定义成“%.o”,意思是我们的集合中都是以“.o”结尾的,而如果我们的定义成“%.c”,意思是对所形成的目标集进行二次定义,其计算方法是,取模式中的“%”(也就是去掉了[.o]这个结尾),并为其加上[.c]这个结尾,形成的新集合。

(八)嵌套执行make
我们有一个子目录叫add,这个目录下有个makefile文件,来指明了这个目录下文件的编译规则。那么我们总控的Makefile可以这样书写:







subsystem:


cd add && $(MAKE)


等价于







subsystem:


$(MAKE) -C add


1.如果你要让上一条命令的结果应用在下一条命令时,你应该使用分号(;)分隔这两条命令,或者使用“&&”。
2.如果你要传递变量到下级Makefile中,那么你可以使用这样的声明:







 export < variable … >

需要注意的是,有两个变量,一个是SHELL,一个是MAKEFLAGS,这两个变量不管你是否export,其总是要传递到下层makefile中。

(九)变量
变量在声明时需要给予初值,而在使用时,需要给在变量名前加上“$”符号,但最好用小括号“()”或是大括号“{}”把变量给包括起来。

1.当使用一个变量来定义另一个变量时需要注意:







foo=$(bar)
bar=hello world!

使用“=”号时,右侧变量的值可以定义在文件的任何一处,也就是说,右侧中的变量不一定非要是已定义好的值,其也可以使用后面定义的值。







bar=hello world!
foo:=$(bar)

使用”:=”号时,前面的变量不能使用后面的变量,只能使用前面已定义好了的变量。

2.空格







nullstring:=
space:=$(nullstring) # end of the line
dir:=/foo/bar    # directory to put the frobs in

nullstring 是一个Empty变量,其中什么也没有,而我们的space的值是一个空格,采用“#”注释符来表示变量定义的终止。
dir这个变量的值是“/foo/bar ”,后面跟了4个空格。

3.变量的静态模式







foo:=a.o b.o c.o
bar:=$(foo:%.o=%.c)

$(bar)变量的值为“a.c b.c c.c”。

4.变量的追加







objects=main.o foo.o bar.o utils.o
objects+=another.o

(十)隐含规则
对一个目标文件是“文件名.o”,依赖文件是“文件名.c”的规则,可以省略其编译规则的命令行。 因为如果make找到一个whatever.o,那么whatever.c,就会是whatever.o的依赖文件,并且 cc -c whatever.c 也会被推导出来。这样就可以省略掉描述.c文件和.o依赖关系的规则,而 只需要给出那些特定的规则描述(.o目标所需要的.h文件) 。

1.编译C程序的隐含规则
“filename.o”的目标的依赖目标会自动推导为“filename.c”,并且其 生成命令是“$(CC) –c $(CXXFLAGS) $(CFLAGS)”

2.编译C++程序的隐含规则
“filename.o”的目标的依赖目标会自动推导为“filename.cc”或是“filename.C”,并且其 生成命令是“$(CXX) –c $(CXXFLAGS) $(CFLAGS)”

参考:
陈皓的《跟我一起写 Makefile》 http://blog.csdn.net/haoel
宋敬彬的《Linux网络编程》

发表评论

表情:
评论列表 (有 0 条评论,300人围观)

还没有评论,来说两句吧...

相关阅读

    相关 国际经济合作知识归纳

    第一章 国际经济合作概述 一、国际经济合作的研究对象是什么?开展国际经济合作的基本前提是什么? 研究对象:生产要素在国际间的移动和重新组合配置(即生产要素的国际移动和重新组

    相关 《金融学》知识归纳

    《金融学》知识点归纳 第一章 一、货币产生的原因(马克思的劳动价值理论) 1、简单的、偶然的价值形式 2、扩大的价值形式 3、一般价值形式 4、货币价值形式 结论