make,Makefile简易教程

2023-05-16

一、概述

make是一个类UNIX系统下的编译命令,也可以理解为一个项目管理工具,通过make可以按照自己指定的编译命令编译整个项目,相当于将在命令行的编译命令按序执行,省去了反复键入编译命令的麻烦。除此之外,如果手动执行编译命令,不仅费时难以记忆,最重要的是每执行一次编译命令,项目中的整个文件都要重新编译,即使是未修改过的文件,这在大型项目中是难以忍受的。而make就提供了一种完美的解决方案,它将要执行的编译命令通过特定的语法组织到Makefile文件中,每次只要执行make命令,就可以完成整个项目的构建。

make执行时是根据文件的时间戳来选择要编译的文件。比如某个项目中你只是修改了其中一个文件,这个文件的时间戳就会晚于你所要生成的目标文件的时间戳,因为最终的目标文件肯定是最后生成的。如此,便不回去重新编译那些未修改的文件,省去了大量不必要的编译时间。所谓Makefile,就是将make要执行的编译命令写入到此文件中,这个文件也可以是其它名字,make时可以使用make -f filename来进行构建,当然,减少不必要的麻烦,还是统一命名为Makefile或者makefile为好。Makefile中指定了要执行的编译命令以及依赖的相关文件,执行make时,会在命令执行目录下寻找Makefile文件,根据该文件来构建整个项目。在类UNIX系统下的C/C++项目,make都是不可或缺的。

二、Makefile基础

一条规则的基本要素:

  • 目标:执行make要生成的目标文件
  • 依赖:用来生成目标文件的依赖文件
  • 命令:即如何用依赖文件生成目标文件的规则
# 一条简单的规则
# test为目标,test.c为依赖
# gcc一行即是命令,须以TAB键开头
test: test.c
	gcc test.c -o test 

在一条规则中,目标必须存在,依赖和命令两个中至少要存在一个。在具体的Makefile编写之前,先讲一下Makefile文件中的几个基础知识,后续编写实例会用到

一条规则:模式规则

模式规则:模式规则类似于普通规则。只是在模式规则中,目标名中需要包含有模式字符“%”,包含有模式字符“%”的目标被用来匹配一个文件名,“%”可以匹配任何非空字符串。规则的依赖文件中同样可以使用“%”,依赖文件中模式字符“%”的取值情况由目标中的“%”来决定。例如:对于模式规则“%.o : %.c”,它表示的含义是:所有的.o文件依赖于对应的.c文件。我们可以使用模式规则来定义隐含规则。

两个函数

通配符函数:$(wildcard <pattern>)

功能:返回pattern指定的文件

用法:

# 获取当前目录下的.c文件,并存储到变量SRC中
SRC = $(wildcard *.c)

字符串替换函数:$(patsubst <pattern> <replacement> <text>)

功能:匹配text中符合pattern的单词(单词以“空格”、“Tab”或“回车”“换行”分隔),匹配成功用replacement进行替换,返回被替换过后的字符串。这里,pattern可以包括通配符%,表示任意长度的字符串,如果replacement也包含%,那么replacement中的%将是pattern中那个%所代表的字符串

用法:

# 将SRC中的.c文件替换为同名的.o文件然后返回
SRC = $(wildcard *.c)
OBJ = $(patsubst %.c, %.o, $(SRC))
# 或者 OBJ= $($(SRC):%.c=%.o)

三个自动变量

$@ # 规则中的目标 
$< # 所有依赖
$^ # 第一个依赖

伪目标

除了以上几点,Makefile中还有一个比较重要的概念就是伪目标,我们通常再重新执行make之前, 会执行make clean命令,这个命令的作用就是删除一些规则指定的文件,如生成的中间文件以及可执行文件等,但是,如果Makefile所在文件下恰好存在一名为clean文件时,则不会执行相应的删除文件命令,解决办法就是将clean声明为伪目标,如此,不管当前文件夹是是否存在clean文件,执行make clean时都会执行相应的删除命令,其声明格式为:

.PHONY: clean

三、Makefile实例编写

有了以上基础知识,便可以编写一些基础的Makefile文件了,下面通过一个具体的实例来演示:

创建Makefile

所需文件:add.c,min.c,main.c

# 依赖.o文件生成可执行文件app
app: main.o add.o min.o
	gcc main.o add.o min.o -o app
# 依赖.c文件生成.o文件
main.o: main.c
	gcc -c main.c -o main.o
add.o: add.c
	gcc -c add.c -o add.o
min.o: min.c
	gcc -c min.c -o min.o
# clean目标用于删除中间文件
clean:
	rm -rf main.o add.o min.o

注意:Makefile文件按照从上到下的规则依次执行的,并且将文件的第一个目标作为终极目标,执行结果:

image-20210627003431690

使用自定义变量

# 声明自定义变量 obj
obj = main.o add.o min.o
# 使用 $ 取出自定义变量的值
app: $(obj)
	gcc main.o add.o min.o -o app
# 依赖.c文件生成.o文件
main.o: main.c
	gcc -c main.c -o main.o
add.o: add.c
	gcc -c add.c -o add.o
min.o: min.c
	gcc -c min.c -o min.o
# clean目标用于删除中间文件
clean:
	rm -rf $(obj)

使用自动变量

target = app
obj = main.o add.o min.o

$(target): $(obj)
	gcc $^ -o $@
# 依赖.c文件生成.o文件
%.o: %.c
	gcc -c $< -o $@
# clean目标用于删除中间文件
clean:
	rm -rf $(obj) $(target)

使用Makefile变量

target = app
obj = main.o add.o min.o

CC = gcc
# 编译时使用的参数,如 -c, -g, -Wall, -I 等
CPPFLAGS = 
CFLAGS = -c
# 链接库使用的选项 -L, -l
LDFLAGS = 

$(target): $(obj)
	$(CC) $^ -o $@

%.o: %.c
	$(CC) $(CFLAGS) $< -o $@

clean:
	rm -rf $(obj) $(target)

使用函数

src = $(wildcard ./*.c)
obj = $(patsubst ./%.c, ./%.o, $(src))
target = app

ALL:$(target)

CC = gcc 
CFLAGS = -c

$(target): $(obj)
	$(CC) $^ -o $@

%.o: %.c
	$(CC) $(CFLAGS) $< -o $@

clean:
	# 命令前加'-',执行出错时会继续执行
	-rm -rf $(obj) $(target)
# 声明伪目标
.PHONY: clean ALL

编译不同目录下文件

重新组织文件结构,源文件存放在src目录下,头文件在inc目录下,中间的.o文件存放在obj目录下,可执行文件放在bin目录下,如下图所示:

image-20210627014946600

src = $(wildcard ./src/*.c)
obj = $(patsubst ./src/%.c, ./obj/%.o, $(src))
inc_path = ./inc/
target = ./bin/app

ALL:$(target)

CC = gcc 
CFLAGS = -c 

$(target): $(obj)
	$(CC) $^ -o $@

./obj/%.o: ./src/%.c
	$(CC) $(CFLAGS) -I $(inc_path) $< -o $@

clean:
	-rm -rf $(obj) $(target)

.PHONY: clean ALL

执行结果如下:

image-20210627015913432

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

make,Makefile简易教程 的相关文章

  • Apollo 算法阅读之Public Road轨迹规划算法--路径规划(含源代码)

    本次博文主要介绍apollo 5 0版本内使用的轨迹规划算法 public road xff0c 该算法的核心思想是PV解耦 xff0c 即Path Velocity的解耦 xff0c 其主要包含两个过程 xff1a 1 路径规划 xff0
  • 交互式多模型 IMM的原理

    交互式多模型简单原理 交互式多模型 IMM xff08 Interacting Multiple Model xff09 控制算法的主体思想是基于贝叶斯理论而提出的模型间的自动识别与切换 xff1a 在任意跟踪时刻 xff0c 通过设置对应
  • Apollo算法阅读之基于Sqp的Referenceline全局参考路线优化(含源码)

    算法来源于Apollo代码 代码源地址 xff0c 通过序列优化思想 xff0c 建立无人驾驶车辆参考路径的平滑 xff0c 利用泰勒展开将曲率约束线性化表达 xff0c 目标函数中利用弹性带思想 xff0c 并尽可能缩短参考路径长度且保持
  • 离散点间曲率计算

    本文转自知乎计算离散点的曲率 xff08 附Python MATLAB代码 xff09 在很多学科中的很多计算任务中都需要用到曲线的曲率 xff08 或者曲率半径 xff09 xff0c numpy库里和matlab build in里都没
  • 关于Frenet坐标系内曲率约束

    本文摘自于apollo直播公开课 xff0c 因为车辆存在最小的转弯半径 xff0c 所以我们要对车辆运动学进行限制 由于转弯半径是基于笛卡尔坐标系的 xff0c 需要基于Frenet坐标系进行转换 假设 xff1a xff0c 车辆朝向与
  • caffe内CHECK_EQ等函数意义解释

    个人在学习caffe源码文件时遇到了CHECK EQ函数 xff0c 不理解什么含义 xff0c 经过上下文理解 xff0c 明白了其中含义 CHECK EQ x y lt lt 34 x 61 y 34 xff0c EQ即equation
  • 电路交换方式与分组交换方式计算题

    已知网络速率为1Mb S xff0c 对于每个用户来说 xff0c 有10 的时间是活跃的 xff0c 活跃时网速为100kb s 对于电路交换方式来说 xff0c 最多只能支持10位用户接入网络 由于1Mb 61 1000kb xff0c
  • Carla编译make launch过程中出现UE4_ROOT is not defined

    在编译carla过程中出现如下情况 xff1a BuildCarlaUE4 sh ERROR UE4 ROOT is not defined or points to a non existant directory please set
  • request 模块可以帮助我们发起http请求

    request 模块可以帮助我们发起http请求 步骤 xff1a 1 首先import 下 request 模块 2 然后看请求的方式 xff0c 选择对应的请求方法 3 接受返回的报文信息 有requests get requests
  • 自动提取论文公式方法

    需要的软件 MathType 7 Mathpix Snipping Tool 软件获取链接 xff1a 链接 xff1a https pan baidu com s 1Fz VGkgZJbZhlocL4y1AoA 提取码 xff1a ci0
  • 现代 CMake 简明教程--CMake 基础

    前言 用 CMake 来构建 C C 43 43 项目是业内的主流做法 最近 xff0c 我们的项目代码做了一些拆分和合并 xff1a 引入其他仓库代码 xff0c 并且将公共部分拆分以供多个仓库同时使用 为此 xff0c 就得修改项目中的
  • USB接线定义和链接摄像头

    原文链接 xff1a https www cnblogs com chinalantian articles 2131361 html 写本文的意义在于了解USB的接线定义和实现使用手机数据线读取摄像头图像 USB接口定义 颜色 一般的排列
  • C++小结 析构函数、函数后面接冒号 等等

    讲在前面 本小结有析构函数 C 43 43 函数后面接 xff1a 的含义 C 43 43 中public protected及private用法 条件运算符 fabs 和abs 区别 C 43 43 中的结构体内的函数 类中成员函数声明后
  • C++学习笔记:子类构造函数中冒号的使用 — 同时创建父类和子类对象

    C 43 43 中 xff0c 子类对象创建需要预先创建父类对象 xff0c 对象销毁顺序与此相反 假如父类构造函数只存在有参构造 xff0c 在子类对象实例化之前 xff0c 便需要创建一个父类对象 xff0c 在不存在默认无参构造情况下
  • C语言头文件详解

    1 include的作用 简单一句话 xff1a 在include的地方 xff0c 把头文件里的内容原封不动的复制到引用该头文件的地方 2 头文件的引用 头文件引用有两种形式 xff1a include lt stdio h gt 和 i
  • 字符数组进行复制需要加结束符‘\0’

    如想将str1数组内容复制到str2中 xff08 不用strcpy xff0c 如果按照以下格式复制 xff09 xff0c 需要加字符结束符 0 xff1b span class token macro property span cl
  • 学习Kafka

    1 Kafka是什么 xff1f 学习Kafka的目的 xff0c 为了解决高吞吐量项目的需求 xff0c Kafka号称大数据的杀手锏 xff0c 这款为大数据而生的消息中间件 xff0c 以其百亿级tps的吞吐量名声大噪 xff0c 迅
  • cmake命令之option使用案例

    option的命令形式如下 option lt variable gt 34 lt help text gt 34 value option简介 cmake中option起到编译开关的作用 xff0c CMakeLists txt中opti
  • docker学习

    现代软件开发的一大目的就是隔离 xff0c 应用程序在运行时相互独立互不干扰 xff0c 这种隔离实现起来是很不容易的 xff0c 其中一种解决方案就是上面提到的虚拟机技术 xff0c 通过将应用程序部署在不同的虚拟机中从而实现隔离 但是虚
  • 3.编写CMakeLists文件

    本章将介绍为您的软件编写有效的 CMakeLists 文件的基础知识 它将涵盖处理大多数项目所需的基本命令和问题 虽然 CMake 可以处理极其复杂的项目 xff0c 但对于大多数项目 xff0c 你会发现本章的内容会告诉你所有你需要知道的

随机推荐

  • boost库简介

    欢迎来到boost org Boost 提供免费的经过同行评审的可移植 C 43 43 源库 我们强调与 C 43 43 标准库配合良好的库 Boost 库旨在广泛使用 xff0c 并可用于广泛的应用程序 Boost 许可证鼓励所有用户以最
  • 解决mavros源码安装过程中wstool update -t src -j4报错(网络限制)问题

    继上一篇解决了mavlink安装的网络问题后 xff0c 没想到这个指令更新也需要链接到github 而直接执行时 xff0c 报错 xff1a span class token punctuation span mavlink span
  • QT事件详解

    一 简介 在Qt中 xff0c 事件作为一个对象 xff0c 继承自 QEvent 类 xff0c 常见的有键盘事件 QKeyEvent 鼠标事件 QMouseEvent 和定时器事件 QTimerEvent 等 xff0c 与 QEven
  • QT事件系统之二:鼠标事件和滚轮事件

    一 QMouseEvent的详细描述 QMouseEvent 类用来表示一个鼠标事件 xff0c 当在窗口部件中按下鼠标 释放鼠标和移动鼠标指针时 xff0c 都会产生鼠标事件 QMouseEvent 利用 QMouseEvent 类可以获
  • Qt事件系统之三:键盘事件

    QKeyEvent类用来描述一个键盘事件 当键盘按键被按下或者被释放时 xff0c 键盘事件便会被发送给拥有键盘输人焦点的部件 QKeyEvent的key 函数可以获取具体的按键 xff0c 对于Qt中给定的所有按键 xff0c 可以在帮助
  • 第一个自己写的程序

    22年8月份花了三周时间快速过了一遍某站一位大佬的视频 xff0c 前几天刷朋友圈时偶然看见一位道友写了个矩阵乘积的计算器 xff0c 瞬间给了我灵感 xff0c 直接开始操作 理想很丰满 xff0c 现实很扯淡 xff0c 刚开始写了个4
  • CEF学习质料

    目录 一 编译CEF3里的lib xff1a 1 下载CEF3 http opensource spotify com cefbuilds index html 2 下载CMake xff0c 运行CMake GUI exe 3 CMake
  • 【无标题】

    5 1 内存模型基础 这里从两方面来讲内存模型 xff1a 一方面是基本结构 xff0c 这与事务在内存中是怎样布局的有关 xff1b 另一方面就是并发 对于并发基本结构很重要 xff0c 特别是在低层原子操作 所以我将会从基本结构讲起 C
  • C++`中的原子操作和原子类型

    5 2 C 43 43 中的原子操作和原子类型 原子操作 是个不可分割的操作 在系统的所有线程中 xff0c 你是不可能观察到原子操作完成了一半这种情况的 xff1b 它要么就是做了 xff0c 要么就是没做 xff0c 只有这两种可能 如
  • 编写一个使用锁的线程安全查询表

    6 3 基于锁设计更加复杂的数据结构 栈和队列都很简单 xff1a 接口相对固定 xff0c 并且它们应用于比较特殊的情况 并不是所有数据结构都像它们一样简单 xff1b 大多数数据结构支持更加多样化的操作 原则上 xff0c 这将增大并行
  • __declspec(dllexport)和__declspec(dllimport)以及QT中public: static struct QMetaObject const xxx:staticMe

    假设你的头文件如下 xff1a span class token macro property span class token directive hash span span class token directive keyword
  • /MD 与 /MT、/MTD与/MDD的区别

    VS在 属性页的 C C 43 43 gt Code Generation gt Runtime Library 一项中总共有四个选项 MD 与 MT MTD与 MDD xff0c 它们分别有什么区别 xff1f 1 MD 与 MT 用于R
  • C++多线程案列

    C 43 43 多线程案列 话不多说 xff0c 直接上代码 xff1a span class token comment CMakeList txt ThreadDemo1 的 CMake 项目 xff0c 在此处包括源代码并定义 spa
  • 右值引用、移动语义、完美转发

    右值引用 移动语义 完美转发 左值 右值 xff1a 在c 43 43 中 xff0c 所有的值不是左值 xff0c 就是右值 有名字的对象都是左值 xff0c 右值没有名字 还有一个可以区分左值和右值的方法 xff1a 看能不能对表达式取
  • Deep Meta Learning for Real-Time Target-Aware Visual Tracking 论文阅读

    这篇文章是韩国的一个组做的 一直没中 直到19年中了ICCV xff0c 据说是第一篇将元学习引入目标跟踪的文章 xff0c 用的架构是siamese网络的架构 xff0c 但是在模型在线更新的时候使用了meta learning的思想 M
  • 单链表倒序

    单链表倒序 题目来源 牛客网 题目描述 输入一个链表 xff0c 按链表从尾到头的顺序返回一个ArrayList span class token keyword public span span class token keyword c
  • VS2019中编写C语言

    建立C 43 43 控制台程序 xff0c 将main函数所在的文件后缀名从cpp改成c xff0c 然后复制下列模板即可 xff1b 模板如下 xff1a dsa zju cpp 此文件包含 34 main 34 函数 程序执行将在此处开
  • CMake编译工程/第一个CMakeLists.txt(最详细案例演示)

    目录 在 linux 平台下使用 CMake 构建C C 43 43 工程的流程 当前项目目录结构 最小CMake工程 进入文件夹5 3 1 xff0c VScode打开项目文件5 3 1 在项目5 3 1顶层目录中 xff0c New F
  • 数据分析岗-机器学习相关知识

    1 解释共线性 我们进行回归分析需要了解每个自变量对因变量的单纯效应 xff0c 多重共线性就是说自变量间存在某种函数关系 xff0c 如果你的两个自变量间 xff08 X1和X2 xff09 存在函数关系 xff0c 那么X1改变一个单位
  • make,Makefile简易教程

    一 概述 make是一个类UNIX系统下的编译命令 xff0c 也可以理解为一个项目管理工具 xff0c 通过make可以按照自己指定的编译命令编译整个项目 xff0c 相当于将在命令行的编译命令按序执行 xff0c 省去了反复键入编译命令