赞
踩
- 默认有以下三种:
- GNUmakefile
- Makefile
- makefile
- 当然你还可以使用指定Makefile的文件名, 例如:
- Make.Linux (非默认Makefile文件名)
- Make.type(非默认Makefile文件名)
- 不过当你设置的Makefile文件的名称不为默认名称时, 运行相应的make命令需要携带参数指明具体的文件名, 例如
- make -f Make.Linux // 编译Make.Linux中的第一个目标文件
- make -f Make.Linux clean // 执行Make.Linux中的 clean
Makefile它是一个文件, 文件中的内容描述了如何在Linux系统下
C/C++工程的编译规则
Makefile为我们所带来的好处便是 --- 自动化编译, 当我们为大
型项目编写好对应的makefile文件后, 我们只需要一个指令 make, 整个
工程就会进行自动化编译, 最终按照我们的预期生成最终目标文件
Makefile文件定义了一系列规则, 指明了文件的编译顺序, 文件与
文件之间的依赖关系以及是否需要重新编译等
总而言之, 我们使用makefile的原因便是, 它可以极大的简化文件的编译过程。
当我们为工程编写了一个Makefile文件, 然后通过make指令便可以进行工程的自动化编译 那么make运行的规则是什么呢?
- 如果这个工程未被编译过, 那么我们编译并连接makefile中指明的所有C/Cpp文件
- 如果这个工程已被编译过, 但是某几个C文件被修改, 那么我们只编译被修改过的文件, 并链接目标程序
- 如果该工程的头文件被修改, 那么我们需要编译所有引用了该头文件的C/Cpp文件,并链接目标程序。
好的,现在我们知道了make指令的运行规则。 那么我们要如何编写一个
Makefile文件呢?
请看下文:
target : prerequisites
command
// target -- 目标文件, 是我们在整个自动化编译过程中想要得到的文件
// prerequisites -- 先决条件 , 也就是生成target目标文件的前提条件,在这里我们把它叫做依赖文件, 依赖文件是生成目标文件的前提条件。
// command -- 指令, 它是可以在shell命令行中运行的linux命令, 在这里我们将其称为 依赖关系 。 也就是目标文件与依赖文件之间的依赖关系。 它描述了如何通过依赖文件去生成目标文件
// 另外的 command指令前面的空白是 Tab键形成的(必须是Tab, 这是规定)
// 简单来说 , target - 目标文件它依赖于一个或多个 prerequisites中的文件, 也就是依赖文件, command中定义了生成规则
下面来个示例 :
假设现在我们要编写一个C程序, 它有一个头文件, 两个.c文件
分别是 test.h test.c main.c
那我们所要编写的Makefile文件如下:
mybin : main.c test.c test.h
gcc -o mybin main.c test.c test.h
// 在这里 mybin是要生成的目标文件
// main.c test.c test.h 是生成目标文件所依赖的文件
// gcc -o .. 这一行是依赖关系, 也就是生成目标文件要执行的命令
// 当我们在shell命令行提示符后 运行 make指令, 它就会自动化编译并且生成一个名叫 mybin的可执行文件
当我们编写好一个Makefile文件时, 使用指令make就可以自动化编译并生成最终目标文件。
如果我们对其中一个源文件进行了修改, 再次运行make指令。 那么 , make又是怎么知道是否要生成这个目标文件呢 ?
Makefile的显式规则:
- 在我们使用make指令后, Makefile通过比较目标文件与依赖文件的最近修改时间来确定是否要执行make指令,生成新的目标文件
- 文件的时间属性中包含三个时间
- access – 最近访问时间
- modify – 文件内容最近修改时间
- change – 文件属性最近修改时间
- Makefile就是通过比较 modify 文件内容的最近修改时间, 如果目标文件的modify最新, 那么就不执行make指令; 反之 , 就执行make指令生成新的目标文件是在原目标文件的基础上进行修改)
在日常的程序设计中, 编译大型程序会生成多个目标文件, 当我们不需要这些目标文件时,肯定想要一个指令自动删除多个目标文件。
Makefile支持这样的操作
clean:
command
// clean -- 它并不是一个目标文件, 而是一个标签。 不具备相应的依赖文件
// command -- 其中定义了我们所要执行的shell指令, 用于删除一个或多个目标文件
mybin : main.c test.c test.h
gcc -o mybin main.c test.c test.h
clean:
rm mybin
// 例如上述的示例中, 我们添加clean这样的内容
// 当我们在shell的命令行提示符中输入 make clean, 它就会自动执行 clean对应的 rm mybin , 进而删除目标文件mybin
如果你去连续多次运行make 或者make clean, 那么它一定会出现如下的提示
[Jin_Nian@VM-4-8-centos test01_dir]$ make clean
rm *.c *.h
rm: cannot remove ‘*.c’: No such file or directory
rm: cannot remove ‘*.h’: No such file or directory
make: *** [clean] Error 1
// 该提示告诉我们, 我们所要删除的文件并不存在 (或是所要创建的文件已存在 或是最新)
那我们如何在连续多次执行同一条make命令时, 忽略掉这样的提示呢
这就需要我们去声明一个伪目标了
通过特殊标记 .PHONY声明 “伪目标”
- 伪目标并不是一个文件,只是一个标签 。
- 伪目标具有总是被执行的特性
- .PHONY :name – 显式的声明一个伪目标
- 伪目标可以不需要依赖文件
- 伪目标也可以作为依赖文件
mybin : main.o test.o # mybin -- 默认为最终目标文件
gcc -o mybin $@ $^ # $@ -- 目标文件; $^ -- 依赖文件 ($@ $^这俩是自动变量)
main.o : main.c test.h # main.o -- 中间文件(也是目标文件)
gcc -c $@ $^
test.o : test.c test.h # test.o -- 中间文件(也是目标文件)
gcc -c $@ $^
.PHONY : clean // .PHONY声明的伪目标
clean : // clean 是个 标签 , 该标签下有我们想要执行的shell命令
rm mybin main.o test.o
GNU中的make很强大, 依据它的智能性, 它可以自动推导目标文件的依赖文件以及它们之间的依赖关系
make自动推导:
- make看到一个 [.o] 目标文件, 它会自动的把[.c]文件加入到依赖文件中
- 并且 会自动的推导出 .o 与 .c文件之间的依赖关系
- gcc -c file.o -o file.c (或是gcc -c -o file.o file.c)
- 也可以根据 gcc -c file.c 推导出 gcc -c -o file.o file.c
注意 : 在g++中这种自动推导部分不适用
有了自动推导, 我们可以编写更加简洁的Makefile文件了
mybin : main.o test.o
gcc -o mybin $@ $^
main.o : # 自动推导出 main.o : main.c
# gcc -c -o main.o main.c
test.o : # 自动推导出 test.o : test.c
# gcc -c -o test.o test.c
.PHONY : clean
clean :
rm mybin main.o test.o
Makefile中还存在对于变量的定义:
- 所定义的变量必须进行初始化
- 为命令定义变量, 例如 cc = gcc , -o = flag
- 为目标文件定义变量, 例如 target = mybin
- 为依赖文件定义变量, 例如 object = *.o
- 如何使用变量 , 假设定义了如下变量
cc = gcc
flag = -o
tar = mybin
obj = main.o
- 使用方式如下 :
$(tar) : $(obj)
cc $(flag) $(tar) $(obj) # 前面少了Tab键
- 所有的变量都要通过 $来使用 ,
- 加了括号只是为了便于区分, 避免出现错误
- 变量 cc 表示使用gcc 还是 g++ 来编译文件, 该变量可以直接使用, 也可以通过 $ 来使用
- Makefile中只有行注释, 和UNIX中的shell脚本一样, 其注释是用 # 字符声明的
- 如果我们要在Makefile中使用 # 的字面含义时, 需要 反斜杠 \ 对#进行转义 , 也就是 #
- 最后需要再次强调的一点是 , 在Makefile中的commad(任意的shell命令) 都要以 Tab键在开头留出空白
这里只介绍两个
- $@ – 代表目标文件
- $^ – 代表依赖文件
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。