您的位置:首页 > 编程语言 > C语言/C++

C++ 学习笔记(三) 编写makefile(二)

2015-05-31 13:59 253 查看
前面写了最简单的makefile文件,现在继续学习一下进阶的版本吧。

1.使用变量代替重复劳动,实现多处同步修改

Makefile中的变量其实就是C/C++中的宏

定义可以个变量的格式为: 

  变量名 = 变量值   //这里的变量值,一般来说都是字符串

例如:objects = main.o parseMethod.o \
parserBase.o V8Script.o
定义了一个 objects 变量,其代表了一些.o文件的合集。

然后我们就可以直接使用它了:

html:$(objects)
g++ -o html $(objects)
其原理和C/C++中的宏是一样的,都是在使用变量的地方直接用变量值替换变量

2.clean 进阶

.PHONY:clean

clean:
-rm html $(objects)  # 减号 的意思是:如果某个文件出现错误了,不要管,继续执行下去

可以定义clean是伪目标,这样在使用中会方便很多;

rm指令前加上了减号(-),表示在删除后面的文件时,如果某个文件出错,则不理会当前错误,删除下一条。

减号(-)在许多指令上都可以使用

3.makefile引入文件include

makefile和C/C++一样,都可以引入别的文件。

其格式为:

  include 文件名

例如:

include object.mk这样子我们就可以将全部变量放在一个独立的文件中,以实现整个makefile的整洁以及维护的便利性。

3.通配符

波浪号(“~”)字符在文件名中也有比较特殊的用途。如果是“~/test”,这就表示当前用户的$HOME目录下的test目录。

make支持三各通配符:“*”,“?”和“[...]”

4.文件搜寻

文件搜寻主要时用于提示makefile在哪几个目录中寻找目标文件

定义文件搜寻,主要有两种方法:

(1)使用系统内置变量VPATH(全大写)

VPATH = src:../headers

  冒号(:)为分隔符,表示先在src目录下寻找,再在../headers目录下寻找。但是其默认的第一寻找路径仍然时当前路径

(2)使用vpath(全小写)关键字

格式为:vpath 条件 目录

例如:

vpath %.h ../headers
表示所有的.h文件,都在../headers目录下寻找

当然这里也支持多个目录的情况:

vpath %.h ../headers:bin或者

vpath %.h ../headers
vpath %.h bin

两个的意思都是一样的

5.伪目标

伪目标的一个特性是:它总比它的依赖文件要旧,也就是说,伪目标总是被执行的。

因此,我们可以写成这样:

# All Target
all: html

html: html.o
gcc -o html html.o

.PHONY all

这样子的话,因为all时伪目标,因此,可执行文件html始终会被创建。

其实际效果等同于在makefile文件的第一行直接书写:

html: html.o
gcc -o html html.o

当然这是一种简单的情况。实际上,有时候我们需要一次性编译多个可执行文件。那么这个时候,使用伪目标就能实现我们的目的。否则的话,makefile只会将文件第一行的目标作为最终目标,无法实现一次性编译多个目标。

例子如下:

all : prog1 prog2 prog3
.PHONY : all

prog1 : prog1.o utils.o
cc -o prog1 prog1.o utils.o

prog2 : prog2.o
cc -o prog2 prog2.o

prog3 : prog3.o sort.o utils.o
cc -o prog3 prog3.o sort.o utils.o


6.特殊变量 %@ %<

%@用于指代目标,并且是保留后缀名的

%<用于指代依赖文件,同样是保留后缀名的

7.静态模式

我个人理解的静态模式,就是一个foreach语句,实现了对目标集合的遍历。

其格式如下:

  目标集合: 目标: 依赖文件

  执行语句

用一个例子来解释一下:

objects = foo.o bar.o test.etc result
$(objects): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
objects是一个目标集合,含有多种元素(.o)( .etc)以及可执行文件

在静态模式中,首先从目标集合中一个个取出符合条件的目标。

即取出满足( %.o)的目标,也就是所有的.o文件。%在这里属于一个通配符,其代表的就是当前目标的名字(不包含后缀名)

对于每个取出的目标,再生成这个目标对应的依赖文件。也就是生成( %.c),使用当前目标的名字替代%。

实际上这里有时候会隐藏掉( %.c),这是因为makefile可以隐形的推导出目标文件的c文件

再之后,就是对取出的目标,生成对应的执行语句了,同样的时使用变量替代的形式。 $<  和 $@ 参考上面的说明吧

于是,这么一段静态模式,等同于:

foo.o : foo.c
$(CC) -c $(CFLAGS) foo.c -o foo.o
bar.o : bar.c
$(CC) -c $(CFLAGS) bar.c -o bar.o

8.自动生成依赖性

编译器语言 gcc -MM main.c 可以自动根据main.c的include语句生成对应的依赖文件例如 main.o : main.c defs.h

因通常的,我们会让编译器自己生成这种依赖关系,然后存放到同名文件的(.d)文件下

然后我们在主makefile文件中,再引用(.d)文件,来达到一个动态生成依赖文件的目的

9.指定目标

如果我们直接执行make命令,那么默认的是执行文件中的第一个目标。

但是我们也可以在make后面指定我们的目标。类似于 make clean这样子。

于是,我们可以在makefile中实现多种功能了:

“all” 
        这个伪目标是所有目标的目标,其功能一般是编译所有的目标。 
     “clean” 
        这个伪目标功能是删除所有被make创建的文件。 
     “install” 
        这个伪目标功能是安装已编译好的程序,其实就是把目标执行文件拷贝到指定的目标中去。 
     “print” 
        这个伪目标的功能是例出改变过的源文件。 
     “tar” 
        这个伪目标功能是把源程序打包备份。也就是一个tar文件。 
     “dist” 
        这个伪目标功能是创建一个压缩文件,一般是把tar文件压成Z文件。或是gz文件。 
     “TAGS” 
        这个伪目标功能是更新所有的目标,以备完整地重编译使用。 
     “check”和“test” 
        这两个伪目标一般用来测试makefile的流程。 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c++ makefile