make/Makefile
1. 背景
- 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力
- 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的 规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂 的功能操
- makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
- make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual
C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。- make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。
在VS当中,项目管理(多文件管理),VS帮我们自动管理
在Linux当中,维护项目文件关系的工作,需要让make/Makefile来完成
1.1 如何编写Makefile
这里打算编写一个计算器中加的功能键作为简单的代码剖析解释:
①应该将相应的文件创建出来
②编写Makefile文件
上图是最开始也是最容易理解的版本。
第二个图和第一个图的不同就在于gcc -c main.c 这个地方的后面,其实这里编译的时候后面可以省略,因为他会自动的生成同名的.o文件
在这个写法下,那么就不会再出现文件的原始名字,而是全部使用变量替换掉了。
注意:命令前必须是一个“TAB键”,否则编译错误为: missing separator. Stop.
这里就需要加入一些Makefile编写的一些知识
自动变量:
1.1.1 依赖关系
main:main.o cal.o 就是依赖关系
如果想生成可执行的main文件,那么就需要相对应的“.o”
事实上这里还是有过程的省略:
main:main.o
main.o:main.s
main.s:main.i
main.i:main.c
这个才是完整的依赖关系表示
1.1.2 依赖方法
gcc -o main main.o cal.o 就是 main:main.o cal.o 的依赖方法
对于依赖方法也可以认为是依赖关系的实现,如果在依赖关系不成立的情况下,那么依赖方法是不执行的。
1.1.3 项目清理
- 工程是需要被清理的。
- 像clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要make执行。即命令——“make
clean”,以此来清除所有的目标文件,以便重编译。- 但是一般我们这种clean的目标文件,我们将它设置为伪目标,用 .PHONY 修饰,伪目标的特性是,总是被执行的。(但是你的make只要生成了可执行程序就不能再生成了)
2. Linux第一个小程序—进度条
2.1 回车和换行概念
’\r’是回车,’\n’是换行,前者使光标到行首,后者使光标下移一格。通常用的Enter是两个加起来。
2.2 行缓冲区概念
什么现象???
//①
#include <stdio.h>
int main()
{
printf("hello Makefile!\n");
sleep(3);
return 0;
}
//②
#include <stdio.h>
int main()
{
printf("hello Makefile!");
sleep(3);
return 0;
}
//③
#include <stdio.h>
int main()
{
printf("hello Makefile!");
fflush(stdout);
sleep(3);
return 0;
}
刷新策略:
①程序来说,会直接显示hello Makefile!这个称之为行刷新,因为有’\n’的标志
②程序来说,会把程序执行完,也就是先等3秒然后输出hello Makefile! 这个叫做程序结束刷新
③强制刷新:C程序在默认的情况下,会打开三个文件(3个设备:键盘、显示器、显示器),FILE* stdin stdout stderr ,标准输入 ,标准输出,标准错误,你的程序都是存放在磁盘上的,首先进来以后都是先放在缓冲区中,但是并没有输出,只有缓冲区刷新了才能看到所要输出的字符串内容。
④当你没有行刷新标志和结束刷新的时候就要使用强制刷新来显示缓冲区的内容
2.3 完整的进度条代码和解析
Makefile编写
难点:
1.define NUM 101 这里是因为你需要在这里面放100个‘#’并且每次以字符串的形式输出,需要‘\0’的标志
2.反斜杠表示后面的字母不再有特殊的含义而是按照字面的意思匹配词中特定的字符。
3.在C语言中[%-100s] 这里的**“-”表示左对齐,如果不加那就默认右对齐**
4.如果[%d%%]如果这里想输出一个%X那么需要加两次%
5.因为在设置旋转光标的时候只有"| / - "所以要lable[i%4]那么你的i只能取到数组的下标为0~3
6.fflush因为这里没有行刷新和程序结束刷新所以需要强制刷新。
7.对于sleep来说里面的单位是s但是,在这里就会显的太慢了,所以这里需要一个单位更小的,需要使用usleep,但是usleep的单位是微妙所以这里我们是想它所间隔的时间为0.01s。
8.最后如果不换行直接在Linux下运行的话,就会出现覆盖的现象,所以换行输出。