makefile的简单编写

什么是Makefile

一个工程中的源文件数不胜数,其按照功能、模块、类型放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件是先编译,哪些文件后编译,哪些文件需要重新编译,甚至进行更多复杂的功能操作,makefile就像一个shell脚本,也可以执行操作系统的命令。makefile是一个文件,make是一个命令。
Makefile带来的好处是自动化编译。一旦写好,只需要一个make命令,整个工程完全自动编译,大大提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的工具。一般来说,大多数的[IDE](https://baike.baidu.com/item/IDE)都有这个命令,比如:Delphi的make,[Visual C++](https://baike.baidu.com/item/Visual%20C%2B%2B)的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。

make主要解决两个问题

1)大量代码关系维护

大项目中源代码比较多,手工维护、编译时间长而且编译命令复杂,难记忆。
将代码维护命令和编译命令写在makefile文件中,再利用make命令工具解析此文件中自动执行相应的命令,可实现代码的合理编译。

2)减少重复编译的时间

我们在改动其中一个文件的时候,可以通过修改时间,判断哪个文件被修改过,然后只针对这个文件进行编译,然后重新链接所有的目标文件,节省编译时间。

Makefile文件的命名规则

makefile和Makefile均可

如何安装make工具

sudo apt install make

make命令格式

make是一个命令工具,它用来解释makefile中的指令(规则)
make命令格式
make -f file options targets
1.-f file
make默认在文件中查找GUNmakefile、Makefile和makefile作为makefile输入文件
-f可以指定以上文件以外的文件作为makefile输入文件

2.options

  • -v: 显示make工具的版本信息
  • -w: 在处理makefile之前和之后显示工作路径
  • -C dir:读取makefile之前改变工作路径至dir目录
  • -n:只打印要执行的命令但不执行
  • -s:执行但不显示执行的命令

3.targets

  • 若使用make命令时没有指定目标,则make工具默认会实现makefile文件内的第一个目标,然后退出。
  • 指定了make工具要实现的目标,目标可以是一个或者多个

Makefile的语法规则

一条规则,两个函数,三个变量

一条规则

目标:依赖文件列表
命令列表

Makefile规则三要素
1)目标:
通常是要产生的文件名字,可以是动作名称,可以是可执行文件或其他obj文件。
2)依赖文件列表:
用来输入从而产生目标的文件
可以有多个依赖文件列表,也可以没有。
3)命令:
make执行的动作,可以含几个命令,也可以没有。
有多个命令时,每个命令占一行
命令列表前面一定时TAB键
举例:

all:test1 test2
	echo "hello all"
test1:
	echo "hello test1"
test2:
	echo "hello test2"

Makefile示例

测试程序 test.c add.c sub.c div.c mul.c
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
xxx.h就是简单的声明函数,这里就提供add.h
在这里插入图片描述

最简单的makefile
test:add.c sub.c div.c mul.c
	gcc add.c sub.c div.c mul.c -o test

缺点:编译速度慢,修改一个文件,全部文件都要重新编译

第二个版本Makefile
test:test.o add.o div.o sub.o mul.o
	gcc test.o add.o div.o sub.o mul.o -o test
test.o:test.c
	gcc -c test.c
#test.c已经存在,可以直接gcc -c test.c编译
add.o:add.c
	gcc -c add.c
div.o:div.c
	gcc -c div.c
sub.o:sub.c
	gcc -c sub.c
mul.o:mul.c
	gcc -c mul.c

Makefile中的变量

Makefile中使用变量有点像C语言中的宏定义,使用该变量相当于内容替换,使用变量可以使Makefile易于维护,修改内容变得简单。

自定义变量

1)定义变量的方法:
变量名=变量值
2)引用变量:
$(变量名)或 ${变量名} 括号不可以省略。
3)makefile的变量名

  • makefile变量名可以用数字开头
  • 变量大小写敏感
  • 变量一般在makefile头部定义
  • 变量几乎可以在makefile中任何地方使用
    举例:
#C语言中变量可以保存一个数,比如double a = 3.1415926,这样每次使用这个数就不用一直写那么多数字,直接用变量就好
OBJS=add.o div.o mul.o sub.o test.o
TARGET=test

$(TARGET):$(OBJS)
	gcc $(OBJS) -o $(TARGET)

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

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

mul.o:mul.c
	gcc -c mul.c

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

test.o:test.c
	gcc -c test.c

clean:
	rm -rf $(OBJS) $(TARGET)

除了使用用户自定义变量,makefile中也提供了一些变量(变量名大写)供用户直接使用,我们可以直接对其进行赋值。

CC = gcc #arm-linux-gcc

CPPFLAGS : C预处理的选项 如:-I

CFLAGS: C编译器的选项 -Wall -g -c

LDFLAGS : 链接器选项 -L -l

自动变量

  • $@:表示规则中的目标(小眼睛)
  • $<:表示规则中的第一个条件
  • $^:表示规则中的所有条件,组成一个列表,以空格隔开,这个列表中有重复的项就消除重复项
    注意:自动变量只能在规则的命令中使用
    自动变量的好处,可以一直复制命令
#变量

OBJS=add.o sub.o mul.o div.o test.o add.o


TARGET=test


CC=gcc

#$@: 表示目标


#$<: 表示第一个依赖


#$^: 表示所有的依赖

$(TARGET):$(OBJS)

    #$(CC) $(OBJS) -o $(TARGET) 

    $(CC) $^ -o $@

    echo $@
    
    echo $<

    echo $^


add.o:add.c

    $(CC) -c $< -o $@ 


sub.o:sub.c


    $(CC) -c $< -o $@ 

mul.o:mul.c

    $(CC) -c $< -o $@ ​

div.o:div.c
    $(CC) -c $< -o $@ 
test.o:test.c
    $(CC) -c $< -o $@

clean:
    rm -rf $(OBJS) $(TARGET)

模式规则

写了那么多自动变量,重复的,是不是可以改进能。
答案是yes。模式规则可以改进.o文件.c文件多的问题
模式规则示例:
%.o:%.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@

Makefile的第三个版本

用了模式匹配后才发现自动变量是真好用

OBJS=test.o add.o sub.o mul.o div.o
TARGET=test

$(TARGET):$(OBJS)
	gcc -c $^ -o $@
#模式匹配所有的.o都依赖对应的.c
#将所有的.c生成对应的.o
%.o:%.c
	gcc -c $< -o $@

Makefile的函数

mafefile的函数有很多,下面介绍两个
1.wildcard -查找指定目录下的指定类型的文件
src = $(wildcard *.c)//找到当前目录下所有后缀为.c的文件,赋值给src
2.patsubst -匹配替换
obj = $(patsubst %.c, %.o, $(src))//将src变量里所有后缀为.c的文件替换成.o
在makefile中所有的函数都是有返回值的
Makefile第四个版本

SRC=$(wildcard *.c)
OBJS=$(patsubst %.c, %.o, $(src))

TARGET=test
$(TARGET):$(OBJS)
	gcc $^ -o $@

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

Makefile的伪目标

clean用途:清除中间生成的.o文件和最终目标文件
make clean如果当前目录下有同名的clean文件,则不会执行clean对应的命令,解决方案:

伪目标声明:.PHONY:clean

声明目标为伪目标后,makefile将不会判断该目标是否存在或者该目标是否需要更新

clean命令中的特殊符号

  • “-“这条命令出错,make也会继续执行后续的命令。如:”-rm main.o”
  • "@"不显示命令本身,只显示结果。如“@echo clean done”

Makefile的最终版本

SRC=$(wildcard *.c)#查找当前目录下所有的.c文件
OBJS=$(patsubst %.c, %.o, $(SRC))
TARGET=test

$(TARGET):$(OBJS)
	gcc -c $^ -o $@

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

.PHONY:clean
clean:
	rm -rf $(OBJS) $(TARGET)

Makefile工作原理

1)想要生成目标,先看依赖的文件是否存在,如果不存在就寻找新规则生成该依赖文件
在这里插入图片描述

2)检查规则中的目标是否需要更新,必须检查它的所有依赖,如果任意一个依赖更新,目标必须更新。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值