Makefile语法


前言

  本文只讲LInux环境下的Makefile基础语法,环境搭建见下链接:
https://blog.youkuaiyun.com/weixin_44567668/article/details/125189852


一、概述

  学过C语言都知道需要编译才能运行,其实运行的是可执行文件,可能是.obj或者.o文件,而将源文件.c变成可执行文件的过程就是编译,实际上GCC整个编译流程是:预处理、编译、汇编和链接,如使用下面命令进行编译:

gcc main.c -o main

  那有人好奇Makefile有什么用?上面知道计算机系统运行需要一个可执行文件,我们只有一个main.c文件只需要一个命令,但是如果有很多个源文件和头文件的时候一个个敲命令,特别是在修改了其中某个文件后,一行行敲命令很显然不现实。而Makefile可以有效的解决这个问题,Makefile本质上相当于一个shell脚本文件,那样你将所有编译命令集中在一起,最后只需要输入make命令就可以自动化编译,make与Makefile关系如下图:
在这里插入图片描述
  这就是 make 的执行过程,make 工具就是在 Makefile 中一层一层的查找依赖关系,并执行相应的命令运行gcc编译器,编译出最终的可执行文件

二、示例引用

  首先新建一个main.c的源文件,内容如下:

#include "stdio.h"

int main()
{
   
	printf("hello, world! This is a C program.\n");
	return 0;
}

  然后新建名为Makefile的文件,内容如下:

main:main.o
	gcc -o main main.o

main.o:main.c
	gcc -c main.c

clean:
	rm *.o
	rm main

  先不管语法后面会讲,然后在命令行里输入make命令即可执行Makefile,注意main.c、Makefile与终端当前路径是一致的,然后输入./main运行代码看效果
在这里插入图片描述
  可以看出就3步:编辑工程代码->编辑Makefile文件->输入make执行编译
在这里插入图片描述

三、Makefile规则与运行

3.1 书写格式

  1. Makefile的语法规则
[目标]:[依赖]
	[命令]

  由上一小节的例子可以看出就是目标文件指向对应的依赖文件,然后下面就是具体的转换命令。注意:Makefile文件命令行的首行缩进用Tab键,不能使用空格

  1. 通配符
      make支持3种通配符:*?[]。通配符代替了一系列文件,如“ *.c ”代表后缀为.c的文件

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

%.o : %.c
	命令
  1. 注释
      在Makefile里使用#添加注释,可以用反斜框进行转义,如\#

3.2 命令格式

  1. 显示命令
  • 通常,make会把其要执行的命令行在命令执行前输出到屏幕上。当我们用@字符在命令行前,那么,这个命令将不被make显示出来
  • 如果make执行时,带入make参数-n--just-print,那么其只是显示命令,但不会执行命令,这个功能很有利于我们调试我们的 Makefile
  • 而make参数-s--slient则是全面禁止命令的显示
  1. 命令执行
      当依赖目标新于目标时,也就是当规则的目标需要被更新时,make 会一条一条的执行其后的命令。需要注意的是,如果你要让上一条命令的结果应用在下一条命令时,你应该使用分号;分隔这两条命令,如:
exec: 
	cd /home/hchen;pwd
  1. 命令出错
      有些时候,命令的出错并不表示就是错误的。为了做到这一点,忽略命令的出错,我们可以在 Makefile 的命令行前加一个减号-
clean: 
	-rm -f *.o

  还有一个全局的办法是,给 make 加上-i或是--ignore-errors参数,那么,Makefile 中所有命令都会忽略错误。而如果一个规则是以.IGNORE作为目标的,那么这个规则中的所有命令将会忽略错误。
  还有一个要提一下的 make 的参数的是-k或是--keep-going,这个参数的意思是,如果某规则中的命令出错了,那么就终目该规则的执行,但继续执行其它规则

  1. 定义命令包
      如果 Makefile 中出现一些相同命令序列,那么我们可以为这些相同的命令序列定义一个变量。定义这种命令序列的语法以define开始,以endef结束,如:
define run-yacc 
	yacc $(firstword $^) 
	mv y.tab.c $@ 
endef

  这里,“run-yacc”是这个命令包的名字,其不要和 Makefile 中的变量重名。调用示例如下:

foo.c : foo.y 
	$(run-yacc)

3.3 make的运行

  1. make的工作方式
    ①读入所有的 Makefile。
    ②读入被 include 的其它 Makefile。
    ③初始化文件中的变量。
    ④推导隐晦规则,并分析所有规则。
    ⑤为所有的目标文件创建依赖关系链。
    ⑥根据依赖关系,决定哪些目标要重新生成。
    ⑦执行生成命令。

  2. Makefile的文件名
      默认的情

makefile 实例分析 Makefile 语法分析 第一部分 VERSION = 2# 给变量VERSION赋值 PATCHLEVEL = 6# 给变量PATCHLEVEL赋值 SUBLEVEL = 22# 给变量SUBLEVEL赋值 EXTRAVERSION = .6# 给变量EXTRAVERSION赋值 NAME = Holy Dancing Manatees, Batman!# 给变量NAME赋值 # *DOCUMENTATION*# To see a list of typical targets execute "make help"# More info can be located in ./README# Comments in this file are targeted only to the developer, do not# expect to learn how to build the kernel reading this file. # Do not:# o use make's built-in rules and variables#    (this increases performance and avoid hard-to-debug behavour);# o print "Entering directory ...";MAKEFLAGS += -rR --no-print-directory# 操作符“+=”的作用是给变量(“+=”前面的MAKEFLAGS)追加值。# 如果变量(“+=”前面的MAKEFLAGS)之前没有定义过,那么,“+=”会自动变成“=”;# 如果前面有变量(“+=”前面的MAKEFLAGS)定义,那么“+=”会继承于前次操作的赋值符;# 如果前一次的是“:=”,那么“+=”会以“:=”作为其赋值符# 在执行make时的命令行选项参数被通过变量 “MAKEFLAGS”传递给子目录下的make程序。# 对于这个变量除非使用指示符“unexport”对它们进行声明,它们在整个make的执行过程中始终被自动的传递给所有的子make。# 还有个特殊变量SHELL与MAKEFLAGS一样,默认情况(没有用“unexport”声明)下在整个make的执行过程中被自动的传递给所有的子make。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

别问,问就是全会

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

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

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

打赏作者

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

抵扣说明:

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

余额充值