一:gcc编译
使用Makfeile之前我们先了解下gcc编译过程中经历的四个步骤:
1:预处理阶段
在这个阶段主要对我们的代码进行一下操作:加载头文件、宏展开、处理注释、处理条件编译、添加文件名和行号。
通过这个阶段生成的是经过预处理的c原始程序(.i文件)。
2:编译
对于经过预处理的c原始程序处理生成汇编语言原始程序(.s文件)。
3:汇编
对于结果编译之后生成的汇编语言原始程序处理生成不可执行的二进制文件(.o)文件。
4:链接
对于不可执行的二进制文件进行库的链接生成可执行的二进制文件。
二:Makefile制作
1:make语法
#Makefile的书写
#目标:依赖
# 命令
main.o:main.c
gcc -c main.o
变量赋值:
1. 简单赋值
最简单明了,只发生在该行
造型: 变量名 := 值
@echo “I LOVE U” //打印,相当于c语言中的printf(“I LOVE U”);
井号# 代表注释 例: #XXXXXXXX
2. 递归赋值
不断递归寻找,知道最后一个值,会影响里面使用到的变量值
造型: 变量名 = 值
3. 条件赋值
先判断该变量是否存在,不存在则赋值,存在则跳过
造型: 变量名 ?= 值
4. 追加赋值
变量在原来的基础上追加值
造型: 变量名 += 值
系统给定变量:
$@ ----- 代表目标
$^ ----- 代表所有的依赖
$< ----- 代表第一个依赖
伪目标:
写入伪目标,无论项目代码有没有改动,都进行编译
造型: .PHONY : XX YY TT XX YY TT这是3个伪目标
make -C XXXX XXXX是一个文件夹(目录)
该指令作用: 执行XXXX目录下的Makefile
export
造型: export XX ----- 将XX变量共享给子文件夹
mkdir -p XX
功能: 如果xx文件夹存在则不创建,如果XX不存在就创建XX文件夹
2:制作Makefile也是在gcc编译的基础上来进行,通过上面我们知道最后的可执行文件是通过.o文件来获取,所以第一步我们考虑的是获取.o文件。
首先用Makefile管理项目的大致模板如下:
bin文件夹用来存放可执行的二进制文件;
fun存放我们的代码;
inc存放我们头文件;
main存放main函数;
obj存放我们通过编译获取的.o文件;
Makefile用来管理项目;
其次在除bin、inc文件的其他文件夹下各创建一个Makefile文件用来管理其中的程序;其中main文件夹下的Makefile如下:
MAIN_OBJ := ../obj/main.o
$(MAIN_OBJ):main.c
gcc -c $^ -o $@
生成main.o文件到…/obj文件夹下。
fun文件夹下的Makfile如下:
FUN_OBJ := ../obj/fun.o
MANU_OBJ := ../obj/manu.o
.PHONY :$(FUN_OBJ) $(MANU_OBJ)
ALL:$(FUN_OBJ) $(MANU_OBJ)
$(MANU_OBJ):manu.c
gcc -c $^ -o $@
$(FUN_OBJ):fun.c
gcc -c $^ -o $@
通过以上就将所需要的.o文件均生成到了obj目录下,之后通过obj下的Makeflie来对其下的所有.o文件进行管理;
APP_BIN := ../bin/app
.PHONY:$(APP_BIN)
$(APP_BIN):fun.o main.o manu.o
gcc $^ -o $@
将所有的.o文件进行链接生成可执行的二进制文件APP。
SUB_DURS := main fun obj
.PHONY:$(SUB_DURS)
all:main fun obj
#通过make -C进入到所有目标文件夹中执行其中的make命令
main fun obj:
make -C $@
在根目录下的Makefile管理整个项目;
到这里整个Makefile的模板就制作完毕了!