什么是makefile?
makefile文件中定义了一系列的规则来指定, 哪些文件需要先编译, 哪些文件需要后编译, 哪些文件需要重新编译, 甚至于进行更复杂的功能操作, 因为makefile就像一个Shell脚本一样, 其中也可以执行操作系统的命令. makefile带来的好处就是——“自动化编译”, 一旦写好, 只需要一个make命令, 整个工程完全自动编译, 极大的提高了软件开发的效率.
make是一个命令工具, 是一个解释makefile中指令的命令工具, 一般来说, 大多数的IDE都有这个命令, 比如:Visual C++的nmake, Linux下GNU的make. 可见, makefile都成为了一种在工程方面的编译方法.
makefile文件中会使用gcc编译器对源代码进行编译, 最终生成可执行文件或者是库文件.
如何写makefile?
写makefile要遵守他的规则,makefile由一组规则组成,规则如下:
目标: 依赖
(tab)命令
makefile基本规则三要素:
- 目标: 要生成的目标文件
- 依赖: 目标文件由哪些文件生成
- 命令: 通过执行该命令由依赖文件生成目标
makefile中的变量
在makefile中使用变量有点类似于C语言中的宏定义, 使用该变量相当于内容替换, 使用变量可以使makefile易于维护, 修改起来变得简单。
makefile常见有两种类型的变量:普通变量、自带变量
普通变量:
变量定义直接用 =
使用变量值用 $(变量名)
//举例:变量的定义和使用
test= aaa // 定义变量test并赋值为aaa
test1 = $(test) // 使用变量, $(变量名)
//其中test1的值是test变量值的引用
除了使用用户自定义变量, makefile中也提供了一些变量(变量名大写)供用户直接使用, 我们可以直接对其进行赋值
CC = gcc #arm-linux-gcc
CPPFLAGS : C预处理的选项 -I
CFLAGS : C编译器的选项 -Wall -g -c
LDFLAGS : 链接器选项 -L -l
自带变量:
$@: 表示规则中的目标
$<: 表示规则中的第一个条件
$^: 表示规则中的所有条件, 组成一个列表, 以空格隔开, 如果这个列表中有重复的项则消除重复项。
特别注意:自动变量只能在规则的命令中使用.
模式规则:至少在规则的目标定义中要包含’%’, ‘%’表示一个或多个, 在依赖条件中同样可以使用’%’, 依赖条件中的’%’的取值取决于其目标。(后边会举例子)
makefile函数
makefile中的函数有很多, 在这里介绍两个最常用的:
1. wildcard – 查找指定目录下的指定类型的文件
src=$(wildcard *.c) //找到当前目录下所有后缀为.c的文件,赋值给src
2. patsubst – 匹配替换
obj=$(patsubst %.c,%.o, $(src)) //把src变量里所有后缀为.c的文件替换成.o
makefile的清理操作
用途: 清除编译生成的中间.o文件和最终目标文件
make clean 如果当前目录下有同名clean文件,则不执行clean对应的命令, 解决方案:
伪目标声明:
.PHONY:clean
声明目标为伪目标之后, makefile将不会检查该目标是否存在或者该目标是否需要更新
clean命令中的特殊符号:
“-”此条命令出错,make也会继续执行后续的命令。如:“-rm main.o”
rm -f: 强制执行, 比如若要删除的文件不存在使用-f不会报错
“@”不显示命令本身, 只显示结果。如:“@echo clean done”
其它
– make 默认执行第一个出现的目标, 可通过make dest指定要执行的目标
– make -f : -f执行一个makefile文件名称, 使用make执行指定的makefile: make -f mainmak
举例:在linux下创建如下几个文件,并放到同一目录下,进行make和make clean操作。
//fun1.c代码如下:
#include <stdio.h>
void fun1()
{
printf("this is fun1\n");
}
//fun2.c代码如下:
#include <stdio.h>
void fun2()
{
printf("this is fun2\n");
}
//sum.c代码如下:
#include <stdio.h>
int sum(int len)
{
int i = 0;
int sum = 0;
for(i=0; i<len; i++)
{
sum += i;
}
return sum;
}
//head.h
void fun1();
void fun2();
int sum(int len);
//main.c代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "head.h"
int main(int argc, char *argv[])
{
printf("this is main!\n");
int i = 0;
for(i=0; i<argc; i++)
{
printf("[%d]:[%s]\n", i, argv[i]);
}
fun1();
fun2();
printf("sum(10)==[%d]\n", sum(10));
return 0;
}
makefile里边的内容:
src=$(wildcard ./*.c)
object=$(patsubst %.c, %.o, $(src))
target=main
CC=gcc
CPPFLAGS=-I./
$(target):$(object)
$(CC) -o $@ $^
%.o:%.c
$(CC) -o $@ -c $< $(CPPFLAGS)
.PHONY:clean
clean:
-rm -f $(target) $(object)
结果如下:
编写makefile要掌握其套路,常用的方法和操作在上边已有呈现,下边是本次makefile文件编写的注释,帮助我们理解。
# 查找当前目录下所有的 .c 源文件
src=$(wildcard ./*.c)
# 将 src 变量中所有后缀为 .c 的文件替换为对应的 .o 文件
object=$(patsubst %.c, %.o, $(src))
# 定义目标文件名为 main,target 为普通变量
target=main
# 指定编译器为 gcc
CC=gcc
# 编译时使用的预处理器选项,包含当前目录
CPPFLAGS=-I./
# 定义 main 目标及其依赖对象
$(target): $(object)
$(CC) -o $@ $^ # 使用 gcc 链接生成最终可执行文件
# 定义规则,将 .c 文件编译成 .o 文件
%.o: %.c
$(CC) -o $@ -c $< $(CPPFLAGS) # 编译源文件,生成目标文件
# 声明 clean 为伪目标,以便不受文件名影响而被执行
.PHONY: clean
# 定义清理操作,删除生成的目标和对象文件
clean:
-rm -f $(target) $(object) # 移除生成的可执行文件和对象文件,-f 表示强制删除,不提示错误信息
标签:文件,%.,变量,make,makefile,如何,clean,编写
From: https://blog.csdn.net/qq_57259389/article/details/143354642