7. 一文快速学懂常用工具——Makefile

本章讲解知识点

    1. 引言
    1. Makefile
    1. Makefile 入门


  • 本专栏适合于软件开发刚入职的学生或人士,有一定的编程基础,帮助大家快速掌握工作中必会的工具和指令
  • 本专栏针对面试题答案进行了优化,尽量做到好记、言简意赅
  • 如专栏内容有错漏,欢迎在评论区指出或私聊我更改,一起学习,共同进步。
  • 相信大家都有着高尚的灵魂,请尊重我的知识产权,未经允许严禁各类机构和个人转载、传阅本专栏的内容。


1. 引言

家人们,我问大家一个问题,我们之前的教程都是针对一个源文件 douya.c 进行了无数种操作。当我们有多个文件时,怎么链接到一起最后形成一个执行文件呢?

当然我们也有简单的做法。

我们给出实例,我们创建两个 c 文件,一个 douya.c 和 max.c,douya.c 里 main 函数调用 max.c 里的 max 比较大小函数:

给出 max.c 内容:

#include <stdio.h>  
#include "max.h"  int max(const int a, const int b){  return a > b ? a : b;  
}  

然后给出头文件 max.h,我们 extern 出 max 函数:

#ifndef MAX_H  
#define MAX_H  extern int max(const int a, const int b);  #endif

最后我们给出 douya.c 内容:

#include <stdio.h>   
#include "max.h"   
int main(){    printf("Hello, Douya!\n");   int result = max(4, 6);  printf("the max value is %d: \n", result);  return 0;    
} 

1.好了,这里我们给出了一个简单例子,主要是为了说明多文件的编译、链接、执行。

然后我们输入

$ gcc -Wall douya.c max.c -o douya

该命令自动将两个文件编译、链接并生成执行文件,运行 ./douya

$ ./douya  
Hello, Douya!  
the max value is 6:  

我们就实现了。

2.当然我们也可以单文件先各自生成目标文件,最后链接成可执行文件。

如下:

$ gcc -c douya.c -o douya.o

这里的 -c 就表示只执行到汇编这一步而不链接,生成目标文件 douya.o;max.c 文件同理生成 max.o,最后我们将两个目标文件链接起来生成可执行文件。大家关于程序编译的四个步骤,你可没忘吧?

$ gcc -c douya.c -o douya.o
$ gcc -c max.c -o max.o
$ gcc max.o douya.o -o douya
$ ./douya  
Hello, Douya!  
the max value is 6:  

肯定有家人会说了,一个工程项目往往几十个源文件,难道还要一一编译再链接?那也太麻烦了吧!

确实很麻烦,所以我们引入今天的正题。


2. Makefile

2.1. 什么是 Makefile

我们要引出一个重要内容——Makefile。Makefile 是一种常用于编译的脚本语言。它可以更好更方便的管理你的项目的代码编译,节约编译时间(没改动的文件不编译)。

2.2. 为什么使用 Makefile

makefile 关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile 定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 makefile 就像一个 Shell 脚本一样,其中也可以执行操作系统的命令。

makefile 带来的好处就是——“自动化编译”,一旦写好,只需要一个 make 命令,整个工程完全自动编译,极大的提高了软件开发的效率。make 是一个命令工具,是一个解释 makefile 中指令的命令工具,一般来说,大多数的 IDE 都有这个命令,比如:Delphi 的 make,Visual C++的 nmake,Linux 下 GNU 的 make。可见,makefile 都成为了一种在工程方面的编译方法。


3. Makefile 入门

3.1. Makefile 语法

我们下面介绍它的常用语法

目标...: 依赖...  命令1  命令2  ...  

1.目标:目标即要生成的文件。如果目标文件的更新时间晚于依赖文件的更新时间,则说明依赖文件没有改动,目标文件不需要重新编译。否则重新编译并更新目标。

2.依赖:即目标文件由哪些文件生成。如果依赖条件中存在不存在的依赖条件,则会寻找其它规则是否可以产生依赖条件。

例如:规则一是生成目标 hello.out 需要使用到依赖条件 hello.o,但是 hello.o 不存在。则 Makefile 会寻找到一个生成 hello.o 的规则二并执行。

3.命令:即通过执行该命令,由依赖文件生成目标文件。

注意每条命令前必须有且仅有一个 tab 保持缩进,这是语法要求。

4.ALL:Makefile 文件默认只生成第一个目标文件即完成编译,但是我们可以通过 “ALL” 指定需要生成的目标文件。

5.示例:我们前面讲了两个文件链接的实例,直接使用 Makefile 的方式编译:写一个 Makefile

ALL:douya  douya:max.o douya.o  gcc max.o douya.o -o douya  
max.o:max.c  gcc -c max.c -o max.o  
douya.o:douya.c  gcc -c douya.c -o douya.o  

编译并执行:

$ make  
gcc -c max.c -o max.o  
gcc -c douya.c -o douya.o  
gcc max.o douya.o -o douya     
$ ./douya  
Hello, Douya!  
the max value is 6:  

怎么样,每次我们编译,只需要 make 一下,不用再重复输入指令,是不是很方便?

3.2. 两个函数

1.wildcard。wildcard 用来明确表示通配符。

示例:

SRC = $(wildcard ./*.c)  

表示匹配目录下所有的 .c 文件,并将其赋值给 SRC 变量。

2.patsubst。pat 是 pattern 的缩写,subst 是 substring 的缩写。Patsubst 是模式字符串替换函数。

示例:

OBJ = $(patsubst %.c, %.o, $(SRC))  

这个函数有三个参数,意思是取出 SRC 中所有的值,然后将 “.c” 替换为 “.o”,最后赋值给 OBJ 变量。

这两个函数很有用,我们来举个例子。通过上面两个函数,加入我们目录下有很多个 “.c” 后缀的源文件,就不需要写很多条规则语句了,而是可以像下面这样写:

SRC = $(wildcard ./*.c) 
OBJ = $(patsubst %.c, %.o, $(SRC))  ALL: douya  douya: $(OBJ)  gcc $(OBJ) -o douya  $(OBJ): $(SRC)  gcc -c $(SRC) -o $(OBJ)  

这里需要先将所有的 “.c” 文件编译为 “.o” 文件,这样后面更改某个 “.c” 文件时,其它的 “.c” 文件将不再编译,而只是编译有更改的 “.c” 文件,可以大大节约大项目中的编译速度。

3.3. 通配符

Makefile 是可以使用 shell 命令的,所以 shell 支持的通配符在 Makefile 中也是同样适用的。 shell 中使用的通配符有:"*","?","[...]"。具体看一下这些通配符的表示含义和具体的使用方法。

*: 匹配 0 个或者是任意个字符
: 匹配任意一个字符
[]: 我们可以指定匹配的字符放在 "[]"

下面实例可以说明通配符可以使用在规则的命令当中,表示的是任意的以 .o 结尾的文件。

.PHONY:clean
clean:rm -rf *.o test

下面实例可以说明我们的通配符不仅可以使用在规则的命令中,还可以使用在规则中。用来表示生所有的以 .c 结尾的文件。

test:*.cgcc -o $@ $^

还有一个和通配符 "*" 相类似的字符,这个字符是 "%",也是匹配任意个字符,使用在我们的的规则当中。

test:test.o test1.ogcc -o $@ $^
%.o:%.cgcc -o $@ $^

3.4. 变量

Makefile 中也有一些已经定义好的常用变量,这里介绍其中常用的3个。

(1)$@:表示规则中的目标,例如 douya.o

(2)$<:表示规则中的第一个依赖条件,例如 douya.c

(3)^ :表示规则中的所有依赖条件,由于我们示例中都只有一个依赖条件,这种情况下 ^ $< 区别不大。

(4)示例:使用这些变量替换上面写的 Makefile,即是:

ALL: douya  douya: douya.o max.ogcc -g $^ -o $@%.o: %.cgcc -c $^ -o $@ 

3.5. 其它常用功能

1.代码清理 clean。我们可以编译一条属于自己的 clean 语句,来清理 make 命令所产生的所有文件。例如:

ALL: douya  douya: douya.o max.ogcc -g $^ -o $@%.o: %.cgcc -c $^ -o $@clean:  -rm -rf *.o douya 

这样我们就可以使用 clean 命令来清理生成的文件了:

$ make clean

2.伪目标 .PHONY。上面我们写了一个 clean 语句,使得我们执行 “make clean” 命令的时候,可以清理我们生成的文件。

但是假如还存在一个文件名就是 clean 文件,那么我们再执行 “make clean” 命令的时候就只是显示:make: clean is up to date.

解决方法就是我们使用伪目标,这样就可以避免出现上面的问题了,例如:

ALL: douya  douya: douya.o max.ogcc -g $^ -o $@%.o: %.cgcc -c $^ -o $@clean:  -rm -rf *.o douya   .PHONY: clean ALL

我们只是讲了入门知识,以上知识已经足以帮助我们看懂别人写好的 Makefile,或者自己写简单的 Makefile。

关于 Makefile,深入学习请参考《跟我一起写 makefile pdf 陈皓》



面试题

1. Makefile 了解吗?⭐⭐⭐

Makefile 是一种常用于编译的脚本语言。它可以更好更方便的管理你的项目的代码编译,节约编译时间(没改动的文件不编译)。

makefile 带来的好处就是——“自动化编译”,一旦写好,只需要一个 make 命令,整个工程完全自动编译,极大的提高了软件开发的效率。

2. make 命令的作用是什么?⭐⭐⭐

make 命令根据 Makefile 中的规则和依赖关系,自动构建和编译项目的源代码,以生成可执行文件或其他目标。

3. Makefile 中的目标和依赖关系是什么意思?⭐⭐⭐

目标是要构建的文件或任务,依赖关系是构建目标所需的文件或任务列表。Makefile 规则定义了如何从依赖关系生成目标。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/126557.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flask 网站装潢, 简易更换模板

Flask 网站装潢&#xff0c;简易更换模板 本博文找个好看的网页模板&#xff0c;并简单改一改变成flask模板&#xff0c;并展示 主博客目录&#xff1a;《从零开始学习搭建量化平台笔记》 文章目录 Flask 网站装潢&#xff0c;简易更换模板下载模板Python 自动生成目录修改目录…

C# 使用 REST API HTTP 客户端生成器

本文内容 使用 AutoClientAttribute使用谓词属性定义 HTTP 方法HTTP 有效负载HTTP 头 显示另外 2 个 备注 此 API 是实验性的。 它可能会在后续版本的库中更改&#xff0c;并且无法保证向后兼容性。 HttpClient是使用 REST API 的好方法&#xff0c;但存在挑战。 其中一个挑…

CMake基础【学习笔记(八)】

声明此博客为转载 CMake基础 文章目录 CMake基础一、准备知识1.1 C的编译过程1.2 静态链接库和动态链接库1.3 为什么需要CMake1.3.1 g 命令行编译1.3.2 CMake简介 二、CMake基础知识2.1 安装2.2 第一个CMake例子2.3 语法基础2.3.1 指定版本2.3.2 设置项目2.3.3 添加可执行文件…

华纳云 宝塔怎么配置香港服务器多ip?

宝塔面板是一款开源的服务器管理面板&#xff0c;提供了简单易用的图形化界面&#xff0c;使用户能够轻松管理和配置服务器。通过切换到香港服务器多IP&#xff0c;用户可以拥有更多的IP资源&#xff0c;提供更灵活的网络服务。 配置香港服务器多IP 1.登录宝塔面板 打开浏览器&…

Goby 漏洞发布| Cisco IOS XE ebui_wsma_http 接口权限绕过漏洞(CVE-2023-20198)

漏洞名称&#xff1a; Cisco IOS XE ebui_wsma_http 接口权限绕过漏洞&#xff08;CVE-2023-20198&#xff09; English Name&#xff1a; Cisco IOS XE ebui_wsma_http API Permission Bypass Vulnerability (CVE-2023-20198) CVSS core: 10 影响资产数&#xff1a; 307282…

kafka为什么如此之快?

天下武功&#xff0c;唯快不破。同样的&#xff0c;kafka在消息队列领域&#xff0c;也是非常快的&#xff0c;这里的块指的是kafka在单位时间搬运的数据量大小&#xff0c;也就是吞吐量&#xff0c;下图是搬运网上的一个性能测试结果&#xff0c;在同步发送场景下&#xff0c;…

以八数码问题为例实现A*算法的求解(未完结)

八数码&#xff1a; 在一个 33 的网格中&#xff0c;1∼8 这 8 个数字和一个 x 恰好不重不漏地分布在这 33 的网格中。 例如&#xff1a; 1 2 3 x 4 6 7 5 8在游戏过程中&#xff0c;可以把 x 与其上、下、左、右四个方向之一的数字交换&#xff08;如果存在&#xff09;。…

(11月4日)GBASE南大通用 x openGauss Meetup,欢迎报名

由openGauss社区、天津南大通用数据技术股份有限公司主办&#xff0c;伟仕佳杰科技有限公司、神州数码&#xff08;中国&#xff09;有限公司协办的“GBASE南大通用 x openGauss Meetup”活动将于2023年11月4日&#xff08;周六&#xff09;在合肥市高新区云飞路66号天源迪科科…

3DEXPERIENCE云端项目管理小工具--Project Planner项目策划者角色

云端3DEXPERIENCE平台提供了一个协作环境&#xff0c;使企业和个人能够以全新的方式实现创新。它将人员、创意、数据和解决方案连接到一个始终在线且可用的协作和交互环境中&#xff0c;可以帮助您的企业提高执行力、生产率并加速创新。 3DEXPERIENCE中的Project Planner项目策…

BUUCTF 后门查杀 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 小白的网站被小黑攻击了&#xff0c;并且上传了Webshell&#xff0c;你能帮小白找到这个后门么&#xff1f;(Webshell中的密码(md5)即为答案)。 密文&#xff1a; 下载附件&#xff0c;解压得到一个网站文件夹。 解…

Nginx搭载负载均衡及前端项目部署

目录 ​编辑 一.Nginx安装 1.安装所需依赖 2.下载并解压Nginx安装包 3.安装nginx 4.启动Nginx服务 二.Tomcat负载均衡 1.准备环境 1.1 准备两个Tomcat 1.2 修改端口号 1.3 配置Nginx服务器集群 2.效果展示 ​编辑三.前端项目打包 ​编辑四.前端项目部署 1.上传项目…

YOLO目标检测——安全帽佩戴检测数据集【含对应voc、coco和yolo三种格式标签】

实际项目应用&#xff1a;安全帽佩戴检测数据集可以用于实时检测工作人员是否按照要求佩戴了安全帽&#xff0c;以保障他们的安全数据集说明&#xff1a;安全帽佩戴检测数据集&#xff0c;真实场景的高质量图片数据&#xff0c;数据场景丰富&#xff0c;图片分为带头盔和没带头…

云原生周刊:ingress2gateway 发布 | 2023.10.30

开源项目推荐 m9sweeper m9sweeper 是一个免费且简单的 Kubernetes 安全平台。它将行业标准的开源实用程序集成到一站式 Kubernetes 安全工具中&#xff0c;该工具可以帮助大多数 Kubernetes 管理员保护 Kubernetes 集群以及集群上运行的应用程序。 Kairos Kairos 是在 Kub…

wordpress如何修改数据库里用户ID下一个自增值的开始数字

有时候我们为了让别人认为网站有很多注册用户&#xff0c;会想把网站用户ID的起始数改大一点&#xff0c;因为WP默认的用户ID是从1开始&#xff0c;注册一个就加1&#xff0c;这样别人就很容易知道网站的用户量。 那么如何改呢&#xff1f;首先进phpmyadmin&#xff0c;找到wp…

智慧矿山:AI算法在带式运输机中的异物识别应用

随着现代农业和工业的发展&#xff0c;带式运输机在各种生产作业中发挥着越来越重要的作用。然而&#xff0c;在带式运输机运行过程中&#xff0c;可能会混入各种异物&#xff0c;这些异物的存在可能会对运输过程和设备本身造成损害。为了解决这一问题&#xff0c;本文将介绍一…

c++装饰器模式

前言 装饰器模式&#xff0c;就是可以对一个对象无限装饰一些东西&#xff0c;而且可以没有顺序。比如一个人可能只会说出他的名字&#xff0c;但是可以让他再说哈哈&#xff0c;可以说完哈哈之后再说哇哇。如何后面又不想装饰了&#xff0c;不需要改类原来的代码&#xff0c;…

基于深度学习的人脸性别年龄识别 - 图像识别 opencv 计算机竞赛

文章目录 0 前言1 课题描述2 实现效果3 算法实现原理3.1 数据集3.2 深度学习识别算法3.3 特征提取主干网络3.4 总体实现流程 4 具体实现4.1 预训练数据格式4.2 部分实现代码 5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 毕业设计…

智慧校园地下管线三维可视化管控平台减少人力和物力资源的浪费

随着科技的不断发展&#xff0c;三维可视化管理平台在各个领域得到了广泛的应用。三维可视化管理平台通过将数据以三维形式呈现&#xff0c;使得用户能够更直观地理解和分析数据&#xff0c;从而提高工作效率和决策质量。 VR数字孪生园区系统是通过将实际园区的各种数据和信息进…

RabbitMQ入门到实战教程,消息队列实战,改造配置MQ

RabbitMQ入门到实战教程&#xff0c;MQ消息中间件&#xff0c;消息队列实战-CSDN博客 3.7.Topic交换机 3.7.1.说明 Topic类型的Exchange与Direct相比&#xff0c;都是可以根据RoutingKey把消息路由到不同的队列。 只不过Topic类型Exchange可以让队列在绑定BindingKey 的时候…

C语言实现获取文件大小、创建时间、修改时间(stat结构体)

源代码&#xff1a; #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <sys/stat.h> #include <sys/types.h>#define EXE_ABORT() {system("pause");return 0;} #define FILEPATH &q…