MakeFile

Makefile的作用

可以节省每个C文件都包含头文件的麻烦,还可以更改makefile包含的文件,来改变编译的选项

常用符号

$@ – 目标文件
$^ – 所有的依赖文件
$< – 第一个依赖文件。
#为注释
%.o (模式规则)
%.c 以上两个命令将.c文件转换为同名的.o 文件
shell命令,用来找到所有的.c和.h文件
deps = $(shell find ./ -name “.h")
src = $(shell find ./ -name "
.c”)
https://blog.csdn.net/qq_31811537/article/details/82892128

在目录中删除文件

clean :
rm edit $(objects)

实际应用中,防止因为存在名为’clean’的文件而混乱,所以使用.PHONYz作为伪目标,
这样输入命令make clean时,会执行clean描述的指令,而不是名字叫clean的文件
.PHONY : clean
clean :
-rm edit $(objects)

makefile文件的命名

默认使用:GNUmakefile, makefile, Makefile
或者使用非标准的文件名,使用 -f 或 --file 指定makefile文件,比如使用 -f name 或者 --file = name告诉make读name这个文件作为makefile文件。
如果-f 或 --flie的参数不止一个,所有的makefile文件会按具体的顺序作用

-c指令

对C文件进行编译,产生.o文件
.o文件是 relocatable 文件,是不可执行文件
例,

gcc -c main.c -o main

-o指令

对 .o文件进行链接,生成可执行文件,不需要按照依赖顺序

gcc -o main main.o

file指令

用来查看文件格式

file main

ar rc指令

libadd_minus.a add_minus.o

将会生成libadd_minus.a 静态库文件
.a静态库文件只是.o文件的合集,本质上还是relocatable文件

-l指令

例如,

gcc -o main2 main.o -L./ -ladd_minus

使用-l指令时,要省略前缀 “lib” 和后缀 “.a”

-f指令

指定路径

将.c文件编译成动态库

gcc multi_div.c -fPIC -shared -o libmulti_div.so
生成 libmulti_div.so文件

makefile操作规则

  1. makefile根据源文件 和 目标文件的更新时间,来判断是否进行重新编译(若源文件比目标文件更新),提高编译效率
  2. 若全部都没编译过,则所有C文件都要被编译和链接
  3. 假若工程的几个文件被修改,则只需编译这几个文件,并重新链接工程
  4. 若头文件被修改,那么所有包含头文件的源文件都要重新编译和链接。

makefile规则格式

在这里插入图片描述
makefile按照栈的关系生成,最先入栈的最后生成(因为前面的文件需要后面的文件支持来生成)
clean命令不会自动执行,只有输入clean时才会执行

makefile的简化

一、使用变量来简化
在这里插入图片描述
在这里插入图片描述
此处用$(object)表示objects变量的值

二、让make自动推导依赖关系
此处使用的是隐含规则
在这里插入图片描述
在这里插入图片描述
.PHONY是伪命令,就算输入make clean时,也不会执行clean.exe

在这里插入图片描述

edit : $(objects)
	gcc -o edit $(objects)

此处使用了makefile隐含规则,因为生成edit文件需要各个.o文件,所以make根据隐含规则,自动根据.c文件生成.o文件

makefile隐含规则

一、
在这里插入图片描述
二、 同时生成多个可执行文件
在这里插入图片描述
注: 使用 ./文件名 执行可执行文件

命令出错

  1. 当make检测到命令执行的返回码为不成功时,则终止
  2. 在makefile命令行前加一个"-"号,此时不管命令是否出错,都认为是成功的
    比如:
.PHONY: all
all: p1 p2 p3
p1: p1.c
	-gcc p1.c -o p1

此时就算p1.c中语句错误,也认为是成功的

Make的嵌套执行

在这里插入图片描述
注: @是没有回显的意思

在这里插入图片描述

MakeFile中使用变量

在这里插入图片描述

有两种定义方式
第一种为先使用后定义,使用 = 表示,即赋给左值的值是没有定义的也可以,使用时会去找这个未定义的值(全局的找)
第二种为先定义再使用,使用 := 表示,假如还是按照下图例一,foo的值会为空,因为第一行赋值时,bar还没有定义。

?= 是如果没有被赋值过就赋予等号后面的值
+= 是添加等号后面的值
在这里插入图片描述
左上的运行结果为 huh?
右上无法运行,因为a的值为b的值,b的值为a的值,如此递归引用导致无法运行
左下为 foo bar
右下为 bar,因为赋值给y时,x还为空,所以输出为 bar

其他变量
系统环境变量

环境变量(路径)可以在make开始运行的时候载入

all:
        	@echo $(PATH)

输出: a/b/c/sss
但如果makefile定义了这个变量,则环境变量的值被覆盖(除非make运行时指定了 -e 参数)

PATH := " home"
all:
		@echo $(PATH)

输出: home

自动化变量

$@ 表示规则中的目标文件集

hello : 1.c 2.c 3.c 
		@echo $@

输出: hello

$< 表示规则中依赖目标的第一个目标名字

hello: 1.c 2.c 3.c
		@echo $<

输出: 1.c

预定义变量

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

宏定义

可以控制编译路径

函数功能介绍

在这里插入图片描述

在这里插入图片描述

ifeq函数

ifeq的意思表示条件语句的开始,并指定一个条件表达式,表达式包含两个参数,以逗号分隔,表达式以圆括号括起。相当于条件编译中的#if,判断参数1和参数2是否相等,相等的话,就执行以下语句,以endif结尾
例如,

ifeq ($(CC),gcc)

define 命令

将一些语句,定义成一个变量,相当于一个命令包,以endef结尾
例如:

define GET_MCAL_COMP_CONFIG_PATH
	具体代码
endef

命令块的参数传递,以下是示例代码

# Get config path for each component
MCAL_COMP_DIR_LIST = Mcu Port Gpt Dio Wdg Spi Can Ipc Pwm Adc
define GET_MCAL_COMP_CONFIG_PATH
  ifeq ($(wildcard $(mcal_PATH)/$(1)/config/config_$(MCAL_CONFIG)/.*),)
    # Specified config directory not found, default to base config directory
    $(1)_CONFIG_PATH += $(mcal_PATH)/$(1)/config
  else
    $(1)_CONFIG_PATH += $(mcal_PATH)/$(1)/config/config_$(MCAL_CONFIG)
  endif
endef
$(foreach MCAL_COMP,$(MCAL_COMP_DIR_LIST),$(eval $(call GET_MCAL_COMP_CONFIG_PATH,$(MCAL_COMP))))

其中$ (1)为参数1,当命令块被调用时(使用call函数调用时),传入的第一个参数,将会代替 ( 1 ) , (1), (1) ( 2)是第二个参数

addsuffix函数

$(addsuffix SUFFIX,NAMES…) 函数名称:加后缀函数—addsuffix。
函数功能:为“NAMES…”中的每一个文件名添加后缀“SUFFIX”。参数“NAMES…”
为空格分割的文件名序列,将“SUFFIX”追加到此序列的每一个文件名 的末尾。
返回值:以单空格分割的添加了后缀“SUFFIX”的文件名序列。 函数说明: 示例: $(addsuffix .c,foo bar)

返回值为“foo.c bar.c”

$为引用展开变量展开的值

addprefix函数

加前缀

filter函数

把想要的留下
https://blog.csdn.net/zhoudengqing/article/details/41777957

filter-out函数

把不想要的剔除掉

if函数

https://www.jianshu.com/p/d4ce01b75ddb

subst函数

$(subst _defconfig,,$(b)),意思是将字符串$(b)中的_defconfig去掉

https://blog.csdn.net/pure_dreams/article/details/79976367

patsubst函数

带有规则的替换

strip

去掉最后一个字符后的空格

wildcard函数

功能: 拓展通配符
例如
*是通配符的意思
$(wildcard *.c)
以上这个函数会返回当前目录的所以.c文件的名字,每个名字由空格隔开

Foreach函数

** 格式 ** $(foreach ,, )
在这里插入图片描述
在这里插入图片描述

Eval函数

功能: 展开并运行

其余函数参考地址:

https://blog.csdn.net/ustc_dylan/article/details/6963248
https://blog.csdn.net/yangxuan0261/article/details/52060582#dir-names

CFLAGS 为编译器选项

程序的运行过程:
预处理->编译->汇编->链接
预处理 gcc -E hello.c -o hello.i
编译,生成汇编代码 gcc -S hello.i -o hello.s
汇编,生成.o汇编文件 gcc -c hello.s -o hello.o
链接生成可执行文件 gcc hello.o -o hello

exe文件可以放在makefile里面,可以执行之
函数中用 %不用 *号
export 相当于环境变量,其他文件也可以调用
CURDIR 执行makefile的路径
makefile的层级?

-include 忽略错误

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值