当前位置: 首页 > news >正文

Linux-Makefile

文章目录

    • Makefile
    • 概述
    • make主要解决两个问题
    • make工具的安装
    • Makefile文件命名规则
    • Makefile语法规则
    • Makefile基本规则三要素:
    • make命令格式
    • Makefile工作原理
    • Makefile示例
    • Makefile中的变量
    • 三个自动变量
    • 模式规则
    • Makefile中的两个函数
    • Makefile中的伪目标
    • 总结

Makefile

概述

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

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

make主要解决两个问题

1) 大量代码的关系维护*

大项目中源代码比较多,手工维护、编译时间长而且编译命令复杂,难以记忆及维护

把代码维护命令及编译命令写在makefile文件中,然后再用make工具解析此文件自动执行相应命令,可实现代码的合理编译

2) 减少重复编译时间

n 在改动其中一个文件的时候,能判断哪些文件被修改过,可以只对该文件进行重新编译,然后重新链接所有的目标文件,节省编译时间

make工具的安装

sudo apt install make

Makefile文件命名规则

makefile和Makefile都可以,推荐使用Makefile。

Makefile语法规则

一条规则:

目标:依赖文件列表

命令列表

Makefile基本规则三要素:

1)目标:

  • 通常是要产生的文件名称,目标可以是可执行文件或其它obj文件,也可是一个动作的名称

2)依赖文件:

  • 用来输入从而产生目标的文件
  • 一个目标通常有几个依赖文件(可以没有)

3)命令:

  • make执行的动作,一个规则可以含几个命令(可以没有)
  • 有多个命令时,每个命令占一行

make命令格式

make是一个命令工具,它解释Makefile 中的指令(应该说是规则)。

make命令格式:

make [ -f file ][ options ][ targets ]

1.[ -f file ]:

  • make默认在工作目录中寻找名为GNUmakefile、makefile、Makefile的文件作为makefile输入文件
  • -f 可以指定以上名字以外的文件作为makefile输入文件

l

2.[ options ]

  • -v: 显示make工具的版本信息
  • -w: 在处理makefile之前和之后显示工作路径
  • -C dir:读取makefile之前改变工作路径至dir目录(先进入指定的目录,在执行make)
  • -n:只打印要执行的命令但不执行
  • -s:执行但不显示执行的命令

3.[ targets ]:

  • 若使用make命令时没有指定目标,则make工具默认会实现makefile文件内的第一个目标,然后退出
  • 指定了make工具要实现的目标,目标可以是一个或多个(多个目标间用空格隔开)。

Makefile工作原理

若想生成目标, 检查规则中的依赖条件是否存在,如不存在,则寻找是否有规则用来 生成该依赖文件
在这里插入图片描述
检查规则中的目标是否需要更新,必须先检查它的所有依赖,依赖中有任一个被更新,则目标必须更新

在这里插入图片描述
总结:

  • 分析各个目标和依赖之间的关系

  • 根据依赖关系自底向上执行命令

  • 根据修改时间比目标新,确定更新

  • 如果目标不依赖任何条件,则执行对应命令,以示更新

Makefile示例

测试程序: test.c add.c sub.c mul.c div.c

test:test.c add.c sub.c mul.c div.cgcc test.c add.c sub.c mul.c div.c -o test

Makefile中的变量

在Makefile中使用变量有点类似于C语言中的宏定义,使用该变量相当于内容替换,使用变量可以使Makefile易于维护,修改内容变得简单变量定义及使用。

自定义变量

1)定义变量方法:

变量名=变量值

2)引用变量:

(变量名)或(变量名)或(变量名){变量名}

3)makefile的变量名:

  • makefile变量名可以以数字开头(不建议使用数字开头)
  • 变量是大小写敏感的
  • 变量一般都在makefile的头部定义
  • 变量几乎可在makefile的任何地方使用
  7 #Makefile中的两个函数8 # wildcard 获取当前目录指定类型的wenj9 # patsubst 将对应文件类型替换成另外一个类型 10 11 12 #定义变量13 #引用变量14 #$(变量名) 或者${变量名}15 16 # 自动变量17 #   $@  表示目标18 #   $<  表示第一个依赖19 #   $^  表示所有的依赖20 #21 22 TARGET:=test23 24 # 获取当前目录下所有的.c文件25 SRCS:=$(wildcard ./*.c)26 27 # 将SRCS中出现的所有.c文件修改为.o文件28 OBJS:=$(patsubst %.c, %.o, $(SRCS))29 30 $(TARGET):$(OBJS)31     gcc $^ -o $@    32 33 # 模式规则  表示所有.o 依赖所有.c 将.c生成.o34 %.o:%.c35     @gcc -c $< -o $@   36 37 #将clean 声明为伪目标:38 .PHONY:clean39 clean:40     #命令前面加- 表示这条命令执行失败后继续执行下面的命令41     -mkdir a/b/c42     rm -rf $(OBJS) $(TARGET)

除了使用用户自定义变量,makefile中也提供了一些变量(变量名大写)供用户直接使用,我们可以直接对其进行赋值。

CC = gcc #arm-linux-gcc

CPPFLAGS : C预处理的选项 如:-I

CFLAGS: C编译器的选项 -Wall -g -c

LDFLAGS : 链接器选项 -L -l

三个自动变量

  • $@: 表示规则中的目标
  • $<: 表示规则中的第一个条件
  • $^: 表示规则中的所有条件, 组成一个列表, 以空格隔开,如果这个列表中有重复的项则消除重复项。

注意:自动变量只能在规则的命令中中使用

#变量
OBJS=add.o sub.o mul.o div.o test.o add.o
TARGET=test
CC=gcc#$@: 表示目标
#$<: 表示第一个依赖
#$^: 表示所有的依赖$(TARGET):$(OBJS)#$(CC) $(OBJS) -o $(TARGET) $(CC) $^ -o $@echo $@echo $<echo $^add.o:add.c$(CC) -c $< -o $@ sub.o:sub.c$(CC) -c $< -o $@ mul.o:mul.c$(CC) -c $< -o $@ div.o:div.c$(CC) -c $< -o $@ test.o:test.c$(CC) -c $< -o $@clean:rm -rf $(OBJS) $(TARGET)

模式规则

模式规则示例:

%.o:%.c

$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@

Makefile第三个版本:

OBJS=test.o add.o sub.o mul.o div.o
TARGET=test
$(TARGET):$(OBJS)gcc $(OBJS) -o $(TARGET) #所有.o依赖所有.c 
%.o:%.cgcc -c $< -o $@

Makefile中的两个函数

makefile中的函数有很多,在这里给大家介绍两个最常用的。

  1. wildcard – 查找指定目录下的指定类型的文件

src = $(wildcard *.c) //找到当前目录下所有后缀为.c的文件,赋值给src

  1. patsubst – 匹配替换

obj = $(patsubst %.c,%.o, $(src)) //把src变量里所有后缀为.c的文件替换成.o

在makefile中所有的函数都是有返回值的。

Makefile第四个版本:

# 查找指定目录下的指定类型的文件
SRC=$(wildcard *.c)
#把src变量里所有后缀为.c的文件替换成.o
OBJS=$(patsubst %.c, %.o, $(SRC))TARGET=test$(TARGET):$(OBJS)gcc $(OBJS) -o $(TARGET) %.o:%.cgcc -c $< -o $@

Makefile中的伪目标

clean用途: 清除编译生成的中间.o文件和最终目标文件

make clean 如果当前目录下有同名clean文件,则不执行clean对应的命令,解决方案:

伪目标声明: .PHONY:clean

声明目标为伪目标之后,makefile将不会该判断目标是否存在或者该目标是否需要更新

clean命令中的特殊符号:

  • “-”此条命令出错,make也会继续执行后续的命令。如:“-rm main.o”
  • “@”不显示命令本身,只显示结果。如:“@echo clean done”
 # 获取当前目录下所有的.c文件
SRC=$(wildcard *.c)
# 将SRCS中出现的所有.c文件修改为.o文件
OBJS=$(patsubst %.c, %.o, $(SRC))TARGET:=test
$(TARGET):$(OBJS)gcc $(OBJS) -o $(TARGET) %.o:%.cgcc -c $< -o $@
.PHONY:clean
clean:rm -rf $(OBJS) $(TARGET)

总结

一条规则,两个函数,三个变量。

gcc obj/mul.o obj/main.o obj/add.o obj/div.o obj/sub.o -o bin/test
wuyou@itcast:~/share/wuyou/2day/homework$ tree
.
├── bin
│   └── test
├── inc
│   ├── add.h
│   ├── div.h
│   ├── mul.h
│   └── sub.h
├── Makefile
├── obj
│   ├── add.o
│   ├── div.o
│   ├── main.o
│   ├── mul.o
│   └── sub.o
└── src├── add.c├── div.c├── main.c├── mul.c└── sub.c1 2 3 SRCS:=$(wildcard ./src/*.c)4 5 #将src目录下的所有.c文件生成.o文件存放到obj目录6 OBJS:=$(patsubst ./src/%.c, ./obj/%.o,$(SRCS))7 #头文件目录8 INC:=./inc9 # 目标文件test放到bin目录下10 TARGET:=./bin/test11 12 $(TARGET):$(OBJS)13     gcc $^ -o $@14 15./obj/%.o:./src/%.c16 gcc -c -I $(INC) $^ -o $@17     18 19 .PHONY:clean20 clean:21     rm -rf $(OBJS) $(TARGET)22 
~                                                                                                    
~                                                                                                    
~                                                                                                    
~                                                                                                    
~            
http://www.dtcms.com/a/345084.html

相关文章:

  • 网络编程6(JVM)
  • 【Redis】哨兵模式和集群模式
  • 红帽认证升级华为openEuler证书活动!
  • 【学习记录】c完整线程池实现
  • 未来已来?AI 预测技术在气象、金融领域的应用现状与风险警示
  • MySQL视图详解:从基础概念到实战案例
  • 人工智能-python-深度学习-软件安装阶段
  • 第2章 cmd命令基础:执行动态链接库(rundll32)
  • 大视协作码垛机器人:定制圆形吸盘破解桶型码垛难题
  • HEVC(H.265)与HVC1的关系及区别
  • 【C初阶】数据在内存中的存储
  • 【LeetCode 热题 100】139. 单词拆分——(解法一)记忆化搜索
  • Vue 插槽(Slots)全解析1
  • 所做过的笔试真题
  • 阿里云RDS MySQL数据归档全攻略:方案选择指南
  • (LeetCode 面试经典 150 题) 124. 二叉树中的最大路径和 (深度优先搜索dfs)
  • 大麦盒子DM4036刷包推荐
  • 停车场道闸的常见形式
  • 【会议跟踪】Model-Based Systems Engineering (MBSE) in Practice 2025
  • 场景题:内存溢出 和 内存泄漏 有啥区别?
  • Python-UV
  • Android夜间模式切换及自定义夜间模式切换按钮实现快速适配夜间模式
  • LeetCode Hot 100 第一天
  • 《器件在EMC中的应用》---TVS在EMC中的应用
  • 中国大学MOOC--C语言第十一周结构类型
  • 开源版CRM客户关系管理系统源码包+搭建部署教程
  • 3D打印小批量低成本打印玩具工艺品模型-中科米堆CASAIM
  • MTK Linux DRM分析(十三)- Mediatek KMS实现mtk_drm_drv.c(Part.1)
  • 深入解析TCP/UDP协议与网络编程
  • LeetCode100-239滑动窗口最大值