Makefile语法+简单应用

make工具

make工具:找出修改过的文件,根据依赖关系,找出受影响的相关文件,然后单独编译这些文件
Makefile文件:记录依赖关系和编译规则
Makefile三要素:目标、依赖、命令
目标:依赖文件或者其他文件
< tab > 命令1
< tab > 命令2
< tab > 命令3

在这里插入图片描述
使用make命令之后,到当前目录寻找Makefile文件,然后找到第一个要执行的目标,由于targeta依赖于targetb和targetc,所以先去执行b、c目标对应的命令,等到targeta依赖目标命令执行完之后才能执行targeta
make + 目标:直接执行某一个目标的命令
make targetb或者make targetc

伪目标

.PHONY:指定伪目标
如果在我当前路径下有了targetc文件,如果这个文件没有改动过,执行make targetc就不会更新,不会去执行Makefile里的命令
在这里插入图片描述
若想要去执行targetc目标,需要将targetc设置成伪目标
在Makefile开头加上.PHONY:targetc
在这里插入图片描述

Makefile 变量、模式匹配

变量

=:延时赋值
#当变量被调用时才会被赋值

在这里插入图片描述
在这里插入图片描述

:= #立即赋值

在这里插入图片描述
在这里插入图片描述

?= #空赋值
#当变量为空的时候赋值才有效

在这里插入图片描述
在这里插入图片描述

+= #追加赋值
#真追加,不是求和,字符串追加

截图错了,不是{ }, 是()
在这里插入图片描述
在这里插入图片描述

自动化变量

$<	#Makefile第一个依赖文件,

在这里插入图片描述
在这里插入图片描述

$^	#Makefile全部的依赖文件

在这里插入图片描述
在这里插入图片描述

$@	#目标文件

在这里插入图片描述
在这里插入图片描述

模式匹配

%:匹配任意多个非空字符,此时的文件名叫Makefile_1
在这里插入图片描述
运行命令:如图所示
在这里插入图片描述
这有个知识点:make后直接加要执行的目标文件的前提是,必须是Makefile文件(默认为Makefile),放把文件名改了之后,就要先加上Makefile文件在写要执行的目标文件,通配符做目标,结果打印目标,传什么打什么。

项目编译方法

将所有的.c文件写好 -o指定编译后可执行文件的名称
在这里插入图片描述

引入Makefile对工程管理

首先目标文件mp3目标文件就是mp3
mp3这个文件依赖于main.c和MP3.c 文件
根据Makefile三要素 :目标依赖和命令
最后写命令:生成MP3文件的命令
在这里插入图片描述
但是这种写法让目标文件依赖于.c 文件,每次所有的.c文件都会重新编译,应该让他们依赖于一个重定向文件.o文件,再次编译生成5个文件,main.c mp3.c main.o mp3.o mp3,MP3不直接依赖于main.c和MP3.c,从一个整体拆分成多个部分。
当更改main.c时,只需要重现编译main.c文件即可,MP3.c则不受影响,优化了编译的时间
在这里插入图片描述
在这里插入图片描述

优化工程Makefile文件

在这里插入图片描述
另外还可以用通配符进一步优化,提高可移植性
在这里插入图片描述
或者
在这里插入图片描述

Makefile条件分支

ifeq(var1, var2)	#如果1 == 2 就去执行它下边的语句
……
else
……
endif

还有ifneq(var1, var2), 和上边用法相反
以上面的Makefile举例:

ARCH ?= x86
ifeq ($(ARCH),x86) #注意看!!!ifeq后边有空格,没有不对
    cc=gcc
else
    cc=arm-linux-gnueabihf-gcc
endif

TARGET=mp3
OBJS=main.o mp3.o
$(TARGET):$(OBJS)
   $(cc) $^ -o $@
#main.o:
#   $(cc) -c main.c -o main.o
#mp3.o:
#   $(cc) -c mp3.c -o mp3.o
%.o:%.c
#   $(cc) -c %.c -o %.o
   $(cc) -c $< -o $@
.PHONY:clean
clean:
   rm mp3 *.o *.o

在使用make工具时,直接输入make则,空赋值语句成立,使用GCC编译工具
如果写成 make ARCH=123。此时else成立。使用ARM-GCC工具链

常用函数

  • patsubst
  • notdir
  • wildcard
  • foreach

使用Makefile_function验证举例:

  • patsubst
$(patsubst 模式1, 模式2, 文本) ——模式替换函数
#举例:
$(patsubst %.c, %.o, x.c.c bar.c) 
#最后的文本部分是两个.c结尾的文件名,当和模式1匹配的时候 
#发现模式1也是.c结尾的文件,这两个单词都是能匹配这个模式的,当匹配上之后,这两个单词的模式就会被替换成新的模式——模式2
#最后就变成了x.c.o bar.o
.PHONY:all

all:
    echo "$(patsubst %.c, %.o, x.c.c bar.c)"

在这里插入图片描述

  • notdir
$(notdir src/foot.c abc.c) ——去掉目录,只保留文件名
.PHONY:all

all:
    echo "$(notdir src/foot.c abc.c)"                                    

在这里插入图片描述

  • wildcard
$(wildcard *.c) ——在当前目录下找到所有.c问后缀的文件名
.PHONY:all

all:
    echo "$(wildcard *.c)"

在这里插入图片描述

  • foreach
dirs := a b c d 
$( foreach var, $(dirs), $(wildcard $(var)/*) ) ——遍历函数
#首先先看中间$(dir),每次取值赋给var
#var参与第三个表达式的运算
#总体是说首先取到a,var = a, 然后列出a目录下所有的文件
#然后是取到b……
.PHONY:all
dirs := a b c
all:
    echo "$(foreach var, $(dirs), $(wildcard $(var)    /*))"         

在这里插入图片描述

完善之前的Makefile项目

将每个模块都放在自己的文件夹里,编译生成的文件放在一起

ARCH ?= x86
ifeq ($(ARCH),x86)
    cc=gcc
else
    cc=arm-linux-gnueabihf-gcc
endif

TARGET=mp3

#定义一个生成目录,用来存放生成文件的
BUILD_DIR=build

#源目录存放每个子模块文件夹的
SRC_DIR=moudle1 moudle2

#存放c文件的,得到c文件的所有路径
SOURCE=$(foreach var, $(SRC_DIR), $(wildcard $(var)/*.c))

#首先去掉了路径,然后模式匹配,所有的.c换成.o中间文件
OBJS=$(patsubst %.c, $(BUILD_DIR)/%.o, $(notdir $(SOURCE)))

#指定源文件的路径
VPATH=$(SRC_DIR)#在当前目录找不到文件的基础上,去指定目录去找

#mp3生成文件存放到build,包括最后所有的中间文件也要放到build里面
$(BUILD_DIR)/$(TARGET):$(OBJS)
    $(cc) $^ -o $@
$(BUILD_DIR)/%.o:%.c | creat_build
    $(cc) -c $< -o $@
.PHONY:clean creat_build
clean:
    -rm -r $(BUILD_DIR)
creat_build:
    mkdir -p $(BUILD_DIR)

添加头文件

首先Linux下的编译器会自动检测依赖文件的改动,如果变化,执行make命令,会重新去编译对应的文件,对于.h文件,对于调用它的c文件同样重要,它的更改也需要去做重新编译,所以在依赖.c文件的基础上,也要依赖.h文件,做如下更改:新建include文件夹,用来存放.h文件
在这里插入图片描述

ARCH ?= x86 

ifeq ($(ARCH),x86)
    cc=gcc

else
    cc=arm-linux-gnueabihf-gcc
endif

TARGET=mp3
#定义一个生成目录,用来存放生成文件的
BUILD_DIR=build

#定义头文件路径
INC_DIR = include

#指定头文件路径 -I选项,可以使用模式匹配替换掉
CFLAGS = $(patsubst %, -I %, $(INC_DIR))
#遍历获取所有的.h文件
INCLUDES = $(foreach var, $(INC_DIR), $(wildcard $(var)/*.h))

#源目录存放每个子模块文件夹的
SRC_DIR=moudle1 moudle2

#存放c文件的,得到c文件的所有路径
SOURCE=$(foreach var, $(SRC_DIR), $(wildcard $(var)/*.c))

#首先去掉了路径,然后模式匹配,所有的.c换成.o中间文件
OBJS=$(patsubst %.c, $(BUILD_DIR)/%.o, $(notdir $(SOURCE)))

#指定源文件的路径
VPATH=$(SRC_DIR)#在当前目录找不到文件的基础上,去指定目录去找

#mp3生成文件存放到build,包括最后所有的中间文件也要放到build里面
$(BUILD_DIR)/$(TARGET):$(OBJS)
    $(cc) $^ -o $@

#不仅依赖.c文件还要依赖.h 文件,有变化就会重新编译
$(BUILD_DIR)/%.o:%.c $(INCLUDES) | creat_build
    $(cc) -c $< -o $@ $(CFLAGS)
.PHONY:clean creat_build
clean:
    -rm -r $(BUILD_DIR)
creat_build:
    mkdir -p $(BUILD_DIR)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值