15-makefile
一、Makefile的概述
1.认识make
- make 是一个命令,是个可执行程序,用来解析 Makefile 文件的命令;
- linux 环境下,这个命令存放在 /usr/bin/ 目录下;
- 当用户输入 make 指令时,系统会自动寻找
makefile、Makefile、GNUmakefile
中任何一个,根据该文件中的指令编译工程。
2.什么是makefile
- makefile 是一个编译指令的脚本,里面记录了一条条编译指令,用于描述程序的编译规则;
- Makefile 文件里面的编译指令是根据我们自己写的程序,编写的编译规则。
3.makeflie与gcc的对比
-
用 gcc 编译的时候,我们要在后面跟上要编译的文件名,如:
gcc main.c func.c
文件量和代码量较少的时候,用这种方式编译还比较方便,但如果整体项目很多,文件很多的时候,编译起来就比较困难,而且还容易漏掉一些文件。没人能保证自己的代码一次运行成功,会反复编译,调试,那每次调试都需要输入很长的 gcc 命令。遇到后期追加功能的时候,时间长了,也忘记项目用到了哪些文件了,对后期工作也会造成困扰;
-
而在 makeflie 里面提前写好了编译指令,只是在编写 makefile 文件的时候需要花费时间,但后面重复编译每次只需要 make 指令调用编译就行了,简化了编译过程。同时后期即使追加功能,以前的编译的文件指令都保存在 makefile 文件里了,也不用担心忘记需要编译哪些文件;
-
gcc 编译很大项目的时候,编译时间会很长,如果对代码进行了修改再编译,即使没有修改代码的文件,也要一起重新编译一次,又得消耗很长的时间;
-
makefile 只会对修改过的代码文件重新编译,其它未修改的直接使用以前编译好的可执行文件,除了第一次编译需要花费较长时间外,后面编译都比较快。因此,make 不仅简化了编译步骤,还节省编译时间,提高编译效率。
二、makefile的语法规则
1.makefile语法规则
1.1语法
先创建一个 makefile 文件,在文件里面写命令:
目标:依赖文件列表命令列表 // 命令列表前有缩进
- gcc 编译
gcc main.c -o main
- 目标:通常是要产生的可执行文件名,如上面的 main;
- 依赖文件:是用来输入从而产生目标的文件,一个目标通常有一个或多个依赖文件,如上面的 main.c;
- 命令:make 执行的动作,一个规则可以含几个命令,有多个命令时,每个命令占一行,如上面的
gcc main.c -o main
。
- 注意: makefile 文件里面写的是脚本,要严格遵守脚本的语法规则,有时候多一个少一个空格都可能造成错误。
1.2makefile编译演示
先创建 makefile 文件,在文件里写入如下命令:
main:main.c func.cgcc main.c func.c -o main
接着在 linux 终端输入make
命令即可实现编译。
- 注意:上面只是演示 makefile 命令的语法,和真正的 makefile 实现的功能差远了。这里的 make 只会执行第一个目标的语句,如果下方还有其它语句不会执行。
1.3make命令格式
1.3.1自定义 makefile 文件名
make -f 自定义文件名
- 在终端输入 make 命令时默认在工作目录中寻找名为 GNUmakefile、makefile、Makefile 的文件作为 makefile 输入文件,但如果我们不按照上面的文件名命名,而是修改为自定义的文件名,那么就需要在 make 命令后面加上我们自定义的文件名,如:
make -f my_makefile
但一般不建议这样做。
1.3.2make后跟其它目标
前面说到,make 执行第一个目标的语句后,后面目标的语句就不会执行了,那要执行后面目标的语句,我们可以指定目标:
make 目标
- 例如:makefile
main:main.c func.cgcc main.c func.c -o main
clean:rm main.c
可以通过输入:终端输入make clean
,来执行指定的语句。
1.3.3复杂版makefile
main:main.o fun.ogcc main.o fun.o -o main
main.o:main.cgcc -c main.c -o main.o
fun.o:fun.cgcc -c fun.c -o fun.o
clean:rm main *.o
- 说明:
- 当终端输入 make 命令时,会执行 makefile 文件里的第一条命令,但发现依赖的
main.o fun.o
文件不存在,会执行下面的命令,先生成main.o fun.o
再执行第一条的命令; *.o
里面的 * 是通配符,这里表示所有以.o
结尾的文件;clean:
为假想目标,只有目标,没有依赖。
- 当终端输入 make 命令时,会执行 makefile 文件里的第一条命令,但发现依赖的
三、makefile的变量
makefile 变量类似于 C 语言中的宏,当 makefile 被 make 工具解析时,其中的变量会被展开。变量一般用于:保存文件名列表、保存文件目录列表、保存编译器名、保存编译参数、保存编译的输出等。
1.自定义变量
- 定义格式
变量名=变量值
-
说明
- 注意,等号两边没有空格,应该严格遵循脚本语言的语法编写;
- makefile 变量名可以以数字开头,区分大小写;
- 变量一般都在 makefile 的头部定义,几乎可在 makefile 的任何地方使用;
- 如果需要读取变量的值,需要在变量名前加上美元符号 , , ,(变量名)或${变量名};
- 自定义变量的作用,主要是为了方便切换不同编译方式,方便指定生成的可执行文件名等,如果一个字符在命令中出现多次,就可以通过变量来代替,如:
CC=gcc EXEC=main$(EXEC):main.o fun.o$(CC) main.o fun.o -o $(EXEC) main.o:main.c$(CC) -c main.c -o main.o fun.o:fun.c$(CC) -c fun.c -o fun.o clean:rm $(EXEC) *.o
2.系统环境变量
make 工具会拷贝系统的环境变量并将其设置为 makefile 的变量,在 makefile 中可直接读取或修改拷贝后的变量,读取环境变量的方法和前面读取自定义变量的方法相同,如:
CC=gcc
EXEC=main$(EXEC):main.o fun.o$(CC) main.o fun.o -o $(EXEC)
main.o:main.c$(CC) -c main.c -o main.o
fun.o:fun.c$(CC) -c fun.c -o fun.o
clean:rm $(EXEC) *.oecho $(PWD) // PWD 是一个环境变量
- 说明:
- echo 相当于C语言里的 printf,将内容输出到终端;
- 我们除了可以使用系统的环境变量,还可以自己导出环境变量:
export NUM=100
; - 自己导出的环境变量只在当前终端有效,不会影响系统的环境变量。
3.预定义环境变量
预定义环境变量即 makefile 定义好的环境变量。
- $@ 当前命令的目标名
- $< 当前命令依赖文件列表中的第一个文件
- $^ 当前命令依赖文件列表,带有除去重复文件的功能
- AR 归档维护程序的程序名,默认值为 ar
- ARFLAGS 归档维护程序的选项
- AS 汇编程序的名称,默认值为 as
- ASFLAGS 汇编程序的选项
- CC C 编译器的名称,默认值为 cc
- CFLAGS C 编译器的选项
- CPP C 预编译器的名称,默认值为$(CC) -E
- CPPFLAGS C 预编译的选项
- CXX C++编译器的名称,默认值为 g++
- CXXFLAGS C++编译器的选项
较常用的是前三个,对上面命令的升级版:
CC=gcc
EXEC=main$(EXEC):main.o fun.o$(CC) $^ -o $@
main.o:main.c$(CC) -c $< -o $@
fun.o:fun.c$(CC) -c $< -o $@
clean:rm $(EXEC) *.oecho $(PWD)
上面的代码可以发现,7、8行代码重复,因此可以合并,使用通配符 %:
CC=gcc
EXEC=main
OBJ=main.o fun.o // 将依赖文件通过自定义变量保存 $(EXEC):$(OBJ)$(CC) $^ -o $@
%.o:%.c$(CC) -c $< -o $@
clean:rm $(EXEC) $(OBJ)echo $(PWD)
相关文章:
15-makefile
一、Makefile的概述 1.认识make make 是一个命令,是个可执行程序,用来解析 Makefile 文件的命令;linux 环境下,这个命令存放在 /usr/bin/ 目录下;当用户输入 make 指令时,系统会自动寻找 makefile、Makef…...

yii2 手动添加 phpoffice\phpexcel
1.下载地址:https://github.com/PHPOffice/PHPExcel 2.解压并修改文件名为phpexcel 在yii项目的vendor目录下创建一个文件夹命名为phpoffice 把phpexcel目录放到phpoffic文件夹下 查看vendor\phpoffice\phpexcel目录下会看到这些文件 3.到vendor\composer目录下…...

使用 AI 辅助开发一个开源 IP 信息查询工具:一
本文将分享如何借助当下流行的 AI 工具,一步步完成一个开源项目的开发。 写在前面 在写代码时,总是会遇到一些有趣的机缘巧合。前几天,我在翻看自己之前的开源项目时,又看到了 DDNS 相关的讨论。虽然在 2021 年我写过两篇相对详细的教程&am…...
HNUST-数据分析技术课堂实验
1.要求 1,从下列第一、二、三组实验中各至少选取一个算法进行实验,选修组实验不作强制要求;2,实验过程不限,目标在于锻炼算法实现过程,即可采用C、C、Java、Python(建议)等任意语言编…...

P3456 [POI2007] GRZ-Ridges and Valleys BFS-连通块思想
题目描述 Byteasar loves trekking in the hills. During the hikes he explores all the ridges and valleys in vicinity. Therefore, in order to plan the journey and know how long it will last, he must know the number of ridgesand valleys in the area he is goi…...
WhisperKit: Android 端测试 Whisper -- Android手机(Qualcomm GPU)部署音频大模型
WhisperKit: Android 端测试 Whisper 1.环境需要2.环境构建(1)克隆项目:(2)工具检查(make setup):(3)下载模型(make download-models)(4)Docker中构建环境(ma…...
Clickhouse(Centos)
地址信息 官网地址:Fast Open-Source OLAP DBMS - ClickHouse 下载地址:packages.clickhouse.com/rpm/stable/ 1.clickhouse-client-23.1.3.5.x86_64.rpm 2.clickhouse-common-static-23.1.3.5.x86_64.rpm 3.clickhouse-common-static-dbg-23.1.3.5.x86_…...
Yolo11改进策略:Block改进|使用FastVit的RepMixerBlock改进Yolo11,重参数重构助力Yolo11涨点(全网首发)
文章目录 摘要FastViT:一种使用结构重新参数化的快速混合视觉变换器1、简介2、相关工作3、体系结构3.1、概述3.2、FastViT3.2.1、重新参数化跳过连接3.2.2、线性训练时间过参数化3.2.3、大核卷积4、实验4.1、图像分类4.2、鲁棒性评价4.3、3D Hand网格估计4.4、语义分割和目标检…...

微信小程序-基于Vant Weapp UI 组件库的Area 省市区选择
Area 省市区选择,省市区选择组件通常与 弹出层 组件配合使用。 areaList 格式 areaList 为对象结构,包含 province_list、city_list、county_list 三个 key。 每项以地区码作为 key,省市区名字作为 value。地区码为 6 位数字,前两…...
NIO(New IO)和BIO(Blocking IO)的区别
Java中的NIO(New IO)和BIO(Blocking IO)的区别及NIO的核心组件 Java中的NIO(New IO)和BIO(Blocking IO)是两种不同的网络通信模型,各自具有独特的特性和适用场景。下面将…...

ROS1入门教程6:复杂行为处理
一、新建项目 # 创建工作空间 mkdir -p demo6/src && cd demo6# 创建功能包 catkin_create_pkg demo roscpp rosmsg actionlib_msgs message_generation tf二、创建行为 # 创建行为文件夹 mkdir action && cd action# 创建行为文件 vim Move.action# 定义行为…...

碰撞检测算法之闵可夫斯基差集法(Minkowski Difference)
在游戏开发和机器人路径规划乃至于现在比较火的自动驾驶中,我们常常需要确定两个物体是否发生碰撞,有一种通过闵可夫斯基差集法求是否相交的算法,下面将介绍一下 闵可夫斯基差集法的优势 闵可夫斯基差集法优势: 可以处理复杂的…...
【唐叔学算法】第18天:解密选择排序的双重魅力-直接选择排序与堆排序的Java实现及性能剖析
引言 在数据排序的世界里,选择排序是一类简单而直观的算法,它通过不断选取未排序部分中的最小(或最大)元素来逐步构建有序序列。今天,我们将深入探讨两种基于选择思想的排序方法——直接选择排序和堆排序,…...

2008-2020年各省技术服务水平相关指标数据
2008-2020年各省技术服务水平相关指标数据 1.时间:2008-2020年 2.指标:行政区划代码、地区、年份、信息传输、软件和信息技术服务业城镇单位就业人员(万人)、软件业务收入(万元)、高技术产品出口额占商品出口额比重(%) 3.范围&…...

机器学习DAY4续:梯度提升与 XGBoost (完)
本文将通过 XGBoost 框架来实现回归、分类和排序任务,帮助理解和掌握使用 XGBoost 解决实际问题的能力。我们将从基本的数据处理开始,逐步深入到模型训练、评估以及预测。最后,将模型进行保存和加载训练好的模型。 知识点 回归任务分类任务…...
ML-Agents:训练配置文件(一)
注:本文章为官方文档翻译,如有侵权行为请联系作者删除 Training Configuration File - Unity ML-Agents Toolkit–原文链接 常见训练器配置 关于训练,您需要做出的首要决定之一是使用哪种训练器:PPO、SAC 还是 POCA。有些训练配置…...

【物联网技术与应用】 实验13:雨滴传感器实验
实验13 雨滴传感器实验 【实验介绍】 雨滴传感器或雨滴检测传感器用于检测是否下雨以及降雨。广泛应用于汽车的雨刷系统、智能照明系统和天窗系统。 【实验组件】 ● Arduino Uno主板* 1 ● USB数据线*1 ● 雨滴传感器* 1 ● 雨滴传感器调理板* 1 ● 面包板*1 ● 9V方型…...
帝国cms电脑pc站url跳转到手机站url的方法
本文讲解一下帝国cms电脑网站跳转到手机动态网站和手机静态网站的方法,笔者以古诗词网 www.gushichi.com为例,为大家介绍操作步骤。方法一:帝国pc站跳转到手机静态站 1、假设我们有帝国cms 电脑网站www.XXX.com,手机网站m.XXX.com …...
Django models中的增删改查与MySQL SQL的对应关系
在 Django 中,models 提供了一种高层次的抽象来与数据库进行交互,使得开发者可以使用 Python 代码而非直接编写 SQL 来执行增删改查(CRUD)操作。下面将详细介绍 Django 的 ORM(对象关系映射)操作如何对应到…...

双指针——快乐数
一.题目描述 202. 快乐数 - 力扣(LeetCode) 二.题目解析 我们要判断一个数是不是快乐数要通过它的三个性质来进行判断。这个数会一直变化,由它的各个位的平方和重新构成这个数。如果这个数在变化的过程中变成了1,那么就是快乐数…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...

2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...
深入理解Optional:处理空指针异常
1. 使用Optional处理可能为空的集合 在Java开发中,集合判空是一个常见但容易出错的场景。传统方式虽然可行,但存在一些潜在问题: // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...