make与makefile的基础用法:
目的:gcc -o a.h b.h ……n.h,当多个.c文件进行编译,耗时长,makefile则可以解决这个问题
(1)make是一种文件转换工具,通过某种操作,将依赖文件转换为目标文件。
(2)make命令可以根据makefile脚本中定义的规则,完成从依赖文件到目标文件得转换。
(3)只有当依赖文件比目标文件新时,make才会重新生成目标文件
(4)具体到C程序语言,可以认为可执行程序依赖于目标模块,而目标模块又依赖于源程序和头文件
(5)从源程序和头文件到目标模块,以及从目标模块到可执行程序所需要的操作就是各种GCC命令。
(6)makefile需要描述的就是目标、依赖以及从依赖产生目标所需要执行的各种命令。
(7)makefile基本语法:
目标:依赖
<制表符>命令1
<制表符>命令2
(8)一个makefile可以包含多个目标,通过make命令的参数指定期望实现的目标,缺省实现第一个
(9)命令可以是GCC命令,也可以是普通SHELL命令
(10)目标的依赖和/或命令可以为空
make命令调用makefile文件,makefile中定义一定规则。
举例如下:
在不引入makefile时,运用两步法进行编译
vim helloworld.c文件
gcc -c -o helloworld.o helloworld.c
gcc -o helloworld helloworld.o
引入Makefile:
vim Makefile(部分操作系统不认小写的makefile)
#注释用#,Makefile将来由make命令来解析,根据制定的编译规则对程序进行编译
#制定编译规则的语法
#目标:依赖1 依赖2 ... 依赖N
#(TAB键)编译命令1
#(TAB键)编译命令2
#(TAB键)编译命令N
#制定编译规则1
helloworld:helloworld.o
gcc -o helloworld helloworld.o
#制定编译规则2
helloworld.o:helloworld.c
gcc -c -o helloworld.o helloworld.c
#实验步骤
#make
#ls -l //观察时间戳
#./helloworld
#make //提示up to date,最新的,没有编译
#vim helloworld.c 随意修改
#ls -l //观察时间戳
#make //重新编译了
#./helloworld
在命令行输入make
输入ls -l 查看详情:
此时重新输入make,会提示up to date,最新的,没有编译
在重新修改后ls -l 观察时间戳,make则为重新编译。即helloworld.c时间
当遇到多个文件时如何制定makefile
利用昨天的多个代码:arr.c arr.h cal.c cal.h main.c
#制定编译规则1
main:main.o arr.o cal.o
gcc -o main main.o arr.o cal.o
#制定编译规则2
main.o:main.c
gcc -c -o main.o main.c
arr.o:arr.c
gcc -c -o arr.o arr.c
cal.o:cal.c
gcc -c -o cal.o cal.c
进行make后:
当修改了main函数后:
其他的时间戳要旧,所以无需编译
但是可以发现,此时的makefile文件中给多个文件进行命令编写,相近的编写有很多,非常麻烦,因此使用小技巧:
#制定编译规则1
main:main.o arr.o cal.o
gcc -o main main.o arr.o cal.o
#制定编译规则2
#小技巧:
#%.o:%.c
# gcc -c -o $@ $<
#%.o,$@:目标文件.o
#%.c,$<:源文件.c
#将所有的.c生成对应的.o
%.o:%.c
gcc -c -o $@ $<
在编写结束后,发现如果将来main文件名进行修改,或者编译器不是gcc,每一次改动都需要改动规则文件会非常麻烦,于是引入变量:
#变量,类似C语言的#define常量宏
BIN=main
OBJ=main.o arr.o cal.o
CC=gcc
#制定编译规则1
#访问变量值的语法:$(BIN)
$(BIN):$(OBJ)
$(CC) -o $(BIN) $(OBJ)
#制定编译规则2
%.o:%.c
$(CC) -c -o $@ $<
在编写结束后,又需要使用命令:
rm *.o main来删除上一次运行后的结果来重新执行,这也有一些麻烦,于是在makefile文件中
在makefile文件中加入如下伪目标代码:
20 #伪目标:没有依赖的目标
21 #执行 make clean时才会执行对应的命令
22 clean:
23 rm $(BIN) $(OBJ)
最终,如果不想看到执行命令,则可以在每一条命令语句中加上@进行隐藏。
#变量
BIN=main
OBJ=main.o arr.o cal.o
CC=gcc
#制定编译规则1
$(BIN):$(OBJ)
@echo "开始编译"
@$(CC) -o $(BIN) $(OBJ)
@echo "编译结束"
#制定编译规则2
%.o:%.c
@$(CC) -c -o $@ $<
#伪目标:没有依赖的目标
#执行make clean时才会执行对应的命令
clean:
@rm $(BIN) $(OBJ)
@echo "清理完毕"
则再次输入make时编译命令被隐藏:
如果想添加一些显示信息,则可以用echo显示到屏幕的命令:
其运行结果如下: