Makefile文件的编写(实例详解)

2023-05-16

1.什么是Makefile?

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

在 Linux环境下使用make工具能够比较容易的构建一个属于你自己的工程,整个工程的编译只需要一个命令就可以完成编译、连接以至于最后的执行。不过这需要我们投入一些时间去完成一个或者多个称之为Makefile 文件的编写。

Makefile是一个文件,这个文件中写的是编译的规则,使用Makefile可以根据文件的时间戳来决定当前文件是否参与本次编译。

2.什么是make?

简单来说make是一个可执行程序,在/usr/bin/路径下存放。当执行make的时候就会解析当前目录下的Makefile文件,从而编译当前目录下的工程。

3.Makefile的编写实例

3.1第一个实例

在一个工程中创建text.c文件

#include <stdio.h>

int main(int argc,const char * argv[])
{
    printf("hello world\n");
    return 0;
}

创建Makefile文件
#:代表注释

all:#标签,在执行make的时候默认执行第一个标签后的语句
	gcc text.c -o text
clean:#make clean可以执行这个标签
	rm text

执行结果:
在这里插入图片描述
从图片中我们大致可以了解Makefile的作用。

3.2Makefile的语法规则

目标:依赖
(tab键)命令

text:text.c
	gcc text.c -o text
clean:#伪命令 make clean不会生成clean的文件
	rm text

执行结果:
在这里插入图片描述

3.3Makefile编译多文件

text.c

#include <stdio.h>
extern int add(int a,int b);
extern int sub(int a,int b);
int main(int argc,const char * argv[])
{
    int a=100,b=200;
    printf("%d\n",add(a,b));
    printf("%d\n",sub(a,b));
    return 0;
}

sub.c

int sub(int a,int b)
{
    return (a-b);
}

add.c

int add(int a,int b)
{
    return (a+b);
}

Makefile文件

text: text.o sub.o add.o
	gcc text.o sub.o add.o -o text
text.o:text.c
	gcc -c text.c -o text.o
sub.o:sub.c
	gcc -c sub.c -o sub.o
add.o:add.c
	gcc -c add.c -o add.o
clean:#伪命令 make clean不会生成clean的文件
	rm *.o text

执行结果:
在这里插入图片描述
在函数sub.c中添加几个空格后改变sub.c
在这里插入图片描述
只编译了sub.c文件

3.4Makefile中变量的使用

Makefile中的变量不需要使用类型去定义,随用随写即可。
例如:a=123
变量的使用规则 $(变量名)或者${变量名}
@ 作用是取消命令执行的回显动作

a=123
all:
	echo $(a)

执行结果:
在这里插入图片描述

a=123
all:
	@echo $(a)
	@#@的作用是取消命令执行的回显动作

执行结果:
在这里插入图片描述

3.5Makefile中变量的赋值

= 赋值

a=123
b=$(a)#在Makefile搜索a最后一次赋值的结果,将最后一次赋值的结果赋值给a
a=456

all:
	@echo $(a)
	@echo $(b)
	@#@的作用是取消命令执行的回显动作

执行结果:
在这里插入图片描述
:= 立即赋值

a=123
b:=$(a) #立即赋值,将a当前的结果赋值给b变量
a=456

all:
	@echo $(a)
	@echo $(b)
	@#@的作用是取消命令执行的回显动作

执行结果:
在这里插入图片描述
?= 询问赋值

a=123
b=456
b?=$(a) #询问b之前是否被赋值过,如果之前被赋值给,本次赋值不成立,否则本次赋值成立

all:
	
	@echo $(b)
	@#@的作用是取消命令执行的回显动作

执行结果:
在这里插入图片描述

a=123
#b=456
b?=$(a) #询问b之前是否被赋值过,如果之前被赋值给,本次赋值不成立,否则本次赋值成立

all:
	
	@echo $(b)
	@#@的作用是取消命令执行的回显动作

在这里插入图片描述
+= 附加赋值

a=123
b=hello
b+=$(a)#在b的后面附加上a

all:
	@echo $(b)
	@#@的作用是取消命令执行的回显动作

执行结果:
在这里插入图片描述
通过命令行赋值

a?=123
all:
	@echo $(a)
	@#@的作用是取消命令执行的回显动作

执行结果:
在这里插入图片描述

3.6在多文件编译中加上变量

(修改3.3Makefile文件,加入变量)

T?=text#可以通过询问赋值改变可执行程序的名字
TSAo:=text.o sub.o add.o
CC?=gcc#可以通过询问赋值不使用gcc进行编译
Cflag:= -c -o
$(T): $(TSAo)
	$(CC) $(TSAo) -o $(T)
text.o:text.c
	$(CC) text.c $(Cflag) text.o
sub.o:sub.c
	$(CC) sub.c $(Cflag) sub.o
add.o:add.c
	$(CC) add.c $(Cflag) add.o
clean:#伪命令 make clean不会生成clean的文件
	rm $(TSAo) $(T)

执行结果:
在这里插入图片描述

3.7Makefile中的特殊符号

$@:目标名

$<:第一个依赖

$^:所有的依赖

$*:取出扩展名的目标
以目录下创建text.c和add.c文件为例:

main.o:text.c add.c
	@echo $@
	@echo $*
	@echo $<
	@echo $^

执行结果:
在这里插入图片描述

3.8在3.6的基础上加入特殊字符

T?=text#可以通过询问赋值改变可执行程序的名字
TSAo:=text.o sub.o add.o
CC?=gcc#可以通过询问赋值不使用gcc进行编译
Cflag:= -c -o
$(T): $(TSAo)
	$(CC) $^ -o $@
text.o:text.c
	$(CC) $< $(Cflag) $@
sub.o:sub.c
	$(CC) $< $(Cflag) $@
add.o:add.c
	$(CC) $< $(Cflag) $@
clean:#伪命令 make clean不会生成clean的文件
	rm $(TSAo) $(T)

执行结果:
在这里插入图片描述

3.9Makefile中的通配符

%:Makefile中特有通配符
*:shell命令行的通配符
修改3.8中的Makefile文件,用上通配符

T?=text#可以通过询问赋值改变可执行程序的名字
TSAo:=text.o sub.o add.o
CC?=gcc#可以通过询问赋值不使用gcc进行编译
Cflag:= -c -o
$(T): $(TSAo)
	$(CC) $^ -o $@
%.o:%.c#这里的%是通配符,上面程序编译的时候text.o add.o sub.o都能通配到这句话
	$(CC) $< $(Cflag) $@
clean:#伪命令 make clean不会生成clean的文件
	rm $(TSAo) $(T)

执行结果:
在这里插入图片描述

4.Makefile中的函数

Makefile中有很多的函数,以下面两个为例进行讲解。
wildcard搜索命令,搜索当前目录下的所有的.c结尾的文件
patsubst替换的命令,将a变量保存的.c文件替换为所有以.o 结尾的文件

a:=$(wildcard ./ *.c)
b:=$(patsubst %.c,%.o, $(a))
all:
	@echo $(a)
	@echo $(b)

执行结果:
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Makefile文件的编写(实例详解) 的相关文章

  • 创建任务7.24

    创建任务 1 什么是任务 在裸机系统中 xff0c 系统的主体就是 main 函数里面顺序执行的无限循环 xff0c 这个无限循环里面 CPU 按照顺序完成各种事情 在多任务系统中 xff0c 我们根据功能的不同 xff0c 把整个系统分割
  • Linux驱动开发系列:DRM(第十部分)

    https www iotword com 7227 html 一 DRM简介 DRM xff0c 全称Direct Rending Manger 是目前Linux主流的图形显示框架 相比较传统的Framebuffer xff0c DRM更
  • 解决Ubuntu与Virtualbox虚拟机共享文件夹无权限的问题(保姆级)

    目录 使用这个命令后 xff0c 如果不能马上打开共享文件夹 xff0c 需要重启一下ubuntu系统 这样 xff0c 你共享的work文件夹就能在Ubuntu系统访问了 声明 CSDN 64 m0 637799558昵称更改为 64 孤
  • char类型与int类型的转换

    在c语言中 xff0c char类型与int类型可以转换 xff0c 如何转换我在此做一个粗略的总结 首先是char转换为int include lt stdio h gt int main char a a 61 110 int c 61
  • C语言中字符串大小与长度的区分

    字符串大小和字符串长度不同 xff1a 字符串大小指该字符串占用多少空间 字符串长度指该字符串的字符个数
  • 【字符串函数】strcat的使用及原理

    1 strcat函数的函数声明 char strcat char Destination const char Source 2 strcat函数的头文件 include lt string h gt 3 strcat函数的使用 strca
  • 【DRM】DRM Display Driver Guide

    https zhuanlan zhihu com p 534267979 目录 收起
  • TCP协议

    1 TCP协议的可靠传输 我们知道TCP协议的特点有 有连接 可靠传输 面向字节流 全双工 其中连接 面向字节流和全双工在 网络编程 该文章中详细说明了 而要深入了解TCP协议 了解可靠传输也是重中之重 可靠传输也是TCP协议的一大特点 那
  • c/c++程序运行不出结果?

    1 xff0c 条件语句未执行 在运行过程中 xff0c 用到if或while等条件语句 xff0c 条件之后的语句没有执行就结束了 xff0c 且输出变量也未初始化 xff0c 当然就输出不了任何东西了 xff1b 2 xff0c 变量未
  • 【解救ROS】关于ros机器人(小车)动态调试PID参数

    1 打开终端 xff0c 连接树莓派 ssh clbrobot 64 clbrobt 2 打开底盘节点 roslaunch clbrobot bringup launch 3 再打开一个终端 ssh clbrobot 64 clbrobt
  • 十进制转十六进制(C语言)

    首先要注意输入非负整数的范围 xff1a 这里用long表示 xff1b long 取值 2147483648 2147483647 include lt stdio h gt int main long n int i 61 0 j ch
  • C语言之数组的定义及其使用方法

    作者 xff1a 从未止步 博客主页 xff1a 从未止步的博客 专栏 xff1a 和我一起学C 语录 xff1a Every day is a second chance 行动是理想最高贵的表达 xff0c 给大家介绍一款超牛的斩获大厂o
  • python之常量的定义

    常量 xff1a 与C语言不同的是 xff0c python中并没有用来修饰常量的修饰符 xff0c 在python中可以通过自定义实现常量 xff0c 要求常量的标识符必须全是大写字母 xff0c 且该值不能被修改 举例 xff1a PI
  • C语言之根据摄氏温度求华氏温度

    求摄氏温度26 C对应的华氏温度 计算公式 xff1a f 61 9 c 5 43 32 xff0c 式中 xff1a c表示摄氏温度 xff0c f表示华氏温度 输入输出示例 xff1a celsius 61 26 fahr 61 78
  • python文件的操作和异常之异常

    异常 xff1a python使用称为异常的特殊类对象来管理程序执行期间发生的错误 xff0c 每当发生让python不知所措的错误时 xff0c 他都会创建一个异常的对象 如果你编写了处理该异常的代码 xff0c 程序将继续进行 xff0
  • Java---抽象类和接口

    抽象类 xff1a 抽象类的基本概念 xff1a 在面向对象的概念中 xff0c 所有的对象都是通过类来描述并创建的 xff0c 但是有一种特殊的类 xff0c 并不能用完整的信息来描述一个具体的对象 xff0c 这样的类就是抽象类 xff
  • 通过基于注解的声明式事务实现事务功能~

    编程式事务 xff1a 事务功能的相关操作全部通过自己编写代码来实现 xff1a span class token class name Connection span conn span class token operator 61 s
  • 《DRM 专栏》| 彻底入门 DRM 驱动

    https cloud tencent com developer article 2021477 前面的 DRM 应用程序系列文章中 xff0c 我们学习了如何使用 libdrm 接口编写 DRM 应用程序 本篇我们将进入一个全新的世界
  • 声明式事务的属性~

    说明 xff1a 本篇文章的代码是基于上篇文章之上的 xff0c 如有需要 xff0c 请移至这篇文章 声明式事务的属性 xff1a 只读 xff0c 超时 xff0c 回滚策略 xff1a 事务属性 xff1a 只读 对一个查询操作来说
  • 配置SpringMVC的前端控制器DispatcherServlet时,<url-pattern>中“/“和“/*“的区别

    span class token comment lt 表示所匹配的请求可以是login或 html或 js或 css方式的请求路径 xff0c 但是 不能匹配 jsp请求路径的请求 xff0c 因此就可以避免在访问jsp页面时 xff0c

随机推荐

  • 解决在idea中构建项目出现不能创建java类,只能创建文件的问题~

    注意 xff1a 一定要根据箭头的指向顺序进行 修改完成 xff0c 如下所示 xff1a
  • 解决在idea中构建项目时,出现的java:错误:不支持发行版本 5

    错误描述 xff0c 如下所示 xff1a 错误原因 xff1a idea中默认配置中有几个地方的jdk版本与实际不一致 解决办法 xff1a 第一步 xff1a 第二步 xff1a 第三步 xff1a 第四步 xff1a 第五步 xff1
  • 【C++】搭建HTTP服务器

    目录 项目介绍 网络协议栈介绍 协议分层 数据的封装与分用 HTTP相关知识介绍 HTTP的特点 URL格式 URI URL URN HTTP的协议格式 HTTP的请求方法 HTTP的状态码 HTTP常见的Header CGI机制介绍 CG
  • vscode 出现“未定义标识符cout”

    1 检查是否有 xff1a include lt iostream gt using namespace std 2 若有 xff0c 可以修改一下vscode的设置 xff1a 将C Cpp intelli Sense Engine的 D
  • FreeRtos.STM32f103c8t6调用vTaskDelay时间不准问题

    1 选择晶振要选择正确 2 内核选择的主频要和实际一致 define configCPU CLOCK HZ unsigned long 72000000 系统主频 define configTICK RATE HZ TickType t 1
  • FreeRtos外部中断使用

    首先是config文件里的宏 ARM Cortex M 架构自身允许最多 256 个不同的优先级 xff08 最多有 8 个 优先级位 xff0c 因此从 0 到 0xff 的优先级都是可能的 xff09 xff0c 但绝大多数使用 ARM
  • MPU-6050资源介绍

    介绍 作用 xff1a 测量三轴加速度和三轴角速度 测三轴加速度 xff1a 加速度计 测三轴角速度 xff1a 陀螺仪 加速度计具有静态稳定性 xff0c 动态不稳定性 陀螺仪具有静态不稳定性 xff0c 动态稳定性 需要互补滤波 xff
  • STM32硬件I2C

    以I2C2为例子 硬件I2C不需要我们手动去翻转电平 首先配置I2C xff1a 配置GPIO xff0c 配置复用功能I2C 配置复用开漏 xff0c 使能I2C I2C起始条件函数 64 param I2Cx where x can b
  • 最简单的 DRM 应用 & drm设备不工作

    https zhuanlan zhihu com p 341895843 https zhuanlan zhihu com p 75321245 编写最简单的 DRM 应用 主程序 xff1a int main int argc char
  • spi通信

    特点 常规四线通信方式 一根片选线 xff0c 一根时钟线 xff0c 两根数据线 xff1a 一根是主进从出线 xff0c 一根主出从入线 同步 xff0c 全双工 xff0c 通信方式 和谁通信就将谁的片选线拉低 xff0c 每增加一个
  • FreeRtos任务通信之消息队列

    入队阻塞 xff1a 往队列写数据时 xff0c 队列满时的阻塞 当阻塞结束时 xff0c 优先级最高的任务优先进入就绪态 xff0c 同 优先级时 xff0c 阻塞时间最长的进入就绪态 出队阻塞 xff1a 读队列时 xff0c 队列为空
  • STM32F103C8T6 ADC功能

    12位逐次逼近型ADC 1us转换时间 输入电压0 3 3v和转化范围0 2 12 1 xff08 0 4095 xff09 成线性关系 2个ADC资源 xff0c ADC1和ADC2 xff0c 10个外部通道 有两种转换单元组 xff1
  • stm32串口实验

    目录 xff08 一 xff09 STM32 串口简介 二 软件设计 xff08 三 xff09 效果 xff1a 1 实现功能 xff1a STM32 通过串口和上位机的对话 xff0c STM32 在收到上位机发过来的字符串后 xff0
  • 基于stm32的GPS解析数据

    目录 1 GPS模块 2 GPS发送的数据格式 3 软件设计 3 1配置好串口 3 2然后写串口中断函数 效果 1 GPS模块 2 GPS发送的数据格式 GPRMC lt 1 gt lt 2 gt lt 3 gt lt 4 gt lt 5
  • 大疆遥控控制M3508电机二(基于HAL库)

    接上一篇文章 xff0c 话不多说直接开始 一 打开我们创建的工程文件 xff0c 先就建立一个文件夹用来存放我们写的子文件 xff08 不建立也行 xff09 xff0c 然后建立pid h xff0c pid c存入我们建立的文件夹中
  • aruco_ros 在相机图像中显示的坐标轴姿态与TF发布的姿态不一致 解决方法

    aruco ros 在相机图像中显示的坐标轴姿态与TF发布的姿态不一致 解决方法 运行环境问题描述解决方案 运行环境 系统版本 xff1a Ubuntu 16 04 ROS版本 xff1a Kinetic 问题描述 在进行手眼标定过程中 x
  • 安装vscode的时候没有勾选快捷方式用vscode打开文件,如何用vscode快速打开文件或者文件夹

    1 需要在注册表里面添加内容可以实现 xff0c 下面有一种简单的方式来完成这个操作 2 需要在电脑桌面新建一个Open File With VS code reg 文件然后用打开文件 xff0c 将以下代码复制 Windows Regis
  • C语言学习笔记->const和define区别

    1 define 是预编译指令 xff0c 而const 是普通变量的定义 define定义的宏是在预处理阶段展开的 xff0c 而const定义的只读变量在编译运行中使用 2 const定义的是变量 xff0c 而define定义的是常量
  • 基于栈、寄存器的优缺点

    基于栈的优点 xff1a 对硬件的依赖不高 xff0c 跨平台性 缺点 xff1a 使用的指令集高基于寄存器的优点 xff1a 相对于栈来说 xff0c 寄存器的性能高 xff0c 使用的指令集少 Java代码执行流程 xff1a java
  • Makefile文件的编写(实例详解)

    1 什么是Makefile xff1f 一个工程中的源文件不计其数 xff0c 其按类型 功能 模块分别放在若干个目录中 xff0c Makefile定义了一系列的规则来指定哪些文件需要先编译 xff0c 哪些文件需要后编译 xff0c 哪