Linux笔记---Makefile的简单用法

1. 什么是Makefile

Makefile 是一种用于自动化构建和管理项目的工具,特别是在软件开发中非常常见。

它包含了一系列规则(rules)和指令,描述了如何编译和链接源代码文件,以及生成最终的可执行文件或库文件。

简单来说,在系统中存在一个叫做make的命令,该命令被使用之后,会在当前目录下寻找一个叫做makefile/Makefile的文件,依据其内定义的规则进行项目的自动化构建。

当我们的项目由多个文件构成时,Makefile能够极大地简化我们构建程序的过程。

Makefile 的优点

自动化构建:通过 Makefile 可以自动化执行编译、链接等构建任务,减少手动操作。

增量构建:Makefile 可以根据文件的时间戳来实现增量构建,避免不必要的重复构建过程。

可移植性:Makefile 是跨平台的构建工具,可以在不同的操作系统上使用


2. Makefile的基本知识和基本用法


2.1 目标,依赖关系和命令

Makefile 的基本结构包括目标、依赖关系和命令。

目标是指要构建的文件或动作,依赖关系描述了生成目标所需的前置条件,而命令则是实际执行的操作,通常是编译源文件、链接目标文件或执行其他操作。

例如,我们需要生成一个test.exe(在Linux下可不带后缀)的可执行程序,而编译出test.exe依赖于其源文件test1.c,test2.c,test3.c...等,则可用下面的语句表述:

目标:目标依赖的文件
    命令
    ...

注意:命令前有且仅能有 "一个TAB" 键,不可以手动敲4个空格。

保存退出,输入make命令:

可以看到,我们再输入make命令并回车之后,自动执行了我们预设的命令,并编译生成了可执行程序test。

如果不希望被自动执行的命令回显到屏幕上,我们可以在命令前加上 "@" :


2.2 伪目标

在一个Makefile文件中可以有多个目标,默认会执行第一个目标,也可在make后紧跟要执行的目标,以指定执行某个目标:

上面提到过,目标也可以是动作,这时常常不生成文件,我们叫这种目标为伪目标。

例如,我们有一个目标(clean)的作用是清除生成的可执行程序以重新生成:


2.3 .PHONY

相信看完上面一小节之后,大家会都很好奇.PHONY是什么。其实,被.PHONY修饰的目标就是始终会执行的目标。

这么说来,test和shishen不是始终会被执行的目标吗?我们尝试多次执行make,会发现:

第一次执行可以成功,然而之后再去执行却发现无法成功,而显示test已是最新。

这是因为test所依赖的文件没有发生更新,所以再次进行make没有任何意义,只会浪费系统资源。

所以,make仅仅提示test已是最新,而不去执行默认目标。

Makefile 通过检查目标文件及其依赖关系的时间戳,确定哪些文件需要重新构建。如果目标文件需要重新构建,Makefile 将按照规则中定义的命令来执行,以生成最终的目标文件。这种方式允许进行增量构建,即只重新构建发生变化的文件,从而提高构建效率。


2.4 自动构建工程的工作原理

Makefile自动构建工程的工作原理:如果某个目标的依赖文件不存在当前目录下,make就会尝试查找与依赖文件同名的目标并优先执行。

如果没有同名目标则会报错,即使在某个目标中存在生成所需文件的指令。

更准确地说,依赖关系列表中的元素默认为文件,当文件不存在时,认为其是同名目标,即使该目标不会生成所需文件,该目标也会被执行。

在下面这个例子中,我们让.c文件一步一步地生成可执行程序,而不是直接生成:

可以看到,即使我们没有指定,其余的三个目标也自动执行了,而且顺序是按照依赖关系的先后进行的。

可以猜想,make程序的内部应该会维护一个栈,用于存储需要执行,但依赖关系不满足的目标。


3. 简化Makefile的技巧语法


3.1 宏定义

当然,不是C语言的那个宏定义,但是二者十分相似,例如:

此时,"SRC" 就代表了所需源文件的集合,定义的符号需要放到 "$()" 中才能使用

在指令部分,也可用**"@" 代表目标,"^" 代表所依赖的文件**:

3.2 通配符

在Makefile中,通配符为 "%" ,假如要将所有.c文件先编译为对应的.o文件,再进行链接(也是最常用的方式):

3.3 相同后缀的集合

在源文件增多时,上面的Makefile需要在宏定义处增加对应的文件。

这未免太麻烦了,我们所使用的通配符也不能最大限度地发挥其作用。

而下面的写法可以解决这个问题:

4. 大多数情况下通用的Makefile

BIN=code
CC=gcc
SRC=$(wildcard *.c)
OBJ=$(SRC:.c=.o)
LFLAGS=-o
FLAGS=-c
RM=rm -f

$(BIN):$(OBJ)
	@echo "linking $^ to $@..."
	@$(CC) $(LFLAGS) $@ $^
%.o:%.c
	@echo "compling $< to $@..."
	@$(CC) $(FLAGS) $<

.PHONY:clean
clean:
	@echo "removing $(BIN)..."
	@$(RM) $(BIN) $(OBJ)
	@echo "Finish"
相关推荐
gywl1 小时前
openEuler VM虚拟机操作(期末考试)
linux·服务器·网络·windows·http·centos
青木沐1 小时前
Jenkins介绍
运维·jenkins
吉大一菜鸡1 小时前
FPGA学习(基于小梅哥Xilinx FPGA)学习笔记
笔记·学习·fpga开发
WTT00112 小时前
2024楚慧杯WP
大数据·运维·网络·安全·web安全·ctf
苹果醋32 小时前
React源码02 - 基础知识 React API 一览
java·运维·spring boot·mysql·nginx
日记跟新中2 小时前
Ubuntu20.04 修改root密码
linux·运维·服务器
唐小旭3 小时前
服务器建立-错误:pyenv环境建立后python版本不对
运维·服务器·python
码农君莫笑3 小时前
信管通低代码信息管理系统应用平台
linux·数据库·windows·低代码·c#·.net·visual studio
BUG 4043 小时前
Linux——Shell
linux·运维·服务器