视频教程
一个工程中的源文件不计其数,其按类型、功能、模块分别放在若千个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个shell脚本一样,其中也可以执行操作系统的命令。
Makefile带来的好处就是一”自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如: Delphi的make, Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
makefile和Makefile都可以,推荐使用Makefile
。
make工具的安装
sudo apt install make
一条规则:
目标:依赖文件列表
<Tab>命令列表
测试demo,新建test.mk
all: test1 test2
echo " all finished"
test1:
echo " test1 finished"
test2:
echo " test2 finished"
执行
root@sony-HP-Notebook:/usr/local/cpp_demo/makefile# make -f test.mk
echo " test1 finished"
test1 finished
echo " test2 finished"
test2 finished
echo " all finished"
all finished
make是一个命令工具,它解释Makefile 中的指令 (应该说是规则)。
make命令格式
make [ -f file ][ options ][ targets ]
1.[ -f file ]:
-f可以指定以上名字以外的文件作为makefile输入文件
2.[ options ]
3.[ targets ]:
例如:指定执行test1目标
root@sony-HP-Notebook:/usr/local/cpp_demo/makefile# make test1 -f test.mk
echo " test1 finished"
test1 finished
1)、若想生成目标,检查规则中的依赖是否存在,如不存在,则寻找是否有规则用于生成该依赖文件
2)、检查规则中的目标是否需要更新,必须先检查它的所有依赖,依赖中有任何一个被更新,则目标必须更新
总结:
在Makefile中使用变量有点类似于C语言中的宏定义,使用该变量相当于内容替换,使用变量可以使Makefile易于维护,修改内容变得简单变量定义及使用。
1)定义变量方法:
2)引用变量:
3) makefile的变量名:
#变量
OBJS=add.o sub.o test.o
TARGET=test
$(TARGET):$(OBJS)
gcc $(OBJS) -o $(TARGET)
add.o:add.c
gcc -c add.c -o add.o
sub.o:sub.c
gcc -c sub.c -o sub.o
test.o:test.c
gcc -c test.c -o test.o
clean:
rm -rf $(OBJS) $(TARGET)
执行
# 编译
make
# 执行
./test
除了使用用户自定义变量,makefile中也提供了一些变量(变量名大写)供用户直接使用,我们可以直接对其进行赋值。
注意:自动变量只能在规则的命令中使用
示例,新建rule.mk
OBJS=add.o sub.o test.o
TARGET=test
CC=gcc
# $@: 表示目标
# $<: 表示第一个依赖
# $^: 表示所有的依赖
$(TARGET):$(OBJS)
# gcc $(OBJS) -o $(TARGET)
gcc $^ -o $@
echo $@
echo $<
echo $^
add.o:add.c
# gcc -c add.c -o add.o
$(CC) -c $< -o $@
sub.o:sub.c
# gcc -c sub.c -o sub.o
$(CC) -c $< -o $@
test.o:test.c
# gcc -c test.c -o test.o
$(CC) -c $< -o $@
clean:
rm -rf test
rm -rf *.o
运行
# 清理
make clean -f rule.mk
# 编译
make -f rule.mk
# 执行
./test
模式规则示例:
%.o:%.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -0 $@
Makefile第三个版本 model_rule.mk
OBJS=add.o sub.o test.o
TARGET=test
CC=gcc
# $@: 表示目标
# $<: 表示第一个依赖
# $^: 表示所有的依赖
$(TARGET):$(OBJS)
# gcc $(OBJS) -o $(TARGET)
gcc $^ -o $@
echo $@
echo $<
echo $^
# 模式匹配,所有的.o都依赖对应的.c
# 将所有的.c生成对应的.o
%.o:%.c
$(CC) -c $< -o $@
clean:
rm -rf test
rm -rf *.o
makefile中的函数有很多,在这里给大家介绍两个最常用的
# 找到当前目录下所有后缀为.c的文件,赋值给src
src= $(wildcard*.c)
# 把src变量里所有后缀为.c的文件替换成.o
obj= $(patsubst %.c,%.o, $(src))
在makefile中所有的函数都是有返回值的
Makefile第四个版本 fun_rule.mk
SRC=$(wildcard *.c)
OBJS=$(patsubst %.c, %.o, $(SRC))
TARGET=test
CC=gcc
# $@: 表示目标
# $<: 表示第一个依赖
# $^: 表示所有的依赖
$(TARGET):$(OBJS)
# gcc $(OBJS) -o $(TARGET)
gcc $^ -o $@
echo $@
echo $<
echo $^
# 模式匹配,所有的.o都依赖对应的.c
# 将所有的.c生成对应的.o
%.o:%.c
$(CC) -c $< -o $@
clean:
rm -rf $(OBJS) $(TARGET)
运行
# 清理
make clean -f fun_rule.mk
# 编译
make -f fun_rule.mk
# 执行
./test
clean用途: 清除编译生成的中间.o文件和最终目标文件
make clean 如果当前目录下有同名clean文件,则不执行clean对应的命令,解决方案:
伪目标声明:.PHONY:clean
声明目标为伪目标之后makefile将不会该判断目标是否存在或者该目标是否需要更新
clean命令中的特殊符号:
第五个版本phony_rule.mk
SRC=$(wildcard *.c)
OBJS=$(patsubst %.c, %.o, $(SRC))
TARGET=test
CC=gcc
# $@: 表示目标
# $<: 表示第一个依赖
# $^: 表示所有的依赖
$(TARGET):$(OBJS)
# gcc $(OBJS) -o $(TARGET)
gcc $^ -o $@
# 模式匹配,所有的.o都依赖对应的.c
# 将所有的.c生成对应的.o
%.o:%.c
@$(CC) -c $< -o $@
# 声明clean为伪目标,伪目标不去判断目标文件是否存在,或者是否已经更新
# 无条件执行命令
.PHONY:clean
clean:
-rm -rf $(OBJS) $(TARGET)