一、编译工具
在安装虚拟机时一般会包含一个gcc编译工具。
1、编译文件
gcc [文件名]即可
这样会在目录下生成一个.out可执行文件,运行该.c文件使用的指令时./c。如果想指定生的.c文件名,使用gcc [xxx.c] -o [自定义文件名即可]
Main.c的源码为:
常用参数:
2、关于gcc
gcc编译的流程为:预处理、汇编、编译和链接。
1、 预处理:
就是对程序中的宏定义等相关内容先进行前期的处理,诸如包含的.h文件,一般.h文件中都会有#ifndef、#define、#endif等操作预处理函数,对该部分函数进行预处理。
2、 汇编
汇编就是将.c文件转换为汇编文件。
3、 编译
将.c文件转换成的汇编文件转换成.o(object)的目标文件。
4、 链接
编译生成的.o文件并不能直接执行,而是需要最后的链接,如果工程中含有多个.c文件,最终会生成很多的.o文件,这些.o文件链接在一起最终形成一个完整的可执行文件。
3、makefile篇
makefile是一个描述哪些文件需要编译,哪些文件需要重新编译的文件。类似于一个脚本,可以在Makefile文件中执行系统命令。使用的时候仅需一个make指令即可完成整个工程的自动编译。
在没有makefile时,比如一个计算器程序,main.c中使用了calcu.c、input.c中的函数,若要对程序进行编译,需要使用gcc main.ccalcu.c input.c -o main(输出的可执行文件名)
在程序只有几个.c文件时,gcc一个个编译还可以,当工程较大,几十个几千个.c文件时,很麻烦。或者是其中某一个.c文件修改,重新开始编译,就很麻烦有木有啊有木有~
最好的额解决方式就是哪个文件修改了编译哪个文件即可,其他没有编译的文件就不需要再次重新编译。根据gcc的译码器流程:预处理、汇编、编译、链接。
我们可以在这个方面做做手脚,我们运行gcc时,只运行到编译这一步,先不链接:
警报的意思是我没有写形参,emmm声明中形参他又不用,我就没写,忘了从哪儿看的了,反正是能行。
在gcc编译时使用-c参数只生成.o文件,只运行到编译并不链接。此外,-c放在gcc的后面和.c函数的后面都行:
但是最后生成可执行文件时候-o必须放在.o文件的后面
可是,.o文件一多,记不清那个文件修改了,就很麻烦,所以makefile专门用来解决该问题。
4、makefile编译脚本
1、脚本创建
在main.c的目录中创建Makefile文件,首字母M一定要大写!,之后在Makefile文件中输入脚本内容,每一行首需要空出来的地方一定要使用TAB键!不能使用空格键!语法要求!
输入的代码含义是:
最终生成的可执行文件为main,这个名字可自行更改,生成该可执行文件需要三个.o文件,main.o、input.o、calcu.o。完成该语句的执行指令为gcc -o main ~~~~~~~~
生成main.o需要使用main.c,生成main.o的语句为~~~~~下同。
2、脚本使用—make
创建好Makefile文件并编辑完毕后,使用make指令即可生成对应的.o文件及可执行文件。
5、Makefile语法
1. Makefile语法规则
Makefile规则
目标文件:依赖文件集合
命令
比如:
main : main.oinput.o calcu.o
gcc -o main main.o input.o calcu.o
上述指令中,main是目标文件,其依赖文件是main.o、input.o、calcu.o。如果要更新目标文件main,就必须先更新其依赖文件(充分性),如果依赖文件中有更新,目标文件也必须更新(必要性),“更新”就是执行一遍命令列表。
命令列表中每条命令必须以TAB键开始,不可使用空格代替。
make会为Makefile中的每个以TAB开始的命令创建一个shell进程去执行
clean作为目标,没有目标文件,执行clean的功能直接使用make clean,执行以后就会删除当前目录下所有的.o文件以及可执行文件main。clean的功能就是完成工程的清理。
2、Make的执行过程
1)、在当前目录下查找以Makefile命名的文件。
2)、找到Makefile文件以后按照Makefile中定义的规则去编译生成最终的目标文件。
3)、如果目标文件不存在或者目标所依赖的文件比目标文件新的话就会执行后面的命令来更新目标。
3、Makefile变量
Makefile支持变量,Makefile支持的变量都是字符串,变量的定义与引用:
objects = main.o input.o calcu.o //objects为一个字符串,可任意起名
main : $(objects)
gcc -o main$(objects)
4、赋值符号— = 、:= 、?=
4.1、=赋值
使用=在给变量赋值时,不一定使用已经定义好的值,也可以使用后面定义的值,变量的真实值为其所引用的变量的最后一次有效值。
使用指令vi Makefile进入Makefile界面,按下a进入编辑模式,添加一下代码后wq(保存并退出)。此外,在Make执行Makefile文件过程中会自动输出命令的执行过程,比如之前的make clean就会在执行时显示执行语句,要想不显示执行过程的话可以在执行语句前加上@。由于要输出字符串,所以需要在执行语句前加上echo(同c中的printf,c 中的out<<).
在中断运行make print指令可以看到:
4.2、:=赋值
不会使用后面定义的变量,只能使用前面已经定义好的。
4.3、?=赋值
“?=”与Verilog代码中assign类似,类似于C中的NULL,当变量为NULL时候进行=后面的赋值,否则不进行赋值,即维持原值。
4.4、变量追加 =
与Qt中.pro文件中添加属性类似,C知识点。
6、Makefile模式规则
在有多个.c文件需要生成.o文件时,可以通过模式规则将所有的.c文件变为对应的.o文件。
模式规则中,至少在规则的目标定义中包含“%”,否则就是一般规则,目标中的“%”表示对文件名的匹配,“%”表示任意长度的非空字符串,比如“%.c”就是代表所有以.c结尾的文件。
自动化变量将模式中所定义的一系列的文件自动的逐个取出,直到所有的符合模式的文件都取完,自动化变量只应该出现在规则的命令中。
最终makefile变为:
7、Makefile伪目标
回想之前的Makefile规则格式: 目标:依赖文件。一般的文件名都是要生成的伪文件,而伪目标不代表真正的目标名,在执行make命令时通过指定这个伪目标来执行器所在规则所定义的命令。伪目标的主要作用是避免Makefile中定义的只执行命令的目标和工作目录下的实际文件出现名字冲突。
在工作目标创建一个与执行指令同名的文件时,执行指令并不会执行,因为规则没有依赖文件,所以目标认为是最新的。也没搞懂什么意思,反正我试了试,的确在同一目录下创建一个与指令同名的文件,Makefile中的指令执行不了。
在Makefile文件中,将clean声明为伪目标,就是在clean的上一行添加声明:
.PHONY:clean
8、Makefile条件判断
Makefile也支持条件判断,条件关键字为:ifeq、ifneq、ifdef、ifndef。
8.1 ifeq、ifneq用法
8.2 ifdef、ifndef用法
ifndef <变量名>
8.3 Makefile函数使用
Makefile支持函数,不支持自定义函数。函数用法格式:
(函数名参数集合)或者 {函数名参数集合}
函数的调用使用“$”来表示,参数集合是函数的多个参数,参数之间使用逗号“,”隔开,函数名和参数集合之间以空格隔开。