makefile简介
makefile 是一种类似shell的脚本文件,需要make工具进行解释 makefile 内的语句,然后执行内部语句。Makefile的作用是去管理工程项目,比如一个项目有很多c文件,需要利用Makefile去统一进行编译或者其他操作。
makefile 命名为 makefile 或者 Makefile,如果取名为其他,那么执行时需要使用:
make -f 自定义makefile文件名字
1. makefile 基本规则
makefile由一组规则组成,每条规则的格式是:
目标: 依赖
(tab)命令
其中格式内容的含义是:
目标:想要生成的目标文件
依赖:生成目标文件所需要的文件
命令:通过执行该命令,将依赖文件生成目标文件
2. makefile 中的变量
2.1 自定义变量
直接使用 = 赋值变量,使用 &(变量名) 来获取变量
name=lisi
person=$(name)
2.2 自带变量
makefile 自己默认的一些变量,用户直接赋值。
#CPP编译器名称
CPP=g++
#C编译器名称
CC=gcc
#CPP预处理选项选项 -I 大哎(头文件路径)
CPPFLAGS=-I
#CPP编译器选项
CXXFLAGS=
#C编译器选项 -Wall -g -c
CPPFLAGS=
#链接器选项 -l 小艾尔(链接库名);-L 大艾尔(链接库所在文件夹)
LDFLAGS=
2.3 自动变量
makefile 里面一些特定符号代表的特殊含义。
$@ :表示规则中的目标
$< :表示规则中的第一个条件
$^ :表示规则中的所有条件,如果有重复项会消除重复项。
模式规则
在makefile中 ,% 代表 一个或多个
3. makefile 函数
#两个常用函数
#1. wildcard 查找指定目录下的指定类型的文件
#查找当前文件夹下所有 .c 文件,赋值给src
#假如当前文件夹下有 fun1.c fun2.c,那么 src=fun1.c fun2.c
src=$(wildcard *.c)
#2. patsubst 匹配替换,将某个字符串中的某些字符替换为另一个字符
#下面就是将 src 中的 .c 文件替换为 .o 文件,并赋值给 obj
#假如 src=fun1.c fun2.c,那么 obj=fun1.o fun2.o
obj=$(patsubst %.c,%.o,$(src))
4. 伪目标
伪目标的作用是为了让 makefile 不去检查当前目标是否为最新,不管是不是最新都执行这个目标的命令。
#格式
# 伪目标
.PHONY:clean
clean:
rm -rf $(target) $(obj)
需要伪目标的原因就是,make 在解析 makefile 时,它首先去执行第一条规则,这条规则称为终极规则。假如这条规则里面的 依赖有更新,那么就会去找依赖对应的规则去执行,然后再执行最终规则。假如依赖都是最新,那么不会执行最终规则。可以看到如下提示:
#执行
make
#输出
make: 'xxx' is up to date.
# 表示当前最终规则是最新的,不需要执行最终规则
####假如如果当前目录下有同名clean文件####
#一定要添加 .PHONY 表示 clean 目标是一个伪目标,表示不需要检查文件是否存在或者已更新,会直接去执行这个伪目标的命令
#如果不添加,由于clean 这个目标的规则没有依赖,所以认为它的依赖是最新的,然后检查是否存在clean文件,发现确实存在一个没有更新的名为 clean 的文件,最终导致clean不会执行.
#例如直接写下面这样,不添加 .PHONY , 并且存在一个名为 clean 的文件:
clean:
rm -rf $(target) $(obj)
#执行
make clean
#输出以下内容,无法执行目标命令。
make: 'clean' is up to date.
基础综合案例
用到四个基础文件 file1.c、file2.c 、head.h、hello.c,一个 makefile 文件
其中文件file1.c 如下:
#include"head.h"
int sum(int a, int b)
{
return a+b;
}
其中文件file2.c 如下:
#include"head.h"
int mul(int a,int b)
{
return a*b;
}
其中文件head.h如下:
#include<stdio.h>
int sum(int a,int b);
int mul(int a,int b);
其中调用文件 hello.c 如下:
#include"head.h"
int main()
{
printf("1+2=%d\n",sum(1,2));
printf("2*2=%d\n",mul(2,2));
return 0;
}
makefile文件:
src=$(wildcard ./*.c)
obj=$(patsubst %.c,%.o,$(src))
target=hello
CC=gcc
CPPFLAGS=-I ./
# 最终目标
$(target):$(obj)
$(CC) -o $@ $^
%.o:%.c
$(CC) -o $@ -c $< $(CPPFLAGS)
# 伪目标
.PHONY:clean
clean:
rm -rf $(target) $(obj)
执行
#执行,它会自动去执行终极目标的命令 $(CC) -o $@ $^
make
#输出以下表示成功
gcc -o file2.o -c file2.c -I ./
gcc -o hello.o -c hello.c -I ./
gcc -o file1.o -c file1.c -I ./
gcc -o hello file2.o hello.o file1.o
#执行可执行文件
./hello
#输出以下,成功
1+2=3
2*2=4
#指定执行清除指令
make clean
#输出以下表示成功
rm -rf hello ./file2.o ./hello.o ./file1.o