本篇文章进行自动化构建项目make的学习!!!
注意:make:是一个指令,Makefile/makefile:是一个文件
概念:
makefile是用来自动化构建项目的,它侧面说明了一个人是否具备完成大型工程的能力
make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命
令,比如:Delphi、Visual C++、Linux下GNU的make
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率
make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建
一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
简单的写一个例子:
我们有:test.h、test.cpp、main.cpp 这几个文件
[lyh_sky@localhost lesson9]$ cat test.cpp
#include
using namespace std;
int main()
{
cout << "hello world!!!" << endl;
return 0;
}
[lyh_sky@localhost lesson9]$ cat makefile
test:test.cpp
g++ test.cpp -o test -g
.PHONY:clean
clean:
rm -rf test
[lyh_sky@localhost lesson9]$ make
g++ test.cpp -o test -g
[lyh_sky@localhost lesson9]$ ls
makefile test Test test.cpp
[lyh_sky@localhost lesson9]$ ./test
hello world!!!
依赖关系:
依赖方法:
PHONY clean:定义一个伪目标,依赖关系:
依赖方法:
注意:目标和伪目标都要通过make + 目标/伪目标 进行执行,make默认执行第一条目标
.PHONY关键字:
.PHONY:makefile语法格式中的一个关键字,被其修饰后,表明:“总是会被执行的”,意思是:不管目标文件是否新旧,照旧执行依赖关系!!!
没有被修饰的目标文件,表明:“总是不会被执行的”,意思是:如果目标文件的属性没有发生改变,就不会执行依赖关系!!!
makefile是怎么识别【BinFile】是新的还是旧的呢?
stat指令查看文件的最近访问/更改/改动的时间
lyh_sky@localhost lesson9]$ stat test
文件:"test"
大小:19552 块:40 IO 块:4096 普通文件
设备:fd00h/64768d Inode:1495017 硬链接:1
权限:(0775/-rwxrwxr-x) Uid:( 1000/ lyh_sky) Gid:( 1000/ lyh_sky)
环境:unconfined_u:object_r:user_home_t:s0
Access:2022-10-31 17:11:37.630903494 +0800 // 最近访问
Modify:2022-10-31 17:11:33.745549967 +0800 // 最近更改
Change:2022-10-31 17:11:33.745549967 +0800 // 最近改动
创建时间:-
文件 = 内容 + 属性
Access(最近访问):表示最后一次访问,访问文件到一定次数时,会刷新Access的时间
Modify(最近更改):表示最后一次修改文件内容,文件的内容发生改变时,会刷新Modify的时间
make是如何工作的,在默认的方式下,也就是我们只输入make命令!!那么:
make会在当前目录下找名字叫“Makefile”或“makefile”的文件
如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“test”这个文件,并把这个文件作为最终的目标文件
如果test文件不存在,或是test所依赖的后面的test.cpp文件的文件修改时间要比test这个文件新(可以用 echo 测试),那么,他就会执行后面所定义的命令来生成test这个文件
如果test所依赖的test.cpp文件不存在,那么make会在当前文件中找目标为test.cpp文件的依赖性,如果找到则再根据那一个规则生成test文件。(这有点像一个堆栈的过程)
这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件
在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理
make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦
项目清理:
clean伪目标,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要make执行。即命令——“make clean”,以此来清除所有的目标文件,以便重编译
但是一般我们这种clean的目标文件,我们将它设置为伪目标,用 .PHONY 修饰,伪目标的特性是,总是被执行的
项目清理:
当程序需要清理时,就必须写一个清理所生成的文件的伪目标
像clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要make执行。即命令——“make clean”,以此来清除所有的目标文件,以便重编译
但是一般我们这种clean的目标文件,我们将它设置为伪目标,用 .PHONY 修饰,伪目标的特性是,总是被执行的
[lyh_sky@localhost Test]$ cat test.h
#pragma once
#include
using namespace std;
void Show();
[lyh_sky@localhost Test]$ cat test.cpp
#include "test.h"
void Show()
{
cout << "hello world!!!" << endl;
}
[lyh_sky@localhost Test]$ cat main.cpp
#include "test.h"
int main()
{
Show();
return 0;
}
[lyh_sky@localhost Test]$ cat makefile
test:test.o main.o
g++ test.o main.o -o test
test.o:test.cpp
g++ -c test.cpp -o test.o
main.o:main.cpp
g++ -c main.cpp -o main.o
.PHONY:clean
clean:
rm -rf *.o test
[lyh_sky@localhost Test]$ make
g++ -c test.cpp -o test.o
g++ -c main.cpp -o main.o
g++ test.o main.o -o test
[lyh_sky@localhost Test]$ ls
main.cpp main.o makefile test test.cpp test.h test.o