Linux 之 MakeFile

MakeFile

  • 前言
  • MakeFile基本介绍
    • MakeFile介绍
    • MakeFile文件命名
    • Makefile编写规则
    • MakeFile的执行步骤
  • MakeFile
    • makefile组成元素
      • makefile显示规则
      • makefile隐晦规则
        • 伪目标(标签与文件冲突问题)
      • makefile变量定义
        • makefile中的运算符和特殊变量
      • makefile文件指示
      • makefile注释
    • makefile条件判断
      • makefile条件判断格式
      • makefile条件判断的三种形式
      • makefile条件判断总结
    • makefile函数
      • wildcard  匹配当前目录文件
      • notdir  取文件名
      • patsubst  模式替换
      • filter-out  反过滤
  • MakeFile多文件、多文件夹具体例子

前言

  初学者在Linux中编写代码的时候,都会了解到需要使用 gcc 1.c -o app 把 .c源文件 变成可执行文件。但是如果是一个由上百个.c文件构成的项目,我们还得一个个去变成可执行文件么?
  因此工程管理器应运而生。工程管理器是一个能够管理较多的文件,并且能根据文件时间自动检测出更新过的文件而减少编译的工作量,同时通过读入 Makefile 文件来执行大量的编译工作。

MakeFile基本介绍

MakeFile介绍

  Makefile是一种用于自动化构建和编译软件项目的工具。它通常用于管理大型项目中的源代码文件,以及定义项目的编译、链接和其他构建过程。它通常是使用文本编辑器编写的,其语法基于一种称为"make"的构建工具的规范。Makefile的语法相对简单,但可以非常灵活,可以根据项目的需要进行定制和扩展。
  总的来说,Makefile是工程管理器在软件项目中非常重要的一部分,它可以帮助开发人员自动化构建过程,提高开发效率,减少错误和提高可维护性。

MakeFile文件命名

  默认的情况下,make 命令会在当前目录下按顺序找寻文件名为“GNUmakefile”、“makefile”、“Makefile”的文件。在这三个文件名中,最好使用“Makefile”这个文件名,因为,这个文件名第一个字符为大写,这样有一种显目的感觉。最好不要用“GNUmakefile”,这个文件是 GNU 的 make 识别的。有另外一些 make 只对全小写的“makefile”文件名敏感,但是基本上来说,大多数的 make 都支持“makefile”和“Makefile”这两种默认文件名。
  寻找顺序:“GNUmakefile” > “makefile” > “Makefile(推荐)”
  但是你可以指定执行某一个的MakeFile,使用make的 “-f” 和 “–file” 参数即可。比如:make -f Make.Linux 或 make --file Make.AIX

Makefile编写规则

Target(目标) : prerequisites(依赖)
	Command(命令)

eg;
app:main.o fun.o
	gcc main.o fun.o -o app
main.o:main.c
	gcc -c main.c -o main.o -I ./inc
fun.o:fun.c
	gcc -c fun.c -o fun.o -I ./inc

#1.第一行即“app”为终极目标,下面的所有目标都是为了生成这个终极目标而编写
#2.第一行的规则没有先后顺序
#3.当时间不对时,需要将时间调整正确之后才能使用 make 命令。
#4.makefile根据时间信息判断是否执行编译(目标文件与最终生成文件进行时间对比)。
#5.每个规则中的目标,都可以是一个文件,也可以是一个标签,标签作为第一个会一直执行。标签不是实际的文件;
#6.每一个规则中的目标,不一定要有依赖。
#7.每一个规则,不一定非得有命令列表。
#8.每个规则中可以有多条命令规则,但是前面都得需要加 Tab 键。

MakeFile的执行步骤

1 ) 读入所有的 Makefile 文件。
2 ) 读入 include 的 Makefile 文件。
3 ) 初始化文件中的变量。
4 ) 推导隐晦规则,并分析所有规则。
5 ) 为所有的目标文件创建依赖关系链。
6 ) 根据依赖关系,决定哪些目标要重新生成。
7 ) 执行生成命令。
  
注:①-⑤步为第一个阶段,⑥ -⑦为第二个阶段。第一个阶段中,如果定义的变量被使用了,那么 make 会把其展开在使用的位置。但 make 并不会马上展开,make 使用的是拖延战术,如果变量出现在依赖关系的规则中,仅当这条依赖将要使用了,变量才会在其内部展开。

MakeFile

makefile组成元素

  Makefile 里主要包含了五个东西:显式规则、隐晦规则、变量定义、文件指示和注释。

makefile显示规则

  显式规则说明了如何生成一个或多的的目标文件。这是由 Makefile 的编写人员明显指出的。包括要生成的文件,文件的依赖文件,生成的命令。

makefile隐晦规则

  使用模式规则来定义一个隐含规则。一个模式规则就好像一个一般的规则,只是在规则中,目标的定义需要有“%”字符。“%”的表示一个或多个任意字符。在依赖目标中同样可以使用“%”,只是依赖目标中的“%”的取值,取决于其目标。
  有一点需要注意的是,“%”的展开发生在变量和函数的展开之后,变量和函数的展开发生在 make 载入 Makefile 时,而模式规则中的“%”则发生在运行时。

app:main.o fun.o
	gcc main.o fun.o -o app
%.o:%.c
	gcc -c  $< -o $@  -I ./inc
伪目标(标签与文件冲突问题)

  当同级目录下具有标签名一致文件时使用伪目标。为目标不是一个真正的目标,仅仅是为了执行其所有规则下面的命令,不应该让 make 来判断他是否存在,或者是否应该被生成。
规则:.PHONY:后面声明是 伪目标

clean:
	rm *.o app
#这样在执行make clean命令的时候就不会运行名为clean的makefile文件而发生冲突

makefile变量定义

  makefile中声明变量需要赋予初值,在使用的时候要在前面加上 $ 符号(最好同时使用 () 或者 {} 将变量名包裹)。如果你要是用 $ 字符,则需要用 $$ 来替代。变量可以使用在许多地方,如规则中的“目标”、“依赖”、“命令”以及新的变量中。
  Makefile 中定义的变量切皆为字符串。
eg: 单字符: $A

   多字符:$(AA) 或者 ${AA}

makefile中的运算符和特殊变量
#符号 =
#功能 延迟展开赋值
#例子 
B=$A
A=10
all:
	echo $B   #输出为10

#符号 :=
#功能 立即展开赋值
#例子 
B:=$A
A=10
all:
	echo $B    #无输出,因为B为空

#符号 ?=
#功能 条件赋值(经常出现在make传参)
#例子 
A=30
A?=10
all:
	echo $A    #输出为30

#符号 +=
#功能 追加赋值
#例子
A=30
A+=10
all:
	echo $A    #输出为30 10,因为是字符串

#符号 $@
#功能 代替目标名

#符号 $^
#功能 代替依赖

#符号 $<
#功能 依赖集合中的第一个

#符号 @
#功能 make 在执行命令前不要将命令显示在标准输出上

makefile文件指示

  在 Makefile 使用 include 关键字可以把别的 Makefile 包含进来,这很像 C 语言的#include,被包含的文件会原模原样的放在当前文件的包含位置。include 的语法是:
  include ***.mk
  如果没有找到或是不能读取文件,make会产生警告并且继续载入其他文件,当完成 makefile的读取,make 会再次寻找这些文件,如果还是不行,make 才会出现一条致命信息。你可以在 include 前加一个减号“-”,例如 -include filename 来让 make 不理那些文件。

makefile注释

  上面的例子中已经提及了,即  # + 文本

makefile条件判断

makefile条件判断格式

#语法:
ifxxx (arg1,arg2)
	#do true
else
	#do false
endif
其他形式
ifxxx "arg1" "arg2"
ifxxx 'arg1' 'arg2'
ifxxx "arg1" 'arg2'
ifxxx 'arg1' "arg2"

在这里插入图片描述
判断语句前面的空格不能是 tab 键。

ifxxx功能
ifeq判断参数是否相等,相等为 true,否则为 false
ifneq判断参数是否不相等,不相等为 true,否则为 false
ifdef判断变量是否有值,有值则为 ture,否则为 false
ifndef判断变量是否没有值,没有值则为 ture,否则为 false

makefile条件判断的三种形式

#判断语句不在规则中
B=30
C=20
ifeq ($B,$C)
	A=10
else
	A=20
endif
all:
	echo $A
	
#标签在判断语句中
B=30
C=30
ifeq ($B,$C)
all:
	echo $B
else
all:
	echo $C
endif

#判断语句在命令行中
B=30
C=20
all:
ifeq ($B,$C)
	echo $B
else
	echo $C
endif

makefile条件判断总结

1 ) 条件判断语句根据条件的值来决定 make 的执行。
2 ) 条件判断可以比较两个不同变量或者变量和常量。
3 ) 条件判断在预处理阶段有效,在执行阶段无效。
4 ) 条件判断不能控制规则中命令的执行过程。
5 ) 条件判断语句之前可以有空格,但是不能有 Tab 字符。
6 ) 在条件判断语句中不要使用自动变量(@,$@,$^ , $<)。
7 ) 一条完整的条件语句必须位于同一个 makefile 中。

makefile函数

wildcard  匹配当前目录文件

例子:
  src=$(wildcard ./src/*.c)
返回值:目录下的所有 .c 文件(内容包含路径)

notdir  取文件名

例子:
  allFileName==$(notdir $(src))
返回值:每一个文件的非目录部分(即文件名)

patsubst  模式替换

例子:
  file=$(patsubst %.h,%.o,$(allFileName))
返回值:把所有的文件名后缀从 .h 换成了 .o

filter-out  反过滤

例子:
  sources=file1.c file2.c file3.h file4.h
  src=$(filter-out %.h, $(sources))
返回值:过滤掉所有的 .h 文件

MakeFile多文件、多文件夹具体例子

在这里插入图片描述
目标:
  从 inc 文件夹中取出 .h 头文件 与 src1、src2 文件夹中的 .c 源文件一起参与编译,并且将 .o 文件生成到 obj 目录下。最后在当前目录下生成可执行文件 app 。在后续编译中可以自行选择过滤 .o 文件或者 .c 文件。

INC=./inc/
obj=./obj/
CC=gcc
mode="1"
m="1"
src1c=$(wildcard ./src1/*.c)
src2c=$(wildcard ./src2/*.c)

obj1=$(patsubst ./src1/%.c,./obj/%.o,$(src1c))
obj2=$(patsubst ./src2/%.c,./obj/%.o,$(src2c))
file1=$(filter-out ./obj/$(nf),$(obj1))
file2=$(filter-out ./obj/$(nf),$(obj2))

file3=$(filter-out ./src1/$(nf),$(src1c))
file4=$(filter-out ./src2/$(nf),$(src2c))
obj3=$(patsubst ./src1/%.c,./obj/%.o,$(file3))
obj4=$(patsubst ./src2/%.c,./obj/%.o,$(file4))

#如果m=1代表过滤.o 其他代表过滤.c

ifeq ($(m),$(mode))
app:$(file1) $(file2)
	$(CC) $^ -o $@
else
app:$(obj3) $(obj4)
	$(CC) $^ -o $@
endif

$(obj)%.o:./src1/%.c
	$(CC) -c $^ -o $@ -I $(INC)
$(obj)%.o:./src2/%.c
	$(CC) -c $^ -o $@ -I $(INC)
	
clean:
	rm ./obj/*.o
.PHONY:clean

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【刷题篇】动态规划(四)

文章目录 1、珠宝的最高价值2、下降路径最小和3、最小路径和4、地下城游戏5、按摩师6、打家劫舍|| 1、珠宝的最高价值 现有一个记作二维矩阵 frame 的珠宝架&#xff0c;其中 frame[i][j] 为该位置珠宝的价值。拿取珠宝的规则为&#xff1a; 只能从架子的左上角开始拿珠宝 每次…

数据结构 | 带头双向循环链表专题

数据结构 | 带头双向循环链表专题 前言 前面我们学了单链表&#xff0c;我们这次来看一个专题带头的双向循环链表~~ 文章目录 数据结构 | 带头双向循环链表专题前言带头双向循环链表的结构实现双向链表头文件的定义哨兵位初始化创建节点尾插尾删头插头删打印查找指定位置前插入…

CentOS指令学习

目录 一、常用命令 1、ls 2、cd_pwd 3、touch_mkdir_rmdir_rm 4、cp_mv 5、whereis_which_PATH 6、find 7、grep 8、man_help 9、关机与重启 二、压缩解压 1、zip_unzip 2、gzip_gunzip 3、tar 三、其他指令 1、查看用户登录信息 2、磁盘使用情况 3、查看文件…

Java15新增特性

前言 前面的文章&#xff0c;我们对Java9、Java10、Java11、Java12 、Java13、Java14 的特性进行了介绍&#xff0c;对应的文章如下 Java9新增特性 Java10新增特性 Java11新增特性 Java12新增特性 Java13新增特性 Java14新增特性 今天我们来一起看一下Java15这个版本的一些重要…

74HC165 并入串出

/******************************************************** 程序名&#xff1a;main.C 版 本&#xff1a;Ver1.0 芯 片&#xff1a;AT89C51或STC89C51 晶 体&#xff1a;片外12MHz 编 程: Joey 日 期&#xff1a;2023-11-13 描 述&#xff1a;通过 74HC165 对 16 按键…

android 10车载桌面ActivityView触摸事件源码详解分析

hi&#xff0c;粉丝朋友们&#xff1a; 背景 大家好&#xff01;近来居然有好几个粉丝朋友居然问到了一个虚拟屏幕触摸相关的问题&#xff0c;还有老版本android 10上面有个车载桌面使用的ActivityView可以正常触摸的问题。 其实这个ActivityView在最新的版本已经没有了&…

视觉大模型DINOv2:自我监督学习的新领域

1 DINOv2 1.1 DINOv2特点 前段时间&#xff0c;Meta AI 高调发布了 Segment Anything&#xff08;SAM&#xff09;&#xff0c;SAM 以交互式方式快速生成 Mask&#xff0c;并可以对从未训练过的图片进行精准分割&#xff0c;可以根据文字提示或使用者点击进而圈出图像中的特定…

基于springboot实现结合疫情情况的婚恋系统【项目源码】

基于springboot实现结合疫情情况的婚恋系统演示 SpringBoot框架 SpringBoot是一个全新开源的轻量级框架。基于Spring4.0设计&#xff0c;其不仅继承了Spring框架原来有的优秀特性&#xff0c;而且还通过简化配置文件来进一步简化了Spring应用的整个搭建以及开发过程。另外在原…

Resources接口和实现类

Spring Resources概述 Java的标准iava.net.URL类和各种URL前缀的标准处理程序无法满足所有对low-evel资源的访问&#xff0c;比如: 没有标准化的URL实现可用于访问需要从类路径或相对于 ServletContext 获取的资源。并且缺少某些Spring所需要的功能&#xff0c;例如检测某资源…

RK3399平台开发系列讲解(应用篇)文件属性 stat 函数

🚀返回专栏总目录 文章目录 一、struct stat 结构体二、st_mode 变量三、struct timespec 结构体沉淀、分享、成长,让自己和他人都能有所收获!😄 📢Linux 下可以使用 stat 命令查看文件的属性,其实这个命令内部就是通过调用 stat()函数来获取文件属性的,stat 函数是 …

基于XML的声明式事务

场景模拟 参考基于注解的声明式事务 修改Spring的配置文件 将Spring配置文件中去掉tx:annotation-driven标签&#xff0c;并添加配置&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org…

基于springboot实现沁园健身房预约管理系统【项目源码】计算机毕业设计

基于springboot实现沁园健身房预约管理系统演示 B/S架构 B/S结构是目前使用最多的结构模式&#xff0c;它可以使得系统的开发更加的简单&#xff0c;好操作&#xff0c;而且还可以对其进行维护。使用该结构时只需要在计算机中安装数据库&#xff0c;和一些很常用的浏览器就可以…

CSS特效007:绘制3D文字,类似PS效果

css实战中&#xff0c;怎么绘制3D文字呢&#xff1f; 实际上理论很简单&#xff0c;使用text-shadow&#xff0c;根据需要调整阴影的颜色、大小、偏移量等参数&#xff0c;以达到你想要的立体效果。下面是一个简单的示例。关键点就是知道如何设置text-shadow。 效果图 源代码 …

【debug】解决Kali虚拟机开机黑屏,左上角光标一直闪动无法开机问题

做网络攻防实验时&#xff0c;突然Kali无法打开&#xff0c;遇到这个问题。。。。。。 遇到的问题 突然kali虚拟机变成如下黑屏&#xff0c;无法开机&#xff0c;左上角光标闪动&#xff0c;重启无效。 解决办法 在上图界面&#xff0c;按Ctrl F3&#xff08;不同电脑快捷键…

C++进阶篇4---番外-红黑树

一、红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或 Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制&#xff0c;红黑树确保没有一条路 径会比其他路径长出俩倍&#xff0…

[笔记]深入解析Windows操作系统《番外》windows关键进程解释

文章目录 前言一、Linux起源与发展二、什么是shell1.什么是Shell 总结 前言 一、Linux起源与发展 二、什么是shell 1.什么是Shell 总结 以上就是今天要讲的内容&#xff0c;本文仅仅简单介绍了linux命令行的使用。 参考&#xff1a; shells 概念 centOS7中的几个Ctrl组合…

Spring Cloud学习(七)【Docker 容器】

文章目录 初识 DockerDocker 介绍Docker与虚拟机Docker架构安装 Docker Docker 基本操作镜像相关命令容器相关命令数据卷 Dockerfile 自定义镜像镜像结构Dockerfile DockerComposeDockerCompose介绍安装DockerCompose Docker镜像仓库常见镜像仓库服务私有镜像仓库 初识 Docker …

【机器学习】八、规则学习

知识图谱与基本概念 基本概念 规则学习定义&#xff1a;从训练数据中学习出一组能用于对未见示例进行判别的规则。 规则定义&#xff1a;规则一般是&#xff1a;语义明确、能描述数据分布所隐含的客观规律或领域概念。 逻辑规则定义&#xff1a;⊕←?1⋀?2⋀?3…⋀??⊕…

Redis 5大数据类型命令解读

目录 Redis key的命令 1、redis字符串&#xff08;String&#xff09; 2、redis列表(List) 3、redis哈希表(Hash) 4、redis集合(Set) 5、redis有序集合(ZSet) Redis 命令网站&#xff1a;redis中文文档 Redis key的命令 命令说明示例keys *查看当前库所有的keykeys *…

Please No More Sigma(构造矩阵)

Please No More Sigma 给f(n)定义如下&#xff1a; f(n)1 n1,2; f(n)f(n-1)f(n-2) n>2; 给定n&#xff0c;求下式模1e97后的值 Input 第一行一个数字T&#xff0c;表示样例数 以下有T行&#xff0c;每行一个数&#xff0c;表示n。 保证T<100&#xff0c;n<100000…