Linux 之 MakeFile

news2024/11/16 7:55:08

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

海康Visionmaster-Qt+VS 二次开发环境如何配置?

1 新建 Qt 工程&#xff0c;添加 Qt 模块 Core、GUI、Active Qt 和 Container Widgets 2 拷贝 DLL:VM\VisionMaster4.0.0\Development\V4.0.0\ComControl\bin\x64 下的所有拷贝到项目工程输出目录下&#xff0c;如下图所示&#xff0c;项目的输出路径是 Dll 文件夹。 3 第一…

2023/11/12总结

踩坑记录&#xff1a; org.springframework.jdbc.BadSqlGrammarException: ### Error querying database. Cause: java.sql.SQLSyntaxErrorException: Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column elm.flavors.id which is …

sqli-labs关卡16(基于post提交的双引号加括号闭合的布尔盲注)通关思路

文章目录 前言一、回顾上一关知识点二、靶场第十六关通关思路1、判断注入点2、猜数据库长度3、猜数据库名字4、猜表名长度5、猜表名名字6、猜列名长度7、猜列名名字8、猜数据长度9、猜数据名字 总结 前言 此文章只用于学习和反思巩固sql注入知识&#xff0c;禁止用于做非法攻击…

消息中心常见解决方案分享

解决方案 1、问题2、设计3、流程 看了大部分的消息中心解决方案&#xff0c;发现大家的中心思想都大差不差&#xff0c;区别基本都是在符合自身业务场景的做了一些定制化处理。本文为我对消息中心基本骨架的知识梳理&#xff0c;亦在帮助大家对消息中心设计有一个基本的理解。 …

Python---字典---dict

1、为什么需要字典 如果想要存储一个人的信息&#xff0c;姓名&#xff1a;Tom&#xff0c;年龄&#xff1a;20周岁&#xff0c;性别&#xff1a;男&#xff0c;如何快速存储。 person [Tom, 20, 男] 在日常生活中&#xff0c;姓名、年龄以及性别同属于一个人的基本特征。 但…

RT-Thread:嵌入式实时操作系统的设计与应用

RT-Thread&#xff08;Real-Time Thread&#xff09;是一个开源的嵌入式实时操作系统&#xff0c;其设计和应用在嵌入式领域具有重要意义。本文将从RT-Thread的设计理念、核心特性&#xff0c;以及在嵌入式系统中的应用等方面进行探讨&#xff0c;对其进行全面的介绍。 首先&a…

STL简介+浅浅了解string——“C++”

各位CSDN的uu们好呀&#xff0c;终于到小雅兰的STL的学习了&#xff0c;下面&#xff0c;让我们进入CSTL的世界吧&#xff01;&#xff01;&#xff01; 1. 什么是STL 2. STL的版本 3. STL的六大组件 4. STL的重要性 5. 如何学习STL 6.STL的缺陷 7.为什么要学习string类 …

Spring Data JPA 实现集成实体对象数据库的创建、修改时间字段自动更新

JPA提供了一种事件监听器的机制&#xff0c;用于SQL审计&#xff0c;通过监听器我们可以很快速地去自动更新创建时间、修改时间&#xff0c;主要步骤如下&#xff1a; 一、创建基础实体&#xff0c;包含了创建和修改时间&#xff0c;然后让其他真正的实体继承该实体&#xff0…

云原生微服务架构及实现技术

云原生是一种技术理念和架构方法&#xff0c;它充分利用云计算的优势&#xff0c;将应用程序和基础设施进行优化&#xff0c;以适应云环境的特性。云原生的设计原则主要包括弹性、韧性、安全性、可观测性、灰度等&#xff0c;旨在让企业在云环境中实现轻量、敏捷、高度自动化的…

Spring基础——初探

Spring是一个开源的Java应用程序开发框架&#xff0c;它提供了一个综合的编程和配置模型&#xff0c;用于构建现代化的企业级应用程序。Spring的目标是简化Java开发&#xff0c;并提供了许多功能和特性&#xff0c;以提供开发效率、降低开发复杂性。 特别 主要功能 IoC容器 …

JPA Buddy快速创建update、find、count、delete、exists方法

JPA Buddy快速创建update、find、count、delete、exists方法&#xff0c;JPA默认提供的CrudRepository\JpaRepository提供的方法比较少&#xff0c;一般我们会手写一些方法&#xff0c;这里我们选择通过JPA Buddy快速生成&#xff0c;之前文章中讲到了JPA Buddy原本是IDEA收费插…

数据结构与算法【数组】Java实现

数组是一组元素组成的数据结构&#xff0c;元素类型必须相同&#xff0c;其次&#xff0c;数组内元素是连续存储的&#xff0c;因此数组中元素地址可以通过索引计算出来。 空间占用 在Java中&#xff0c;数组本质上也是一个对象&#xff0c;因此也存在对象头信息。那么数组的…

PHP原生类总结利用

再SPL介绍 SPL就是Standard PHP Library的缩写。据手册显示&#xff0c;SPL是用于解决典型问题(standard problems)的一组接口与类的集合。打开手册&#xff0c;正如上面的定义一样&#xff0c;有许多封装好的类。因为是要解决典型问题&#xff0c;免不了有一些处理文…

新的开始吧

项目答辩终于结束了&#xff1a; 学习规划 下面先对自己的目前的情况来说&#xff1a; 学长学姐让我先把vue和boot学完&#xff0c;所以我打算先把vue3和boot学一下&#xff0c;但是每天还要花一点时间在六级的听力和阅读上面&#xff0c;还有就是算法&#xff1b; 下面进行…

换根dp学习笔记

最近模拟赛经常做到&#xff0c;于是我就学习了一下。 算法原理 换根 d p dp dp的题一般都会给出一个无根树&#xff0c;因为以不同的点为根时&#xff0c;问题的答案不一样&#xff0c;所以它会让你输出答案的最大或最小值。 暴力去做这种题&#xff0c;就是以每个点为根然…

HarmonyOS 学习记录

时光荏苒,岁月如梭,韶华不负,未来可期。转眼间已经30岁了&#xff0c;学习的重要性不言而喻&#xff0c;在接下来的日子里记录下自己学习HarmonyOS的过程。增加一下知识储备&#xff0c;防患于未然嘛 不得不说华为的开发文档写的不错&#xff0c;开发工具直接安装后自动配置环境…

RLHF讲解

RLHF包含了两个至关重要的步骤&#xff1a; 训练Reward Model用Reward Model和SFT Model构造Reward Function&#xff0c;基于PPO算法来训练LLM frozen RMfrozen SFT ModelActor π Φ R L \pi_{\Phi}^{R L} πΦRL​ initialized from SFT ModelCritic V η V_\eta Vη​ i…

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

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

头歌答案HTML——基础

目录 HTML——基础 第1关&#xff1a;初识HTML&#xff1a;简单的Hello World网页制作 任务描述 第2关&#xff1a;HTML结构&#xff1a;自我简介网页 任务描述 HTML——基本标签 第1关&#xff1a;创建第一个 HTML 标签 任务描述 第2关&#xff1a;创建 任务描述 …

【Liunx】服务器解决 跨域问题

首先打开后端的站点 在站点设置内打开 "配置文件" 然后在 “server_name 本机ip ”下方添加跨域配置,添加成功后重启nginx即可 add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Methods GET, POST, OPTIONS, PUT, DELETE; add_header A…