赞
踩
目录
首先说明一下 make 事一条指令,而 makefile 事一个当前目录下的一个文件
make 和 makefile是一个自动化构建工具,因为在我们的项目中我们需要经常去编译,如果一直使用 gcc/g++ 命令编译时比较麻烦的,所以我们就需要一个自动化构建工具,而makefile文件里面就写的是如何编译,以及 make 和 makefile可以进行自动化推导编译
注:makefile/Makefile 都是可以的,首字母大小写都可以
我们现在有一个 mycode.c 的文件,我们要用makefile去写编译他的内容
[lxy@hecs-165234 test8]$ touch makefile
[lxy@hecs-165234 test8]$ vim makefile
[lxy@hecs-165234 test8]$ cat makefile
mycode:mycode.c
gcc -o mycode mycode.c
我们的下面的两行就是我们的 makefile 编辑 mycode.c 文件的内容,我们介绍一下里面的内容
1. 第一行的 mycode:mycode.c 就是依赖关系
2. 第二行的 gcc -o mycode mycode.c 就是依赖方法
我们看一下是否可以对 mycode.c 文件进行编译,在这之前我们先编写 mycode.c 文件,在 mycode.c 文件里面我们写 hello world
[lxy@hecs-165234 test8]$ vim mycode.c
[lxy@hecs-165234 test8]$ cat mycode.c
#include<stdio.h>int main()
{
printf("Hello World\n");
printf("Hello World\n");
printf("Hello World\n");
printf("Hello World\n");
printf("Hello World\n");
return 0;
}
[lxy@hecs-165234 test8]$ make //make 就是make 指令的简单使用,后面还回介绍
gcc -o mycode mycode.c
[lxy@hecs-165234 test8]$ ll
total 20
-rw-rw-r-- 1 lxy lxy 42 Jul 3 17:15 makefile
-rwxrwxr-x 1 lxy lxy 8360 Jul 3 17:20 mycode
-rw-rw-r-- 1 lxy lxy 181 Jul 3 17:20 mycode.c
[lxy@hecs-165234 test8]$ ./mycode
Hello World
Hello World
Hello World
Hello World
Hello World
我们看到是没有问题的,并且也运行出来了
下面回答一下什么是依赖关系和依赖方法
1. 依赖关系:我们知道我们想要编译 mycode.c 文件,然后重命名为 mycode,那么就是我们的 mycode 文件的生成需要依赖于 mycode.c 文件,上面这个就是我们的依赖关系
2. 依赖方法:依赖方法就是更具依赖关系,看如何能让我们的 mycode.c 文件生成 mycode 文件,如果是我们的C语言的话,那么我们的依赖方法就是使用 gcc 编译生成,如果是我们的 C++的话,那么我们就要使用 g++ 编译
既然我们的 makefile 可以编写生成方案的指令,那么当然也可以编写清理方案的指令
[lxy@hecs-165234 test8]$ cat makefile
mycode:mycode.c
gcc -o mycode mycode.c
clean:
rm -rf mycode
[lxy@hecs-165234 test8]$ make clean
rm -rf mycode
我们的 makefile 里面添加了两行代码,其中 clean: 就是依赖关系,只是这里的 clean 并不需要依赖任何文件,而我们的依赖方法就是 删除掉之前的生成方案
我们看到,我们在生成解决方案的时候只是使用了 make, 但是我们在清理解决方案的时候还加了 make clean ,那么为什么这样,下面我们做实验看一下
1. 我们尝试使用 make mycode 我们看可不可以
[lxy@hecs-165234 test8]$ make mycode
gcc -o mycode mycode.c
[lxy@hecs-165234 test8]$ ll
total 20
-rw-rw-r-- 1 lxy lxy 64 Jul 3 18:13 makefile
-rwxrwxr-x 1 lxy lxy 8360 Jul 3 18:18 mycode
-rw-rw-r-- 1 lxy lxy 181 Jul 3 17:20 mycode.c
我们看到是可以的,而且我们直接使用 make 也是可以调用makefile里面第一个依赖的
2. 我们将 clean放到 makefile 前面,在使用make
[lxy@hecs-165234 test8]$ vim makefile
[lxy@hecs-165234 test8]$ cat makefile
clean:
rm -rf mycode
mycode:mycode.c
gcc -o mycode mycode.c
[lxy@hecs-165234 test8]$ make
rm -rf mycode
我们的实验结果是将 clean 放到前面,然后直接 make 就是使用的是 clean 说明:我们的 make 默认会使用第一个依赖
前面只是 makefile 的简单编写,下面我会说几个比较实用的编写技巧
我们编写的makefile,在 make的时候会回显,如果我们不想回显怎么办?
在依赖方法前面加 @
[lxy@hecs-165234 test8]$ vim makefile
[lxy@hecs-165234 test8]$ cat makefile
clean:
@rm -rf mycode
mycode:mycode.c
@gcc -o mycode mycode.c
[lxy@hecs-165234 test8]$ make
[lxy@hecs-165234 test8]$
在我们编写makefile的时候,我们有时候需要的依赖关系很多,自己写可能会输入错误,所以我们可以借助两个特殊符号来代替依赖关系中的文件名
$@ $^
[lxy@hecs-165234 test8]$ cat makefile
mycode:mycode.c
@gcc -o $@ $^clean:
@rm -rf mycode
[lxy@hecs-165234 test8]$ make
[lxy@hecs-165234 test8]$ ll
total 20
-rw-rw-r-- 1 lxy lxy 57 Jul 3 18:32 makefile
-rwxrwxr-x 1 lxy lxy 8360 Jul 3 18:32 mycode
-rw-rw-r-- 1 lxy lxy 181 Jul 3 17:20 mycode.c
$@ 代表:依赖关系前面的内容
$^ 代表:依赖关系后面的内容
有了上面两个,makefile 编写起来就相对容易了
我们现在对我们的 mycode.c 文件进行多次 make,我们看可不可以?
[lxy@hecs-165234 test8]$ make
make: `mycode' is up to date.
[lxy@hecs-165234 test8]$ make
make: `mycode' is up to date.
[lxy@hecs-165234 test8]$ make
make: `mycode' is up to date.
我们多次 make的话,我们看到我们的 make 是不允许继续make的,为什么呢?(这个下面说)
那么我们如何解决这个问题?
.PHONY
.PHONY:.PHONY 后面跟的叫做伪目标,有什么作用?跟在 .PHONY 后面的在执行的时候总是会被执行
[lxy@hecs-165234 test8]$ vim Makefile
[lxy@hecs-165234 test8]$ cat Makefile
.PHONY:mycode
mycode:mycode.c
gcc -o $@ $^
clean:
rm -rf mycode
我们在 .PHONY 后面添加伪目标 mycode
下面我们多执行几次 make
[lxy@hecs-165234 test8]$ make
gcc -o mycode mycode.c
[lxy@hecs-165234 test8]$ make
gcc -o mycode mycode.c
[lxy@hecs-165234 test8]$ make
gcc -o mycode mycode.c
我们看到是可以执行的,但是我们并不建议把 生成解决方案放在 .PHONY 后面,因为这样每一次都会编译,会浪费时间,我们建议把 clean 清理解决方案跟在 .PHONY 后面
我们现在想要对 mycode.c 文件进行详细编译,也就是将编译的每一步都显示出来(.i 文件, .s 文件,.o 文件)那么我们要怎么编写makefile文件?
[lxy@hecs-165234 test8]$ cat makefile
mycode:mycode.o
gcc -o mycode mycode.o
mycode.o:mycode.s
gcc -c mycode.s -o mycode.o
mycode.s:mycode.i
gcc -S mycode.i -o mycode.s
mycode.i:mycode.c
gcc -E mycode.c -o mycode.i
clean:
rm -rf mycode mycode.i mycode.s mycode.omake
[lxy@hecs-165234 test8]$ make
gcc -E mycode.c -o mycode.i
gcc -S mycode.i -o mycode.s
gcc -c mycode.s -o mycode.o
gcc -o mycode mycode.o[lxy@hecs-165234 test8]$ ll
total 48
-rw-rw-r-- 1 lxy lxy 235 Jul 3 18:47 makefile
-rwxrwxr-x 1 lxy lxy 8360 Jul 3 18:47 mycode
-rw-rw-r-- 1 lxy lxy 181 Jul 3 18:43 mycode.c
-rw-rw-r-- 1 lxy lxy 16986 Jul 3 18:47 mycode.i
-rw-rw-r-- 1 lxy lxy 1728 Jul 3 18:47 mycode.o
-rw-rw-r-- 1 lxy lxy 565 Jul 3 18:47 mycode.s
我们看到生成了,我们想要的文件,但是我们发现我们的make后的执行顺序并不是按照我们的 makefile 里面的顺序来的
解释:因为我们的 mycode 需要依赖于我们的 mycode.o,但是我们没有 mycode.o 文件,所以我们需要先获得 .o 文件,以此类推就是这样,而我们的 make 编译就像递归一样,而这就是我们的make的 编译会自动推导
我们在上面说,为什么前面连续 make 会make失败
原因:因为我们连续make的话,是比较浪费时间的,所以我们的 make 会根据 源文件和 目标文件的最新修改时间进行对比,如果目标文件比源文件时间要新的话,那么就说明不需要 make 否则需要。
那么我们的 make 是如何得知文件是否被修改的?
解释:在我们的文件中,会有三个时间
ACCESS
MODIFY
CHANGR
指令:stat + 文件名
以 mycode 文件为例
[lxy@hecs-165234 test8]$ stat mycode
File: ‘mycode’
Size: 8360 Blocks: 24 IO Block: 4096 regular file
Device: fd01h/64769d Inode: 1968773 Links: 1
Access: (0775/-rwxrwxr-x) Uid: ( 1000/ lxy) Gid: ( 1000/ lxy)
Access: 2023-07-03 19:03:29.608149503 +0800
Modify: 2023-07-03 19:03:29.608149503 +0800
Change: 2023-07-03 19:03:29.608149503 +0800
Birth: -
三个时间介绍
access 就是我们的文件的左后一次访问时间,不管是我们打开进行查看,还是我们 cat 一下,亦或者是我们对其进行修改,都算访问,但是我们由于需要经常访问,所以我们的 访问时间是一直需要变化的,但是我们的 ACCESS 时间实际是访问几次后才变一次,原因是,由于我们的 ACCESS 算是文件属性,既然是这样,那么说明我们的这些信息是存在磁盘中的,而我们存在磁盘中,如果一直进行访问磁盘无疑是浪费时间的,所以我们的 ACCESS时间是访问几次后变化一次
我们的三个时间里面还有一个时间叫 CHANGE 我们这两个单词的意思都是修改那么有什么不透吗?
这里先说 modify,我们知道我们的文件信息包含两种
1. 文件内容
2.文件属性
而我们这里的 modify 就指的是文件内容,但是我们的文件内容修改了,一般也就待变属性也修改了,因为我们的文件内容一旦修改,大概率我们的 文件大小也就变了,所以我们的文件属性也就自然修改了
我们的 CHANGE 代表的文件属性的修改,而我们的文件属性就包含大小以及文件本来的属性之类的,还有就是那些所属组,拥有者等...
我们的文件属性的修改并不一定会修改MODIFY
这就是我们的文件的三个时间
既然我们知道我们的文件是有时间的,所以我们的 make 只需要对比源文件和目标文件的新旧,就可以知道源文件是否被修改,而我们的 make 只需要对比 MODIFY 时间就好了
指令:touch
我们的 touch 指令,如果后面的文件名是新的,那么就是创建一个文件,如果是以有的,那么就是修改文件的时间
[lxy@hecs-165234 test8]$ touch mycode.c
[lxy@hecs-165234 test8]$ stat mycode.c
File: ‘mycode.c’
Size: 181 Blocks: 8 IO Block: 4096 regular file
Device: fd01h/64769d Inode: 1968744 Links: 1
Access: (0664/-rw-rw-r--) Uid: ( 1000/ lxy) Gid: ( 1000/ lxy)
Access: 2023-07-03 19:25:06.916600634 +0800
Modify: 2023-07-03 19:25:06.916600634 +0800
Change: 2023-07-03 19:25:06.916600634 +0800
Birth: -
我们的 mycode.c 已经全部更新为了最新时间,如果我们只想跟新 MODIFY 那么我们带 -m 选项
[lxy@hecs-165234 test8]$ touch -m mycode
[lxy@hecs-165234 test8]$ stat mycode
File: ‘mycode’
Size: 8360 Blocks: 24 IO Block: 4096 regular file
Device: fd01h/64769d Inode: 1968773 Links: 1
Access: (0775/-rwxrwxr-x) Uid: ( 1000/ lxy) Gid: ( 1000/ lxy)
Access: 2023-07-03 19:03:29.608149503 +0800
Modify: 2023-07-03 19:27:37.160520398 +0800
Change: 2023-07-03 19:27:37.160520398 +0800
Birth: -
touch 的选项意义
-a change only the access time
-c, --no-create
do not create any files-d, --date=STRING
parse STRING and use it instead of current time-f (ignored)
-h, --no-dereference
affect each symbolic link instead of any referenced file (useful only on systems that can change the timestamps of a symlink)-m change only the modification time
-r, --reference=FILE
use this file's times instead of current time-t STAMP
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。