编写makefile文件

本文详细介绍了如何编写Makefile文件来自动化管理C程序的编译过程。从基本的规则定义到自动变量的使用,再到模式规则和编译参数的添加,最后展示了如何实现清理编译产物的clean命令。示例中展示了如何根据源文件自动构建目标文件,并在编译时添加额外的编译参数,以及如何处理头文件路径。整个过程旨在提高开发效率,确保文件更新时只重新编译必要的部分。
摘要由CSDN通过智能技术生成

0、源文件

cal.c

#include <stdio.h>
#include <unistd.h>

int add(int, int);
int sub(int, int);
int div(int, int);

int main(){
	int a = 2, b = 2;
	printf("%d + %d = %d\n", a, b, add(a,b));
	printf("%d - %d = %d\n", a, b, sub(a,b));
	printf("%d / %d = %d\n", a, b, div(a,b));
	return 0;
}

add.c

int add(int a, int b){
	return a + b;
}

sub.c

int sub(int a, int b){
	return a - b;
}

div.c

int div(int a, int b){
	return a / b;
}

1、makefile规则

1、若想生成目标,检查规则中的依赖条件是否存在
   如不存在,则寻找是否有规则用来生成该依赖文件
2、检查规则中的目标是否需要更新,必须先检查它的所有依赖
   依赖中有任一个被更新,则目标必须被更新
目标:依赖
(tab)命令

目标: 要生成的目标文件
依赖: 目标文件由哪些文件生成
命令: 通过执行该命令由依赖文件生成目标文件

1、目标的时间必须晚于依赖条件的时间,否则,更新目录
2、依赖条件如果不存在,寻找新的规则去产生依赖
3、makefile默认把遇到的第一组规则中的目标作为终极目标,因此要把生成终极目标的规则放在第一个,或则使用ALL指定终极目标
ALL: 指定make的终极目标

例1

makefile(哪个变化了就重新编译哪个,避免一个变化编译全部)

cal:cal.o add.o sub.o div.o
	gcc cal.o add.o sub.o div.o -o cal
	
cal.o:cal.c
	gcc -c cal.c -o cal.o

add.o:add.c
	gcc -c add.c -o add.o

sub.o:sub.c
	gcc -c sub.c -o sub.o

div.o:div.c
	gcc -c div.c -o div.o

2、两个函数

src = $(wildcard ./*.c)
找到当前目录下所有后缀为.c的文件,把文件名作为一个列表赋值给src,src = add.c sub.c div.c
obj = $(patsubst %.c, %.o, $(src))
把参数3中,包含参数1的部分,替换为参数2,obj = add.o sub.o div.o

clean命令: 删除当前目录下的.o文件和cal文件
clean:
	-rm -rf $(obj) cal
"-" 表示出错依然执行,当某个文件不存在时,其他文件依然可以删除

例2

makefile

src = $(wildcard *.c)              # add.c sub.c div.c cal.c
obj = $(patsubst %.c, %.o, $(src)) # add.o sub.o div.o cal.o

ALL:cal

cal:$(obj)
	gcc $(obj) -o cal

add.o:add.c
	gcc -c add.c -o add.o

sub.o:sub.c
	gcc -c sub.c -o sub.o

div.o:div.c
	gcc -c div.c -o div.o

cal.o:cal.c
	gcc -c cal.c -o cal.o

clean:
	-rm -rf $(obj) cal

3、三个自动变量

$@ : 在一组规则的命令中,表示规则中的目标
$^ : 在一组规则中的命令中,表示所有依赖条件
$< : 在一组规则的命令中,表示第一个依赖条件。如果将该变量应用在模式规则中,它可将依赖条件列表中的依赖依次取出,套用模式规则

自动变量只能出现在命令中,目标和依赖中不能出现自动变量

例3

makefile

src = $(wildcard *.c)              # add.c sub.c div.c cal.c
obj = $(patsubst %.c, %.o, $(src)) # add.o sub.o div.o cal.o

ALL:cal

cal:$(obj)
	gcc $^ -o $@

add.o:add.c
	gcc -c $< -o $@

sub.o:sub.c
	gcc -c $< -o $@

div.o:div.c
	gcc -c $< -o $@

cal.o:cal.c
	gcc -c $< -o $@

clean:
	-rm -rf $(obj) cal

4、模式规则

%.o:%.c
	gcc -c $< -o $@

静态模式规则,指定模式规则给谁用
$(obj):%.o:%.c
	gcc -c $< -o $@

例4

src = $(wildcard *.c)              # add.c sub.c div.c cal.c
obj = $(patsubst %.c, %.o, $(src)) # add.o sub.o div.o cal.o

ALL:cal

cal:$(obj)
	gcc $^ -o $@

%.o:%.c
	gcc -c $< -o $@

clean:
	-rm -rf $(obj) cal
此时增加一个mul.c模块不需要更改makefile文件

例5

使用静态模式规则指定某个模式规则应用于obj

makefile

src = $(wildcard *.c)              # add.c sub.c div.c cal.c
obj = $(patsubst %.c, %.o, $(src)) # add.o sub.o div.o cal.o

ALL:cal

cal:$(obj)
	gcc $^ -o $@

$(obj):%.o:%.c
	gcc -c $< -o $@

clean:
	-rm -rf $(obj) cal

5、clean命令

当前文件夹下有clean文件时,会影响makefile中的clean命令执行
解决方法,增加一行: .PHONY:clean ALL

例6

src = $(wildcard *.c)              # add.c sub.c div.c cal.c
obj = $(patsubst %.c, %.o, $(src)) # add.o sub.o div.o cal.o

ALL:cal

cal:$(obj)
	gcc $^ -o $@

$(obj):%.o:%.c
	gcc -c $< -o $@

clean:
	-rm -rf $(obj) cal

.PHONY:clean ALL

6、增加编译参数

例7

src = $(wildcard *.c)              # add.c sub.c div.c cal.c
obj = $(patsubst %.c, %.o, $(src)) # add.o sub.o div.o cal.o

myArgs = -Wall -g

ALL:cal

cal:$(obj)
	gcc $^ -o $@ $(myArgs)

$(obj):%.o:%.c
	gcc -c $< -o $@ $(myArgs)

clean:
	-rm -rf $(obj) cal

.PHONY:clean ALL

7、练习

文件结构
./inc 存放.h文件
./obj 存放.o文件
./src 存放.c文件

makefile

src = $(wildcard ./src/*.c)                     # src = ./src/add.c ./src/sub.c ./src/div.c ./src/cal.c
obj = $(patsubst ./src/%.c, ./obj/%.o, $(src))  # obj = ./obj/add.o ./obj/sub.o ./obj/div.o ./obj/cal.o

myArgs = -Wall -g
inc_path = ./inc

ALL:cal

cal:$(obj)
	gcc $^ -o $@ $(myArgs)

$(obj):./obj/%.o:./src/%.c
	gcc -c %< -o $@ $(myArgs) -I $(inc_path)

clean:
	-rm -rf $(obj) cal

.PHONY:clean ALL
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值