【Makefile】一篇文章搞定Makefile!入门速通~

个人根据正点原子文档原创学习笔记,如有侵权,联系删除,转载请标明出处;

本文包括但不限于:易读性引入、编写与使用、语法、变量、模式、伪目标、条件判断、函数;


何为Makefile

Makefile是一种用于构建和管理项目的自动化构建工具的配置文件;

它使用一套特定的语法来定义目标、依赖关系和构建规则

多终端输入 GCC 命令不现实,可编写一个描述“编译哪些源码文件、如何编译”的文件;

make: 工程编译的工具

Makefile: 描述哪些文件需要编译、哪些需要重新编译的文件

事实上 IDE 都有Makefile,只不过这些 IDE对其进行了封装,提供的是已封装后的图形界面。


Makefile 的引入☆☆☆

典例

C 文件:main.c、input.c 、calcu.c

头文件: input.h、calcu.h

gcc main.c calcu.c input.c -o main

在这里插入图片描述

  • 工程仅三个文件!若文件很多或有文件被修改,使用上面的命令编译的时候所有的文件都会重新编译;

  • 改进编译方法:第一次编译工程,先将工程中的文件都编译一遍,后面修改了哪个文件就编译哪个文件。

    • 分别是将 main.c、input.c 和 calcu.c 编译成对应的.o 文件
    • 将所有的.o 文件链接成可执行文件
    gcc -c main.c
    gcc -c input.c
    gcc -c calcu.c
    gcc main.o input.o calcu.o -o main
    

Makefile编写与使用

如果修改的文件一多,可能都不记得哪个文件修改过了,然后忘记编译,为此我们需要这样一个工具

  • 如果工程没有编译过,那么工程中的所有.c 文件都要被编译并且链接成可执行程序;

  • 如果工程中只有个别 C 文件被修改了,那么只编译这些被修改的 C 文件即可;

  • 如果工程的头文件被修改了,那么我们需要编译所有引用这个头文件的 C 文件,并且链接成可执行文件;

能够完成这个功能的就是 Makefile!

vim编写makefile
  • 行首需要空出来的地方一定要使用“TAB”键!

在这里插入图片描述

make编译工程
  • 直接在命令行中输入 make 命令来编译工程;

  • make 命令会在当前目录下查找是否存在“Makefile”这个文件;

  • 存在则按照Makefile 中定义的编译方式进行编译

  • 文件改动后make,会对改动的自动编译

在这里插入图片描述


Makefile 语法

个人理解:指定目标及其所需资源,执行(创建一个 Shell 进程)完成目标的命令即为makefile

makefile(规则) = Linux基本命令+shell进程+gcc编译器

Makefile 规则格式

Makefile 里面是由一系列的规则组成

#/*	目标…... : 依赖文件集合……
#		命令 1
#		命令 2
#		……					
#例:							*/
main : main.o input.o calcu.o
	gcc -o main main.o input.o calcu.o
  • 上述规则的目标是 main,main.o、input.o 和 calcu.o 是生成 main 的依赖文件,

    如果要更新目标 main,就必须先更新它的所有依赖文件(刚刚更改input.c时已体现);

  • 命令列表中的每条命令必须以 TAB 键开始,不能使用空格!

    make 命令会为 Makefile 中的每个以 TAB 开始的命令创建一个 Shell 进程去执行。

clean
  • 功能:完成工程的清理

  • 执行以后就会删除当前目录下所有的.o 文件以及 main

  • 无依赖文件,默认为依赖文件都是最新,命令行下其对应的命令不会执行,命令行可用make clean

make clean

在这里插入图片描述

make print

功能:类似clean,不过功能是打印;

@echo

原样输出,类似c语言print;

”$(变量)“

引用变量,变量需提前赋值;

Make 的执行过程
make

在这里插入图片描述

在这里插入图片描述

顺序问题
  • Makefile 的“终极目标”所在的规则以外,其它规则的顺序在 Makefile 中是没有意义的

  • “终极目标”就是指在使用 make 命令的时候没有指定具体的目标时,make 默认的那个目标,它是 Makefile 文件中第一个规则的目标;

  • 如果 Makefile 中的第一个规则有多个目标,那么这些目标中的第一个目标就是 make 的“终极目标”。


Makefile 变量
典例
  • 跟 C 语言一样 Makefile 也支持变量

  • Makefile 中的变量都是字符串!类似 C 语言中的宏

1 #Makefile 变量的使用
2 objects = main.o input.o calcu.o
3 main: $(objects)
4 	gcc -o main $(objects)
  • 注释开头要用符号“#”

  • 定义了一个变量 objects,并且进行赋值,其值为字符串“main.o input.o calcu.o”,引用方法是“$(变量名)”;

#示例代码 3.4.2.1 赋值符"="":=""?=""+="使用

name = zzk
curname = $(name)
name = zuozhongkai

name1 = zzk
curname1 := $(name1)
name1 = zuozhongkai

name2 = zzk
curname2 ?= $(name2)
name2 = zuozhongkai

name3 = zzk
curname3 ?= $(name3)
name3 = zuozhongkai

print:
	@echo curname: $(curname)
	@echo curname1: $(curname1)
	@echo curname2: $(curname2)
	@echo curname3: $(curname3)
  • 要输出一串字符的话使用“echo”,就和 C 语言中的“printf”一样;

  • “echo”前加“@”符号,因Make执行中会自动输出命令执行过程,在命令前加上“@”则不输出命令执行过程

赋值符“=”
  • 变量的真实值取决于它所引用的变量的最后一次有效值;
赋值符”:=“
  • 不会使用后面定义的变量,只能使用前面已经定义好的;
赋值符“?=”
  • 如果变量 curname 前面没有被赋值,那么此变量就是“zuozhongkai”,

  • 如果前面已经赋过值了,那么就使用前面赋的值。

在这里插入图片描述

变量追加“+=“
objects = main.o inpiut.o
objects += calcu.o
  • 一开始变量 objects 的值为“main.o input.o”,后面我们给他追加了一个“calcu.o”;

  • 因此变量 objects 变成了“main.o input.o calcu.o”,这个就是变量的追加;

Makefile 模式规则
 %.o : %.c
	#命令
  • 以前将对应.c 源文件编译为.o 文件,每个 C 文件都写一对应规则,若工程中 C 文件很多的话则很麻烦;

  • 可使用 Makefile 中的模式规则,通过模式规则可使用一条规则将所有的.c 文件编译为对应的.o 文件

模式规则中,至少在规则的目标定定义中要包涵“%”,否则就是一般规则;
目标中的“%”表示对文件名的匹配,“%”表示长度任意的非空字符串;
比如“%.c”就是所有的以.c 结尾的文件,类似与通配符,a.%.c 就表示以 a.开头,以.c 结束的所有文件;
  • 通配符)“%”表示对文件名的匹配,“%”表示长度任意的非空字符串

在这里插入图片描述

第 5、6 这两行代码替代了“示例代码 3.4.3.1”中的 3~8 行代码

借助另外一种强大的变量—自动化变量,保障 .o .c 文件编译链接;

Makefile 自动化变量
  • 自动化变量:变量会把模式中所定义的一系列的文件自动的挨个取出,直至所有的符合模式的文件都取完;

  • 自动化变量只应出现在规则的命令中;

在这里插入图片描述

常用的三种: @ 、 @、 @<和$^

在这里插入图片描述

Makefile 伪目标
作用
  • 执行 make 命令的时候通过指定这个伪目标来执行其所在规则的定义的命令;

  • 伪目标是为避免 Makefile 中定义的执行命令的目标和工作目录下的实际文件出现名字冲突;

#例
clean:
	rm *.o
	rm main

#规则中并没有创建文件 clean 的命令,因此工作目录下永远都不会存在文件 clean;
#输入“make clean”以后,后面的“rm *.o”和“rm main”总是会执行;

工作目录下创建一个名为“clean”的文件,那就不一样;
在这里插入图片描述

执行“make clean”的时候,规则因为没有依赖文件,所以目标被认为是最新的;
后面的 rm 命令也就不会执行,预先设想的清理工程的功能也就无法完成;

我们可以将 clean 声明为伪目标,声明方式:

.PHONY : clean
#示例代码 3.4.5.1 伪目标
#工作目录下有一个名为“clean”的文件!

objects = main.o input.o calcu.o
main: $(objects)
	gcc -o main $(objects)
 
.PHONY : clean
 
%.o : %.c
	gcc -c $<
 
clean:
	rm *.o
	rm main

在这里插入图片描述

  • 声明 clean 为伪目标以后不管当前目录下是否存在名为“clean”的文件,输入“make clean”的话规则后面的 rm 命令都会执行
Makefile 条件判断

通过条件判断语句来根据不同的情况来执行不同的分支;

两种条件判断方法

在这里插入图片描述

四个调关键字

ifeq、ifneq、ifdef 、 ifndef

ifeq 与ifneq
  • 用法

在这里插入图片描述

  • ifeq 用来判断是否相等,ifneq 就是判断是否不相等
用来比较“参数 1”和“参数 2”是否相同,如果相同则为真,“参数 1”和“参数 2”可以为函数返回值;
ifneq 的用法类似,ifneq 是用来比较“参数 1”和“参数 2”是否不相等,如果不相等的话就为真;
ifdef 与 ifndef
  • 用法

在这里插入图片描述

  • 功能
如果“变量名”的值非空,那么表示表达式为真,否则表达式为假,“变量名”同样可以是一个函数的返回值;
ifndef 用法类似,但是含义用户 ifdef 相反;
Makefile 函数使用
  • 不支持自定义函数

  • Makefile 中的函数已定义好

用法

在这里插入图片描述

函数的调用以“$”开头,调用函数和调用普通变量一样;

参数集合是函数的多个参数,参数之间以逗号“,”隔开,函数名和参数之间以“空格”分隔开;

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值