31. makefile

1. makefile

  • makefile文件是用来管理项目工程文件,通过执行make命令,make就会解析并执行makefile文件
  • Makefile命名:makefile或者Makefile

1.1 makefile基本规则

目标:依赖
	命令

基本规则三要素:

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

例子:

当前目录下有main.c fun1.c fun2.c sum.c

根据这个基本规则编写一个简单的makefile文件,生成可执行文件main

vi makefile

**version1
main: main.c fun1.c fun2.c sum.c
	gcc -o main main.c fun1.c fun2.c sum.c

** 如果此时修改了main.c,比如加上一个空格,使用make之后,其他的c文件也会全部重新编译
						
** 生成目标--检查-->依赖条件:存在(如果目标的时间 > 依赖的时间 不更新 否则说明修改了需要更新)-->通过命令生成目标
						  不存在-->寻找新规则用来生成依赖条件
						  
**version2
main: main.o fun1.o fun2.o sum.o
	gcc -o main main.o fun1.o fun2.o sum.o
	
main.o: main.c
	gcc -c main.c -I./
	
fun1.o: fun1.c
	gcc -c fun1.c
	
fun2.o: fun2.c
	gcc -c fun2.c
	
sum.o: sum.c
	gcc -c sum.o
	
**如果此时修改了main.c 对于目标为fun1.o fun2.o sum.o的编译就不会执行了
**弊端是如果目录中有几十个.c,就很痛苦

1.2 makefile中的变量

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

三种变量:

  • 普通变量

    • 变量定义直接用 =

    • 使用变量值用$(变量名)

      foo = abc //定义变量并赋值
      bar = $(foo)  // 使用变量
      

      定义了两个变量foo bar,其中bar的值是foo变量值的引用

  • 自带变量

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

    CC=gcc #arm-linux-gcc  指定编译器
    CPPFALGS: C预处理器的选线 -I
    CFLAGS: C编译器的选项 -Wall -g -c
    LDFLAGS: 链接器的选项 -L -l
    
  • 自动变量==(只能在规则中的命令使用)==

    • $@:表示规则中的目标

    • $<:表示规则中的第一个条件

      main: main.c fun1.c fun2.c sum.c 这里main.c就是第一个条件

    • $^:表示规则中的所有条件,组成一个列表,以空格隔开,如果者个列表中有重复的项,则消除重复项

例子:

vim makefile

## version3
target = main #给目标起名字
objects = main.o fun1.o fun2.o sum.o
CC = gcc
CPPFALGS= -I./
$(target): $(objects)
	$(CC) -o $@ $^
	
main.o: main.c
	$(CC) - c $< $(CPPFLAGS)
	
fun1.o: fun1.c
	$(CC) -c $<

fun2.o: fun2.c
	$(CC) -c $<

sum.o: sum.c
	$(CC) -c $<
	
## 但是还是要写这么多行
## 可以找到一个共同的规则,给简化
## main.o 依赖 main.c  fun.o: fun.c  sum.o:sum.c
## 即:xxx.o: xxx.c
  • 模式规则:

    规则的目标定义中可以包含%,表示一个或者多个

    在依赖条件中同样可以使用%,取值取决于其目标

    比如:main.o:main.c fun1.o:fun1.c fun2.o:fun2.c

    ## version4
    target = main #给目标起名字
    objects = main.o fun1.o fun2.o sum.o
    CC = gcc
    CPPFALGS= -I./
    $(target): $(objects)
    	$(CC) -o $@ $^
    	
    %.o: %.c
    $(CC) - c $< $(CPPFLAGS)
    ##main.o: main.c
    ##	$(CC) - c $< $(CPPFLAGS)
    	
    ##fun1.o: fun1.c
    ##	$(CC) -c $<
    
    ##fun2.o: fun2.c
    ##	$(CC) -c $<
    
    ##sum.o: sum.c
    ##	$(CC) -c $<
    

1.3 makefile函数

两个常用的:

  1. wildcard–查找指定目录下的指定类型的文件

    src=$(wildcard *.c)// 找到当前目录下所有后缀为.c的文件,赋值给src

  2. patsubst–匹配替换

    obj=$(patsubpt %.c,%.o,$(src))// 把src变量里所有后缀为.c的文件替换成.o

## version5
target = main #给目标起名字
src=$(wildcard *.c)
objects = $(patsubpt %c, %.o, $(src))
CC = gcc
CPPFALGS= -I./
$(target): $(objects)
	$(CC) -o $@ $^

以上版本的缺点是,每次重新编译都需要手工清理中间.o文件和最终目标文件

1.4 makefile的清理操作

用途:清除编译生成的中间.o文件和最终目标文件

make clean:如果当前目录下有同名clean文件,则不执行clean对应的命令,解决方案:

伪目标声明:

.PHONY:clean

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

  • clean命令中的特殊符号:

    • -此条命令出错,make也会继续执行后续的命令。如:-rm main.o

      rm -f:强制执行,比如要删除的文件不存在使用-f不会报错

    • @不显示命令本身,只显示结果。如:@echo clean done

  • 其它

    • make默认执行第一个出现的目标(main),可通过make dest指定要执行的目标(make clean)
    • make -f-f执行一个makefile文件名称,使用make执行指定的makefile:make -f mainmak
## version
target = main #给目标起名字
objects = main.o fun1.o fun2.o sum.o
CC = gcc
CPPFALGS= -I./
$(target): $(objects)
	$(CC) -o $@ $^
	
clean:
#	rm *.o
	rm $(objects) $(target)
  • 这样写的话,使用make clean时,会显示make:'clean' is up to date

    这是因为clean不需要依赖,那clean这个文件就会一直是最新的,不需要进行更新

  • 因此需要将clean当做是个伪目标,不需要让他检查更新

  • 另外,如果加上之后,成功执行了clean,再次执行会显示无法删除xxx.o,没有这个文件或者目录,加上-f就行

## version
target = main #给目标起名字
objects = main.o fun1.o fun2.o sum.o
CC = gcc
CPPFALGS= -I./
$(target): $(objects)
	$(CC) -o $@ $^

## 当做是伪目标
.PHONY:clean
clean:
#	rm *.o
	rm -f $(objects) $(target)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今儿背单词吗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值