【Linux系统编程】—— 自动化构建工具Makefile指南

文章目录

背景

Makefile 是衡量开发者是否具备完成大型工程能力的一个重要标志。在一个工程中,源文件的数量可能极多,这些文件会按照类型、功能或模块分布在多个目录中。Makefile 通过定义一系列规则,指定文件的编译顺序、依赖关系以及清理规则,从而实现自动化构建。

使用 Makefile 的好处是显而易见的:

  • 自动化编译:只需运行 make 命令,即可完成整个工程的自动编译。
  • 高效开发:显著提高软件开发的效率。

Makefile 是配合 make 命令使用的文件,其中 make 是解释并执行 Makefile 中指令的工具。大多数 IDE 都支持类似的功能,例如 Delphi 的 make,Visual C++ 的 nmake,以及 Linux 下的 GNU make。

将Makefile比作一个人月底的工资,那么一个人工资的各种组成计算就是Makefile的规则

基本使用

在云服务器当中我们可以创建一个文件比如code.c

在文件当中写入

cpp 复制代码
#include <stdio.h>
int main() 
{
    printf("hello Makefile!\n");
    return 0;
}

并且创建一个文件叫做Makefile/makefile两者都是可以的

并且打开vim进行写入

powershell 复制代码
code: code.c
	gcc -o codecode.c

.PHONY: clean
clean:
	rm -f code

依赖关系

  • 目标文件 code依赖于源文件 code.c。

  • 编译命令:gcc -o code code.c。

  • 清理目标:通过 make clean 清理编译生成的目标文件。

项目清理

Makefile 通常会定义一个名为 clean 的目标,用于清理工程文件。由于 clean 不直接或间接依赖于第一个目标文件,因此需要显式执行:

powershell 复制代码
make clean

设置 .PHONY 伪目标可确保 clean 总是被执行:

powershell 复制代码
.PHONY: clean
clean:
	rm -f code

.PHONY 的作用

  • .PHONY 让 Makefile 忽略源文件与可执行目标文件的时间对比,总是执行伪目标的命令。

推导过程

powershell 复制代码
test: code.o
	gcc code.o -o code

test.o: code.s
	gcc -c code.s -o code.o

test.s: code.i
	gcc -S code.i -o code.s

test.i: code.c
	gcc -E code.c -o code.i

.PHONY: clean
clean:
	rm -f *.i *.s *.o code

编译过程
执行 make 命令时,按照以下步骤进行:

  • 预处理:gcc -E code.c -o code.i

  • 汇编:gcc -S code.i -o code.s

  • 编译:gcc -c code.s -o code.o

  • 链接:gcc code.o -o code

Makefile 的工作机制

文件检测:Make 在当前目录中查找名为 Makefile 或 makefile 的文件。

目标检测:读取 Makefile 的第一个目标文件(例如 myproc)。

依赖检查:

  1. 如果目标文件不存在或依赖文件较新,则执行命令生成目标文件。
  2. 递归检查依赖关系,直到满足所有条件。

错误处理:如果缺少依赖文件或命令失败,Make 会停止执行并报错。

文件依赖性示例:

如果 code.c 的修改时间较新,则重新生成所有依赖的文件。

如果目标文件不存在,则根据依赖规则逐层构建。

适度扩展语法

powershell 复制代码
BIN=proc.exe # 定义变量  
CC=gcc 
#SRC=$(shell ls *.c) # 采⽤shell命令⾏⽅式,获取当前所有.c⽂件名 
SRC=$(wildcard *.c) # 或者使⽤ wildcard 函数,获取当前所有.c⽂件名 
OBJ=$(SRC:.c=.o) # 将SRC的所有同名.c 替换 成为.o 形成⽬标⽂件列表 
LFLAGS=-o # 链接选项 
FLAGS=-c # 编译选项 
RM=rm -f # 引⼊命令 
$(BIN):$(OBJ) 
 @$(CC) $(LFLAGS) $@ $^ # $@:代表⽬标⽂件名。 $^: 代表依赖⽂件列表 
 @echo "linking ... $^ to $@" 
%.o:%.c # %.c 展开当前⽬录下所有的.c。 %.o: 同时展开同
名.o
 @$(CC) $(FLAGS) $< # %<: 对展开的依赖.c⽂件,⼀个⼀个的交给gcc。 
 @echo "compling ... $< to $@" # @:不回显命令 
.PHONY:clean 
clean:
 $(RM) $(OBJ) $(BIN) # $(RM): 替换,⽤变量内容替换它 
 
.PHONY:test 
test: 
 @echo $(SRC) 
 @echo $(OBJ)
相关推荐
水饺编程8 分钟前
第2章:Linux 基础,解压缩【.tar.bz2】压缩包文件
linux·c语言·汇编
Zevalin爱灰灰17 分钟前
Linux入门第二部分(ARM裸机篇) 第二章 Cortex-A7 MPCore架构与ARM汇编基础
linux·汇编·arm开发·嵌入式
倔强的石头10623 分钟前
【Linux指南】进程通信系列(七):System V 信号量 —— 同步互斥的内核原语
linux·运维·服务器
GeW35 分钟前
从"补短板"到"强优势"Linux与数据库认证成为产业跃迁人才支点
linux·数据库
码林拾遗WJ2 小时前
告警分级的自动化实测:模型判断 vs 人工拍板
人工智能·算法·自动化
PellyKoo3 小时前
【Ubuntu】GTX 1080 Ti 显卡占用为0但功率高达60W的排查与解决
linux·运维·ubuntu
VisionDataLab3 小时前
机器视觉运维困局:人员高频流动,如何降低产线视觉系统的运维依赖
自动化·视觉检测
Fruiticecake3 小时前
epoll 回显服务器是怎么工作的:从 accept 队列到就绪链表,以及它和 select / poll 的区别
linux
承渊政道4 小时前
Linux网络学习【从NAT与代理服务理解网络转发、探索内网穿透原理、再到认识DNS与ICMP、最后动手部署并测试内网穿透】
linux·网络·学习·内网穿透·dns·nat
重生之小比特4 小时前
【Linux系统】17 库制作与原理(下)
linux·运维·服务器