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.ogcc main.o fun.o -o app
main.o:main.cgcc -c main.c -o main.o -I ./inc
fun.o:fun.cgcc -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.ogcc main.o fun.o -o app
%.o:%.cgcc -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
elseA=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
elseecho $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 其他代表过滤.cifeq ($(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.hqwc.cn/news/176838.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于SSM的药店药品销售系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

23款奔驰E300L升级几何多光束大灯 自适应远近功能

奔驰新款E300L升级几何多光束大灯&#xff0c;单侧的LED头灯分别由84颗独立的LED光源组成&#xff0c;与风挡玻璃上的立体摄像机配合&#xff0c;每秒钟可对路况进行100次扫描&#xff0c;针对不同的路况和驾驶状态&#xff0c;智能调整84个独立光源 几何多光束大灯每侧大灯都拥…

HPC 工作负载管理 —— IBM Spectrum LSF Suite

全面的工作负载管理解决方案&#xff0c;通过增强用户和管理员体验以及实现规模性能来简化 HPC。 IBM Spectrum LSF Suites 是面向分布式高性能计算 (HPC) 的工作负载管理平台和作业调度程序。基于 Terraform 的自动化现已可用&#xff0c;该功能可在 IBM Cloud 上为基于 IBM …

Niushop单商户及多商户v5商城系统第三方商业插件cps联盟视频购物及多包装库存转换的安装

一、后端安装 把video文件夹直接上传到addon目录下即可登录后台&#xff0c;设置->系统维护->插件管理->未安装插件&#xff0c;找到插件直接安装即可 3.在营销->营销中心->营销活动&#xff0c;找到视频列表这个插件&#xff0c;点击进去配置视频即可 4.装…

rocksdb中测试工具Benchmark.sh用法(基准、性能测试)

1.首先要安装db_bench工具&#xff0c;这个工具在成功安装rocksdb之后就自动存在了&#xff0c;主要是在使用make命令之后就成功安装了&#xff0c;详情请见我之前的文章 2.确保成功安装db_bench之后&#xff0c;找到安装的rocksdb目录下面的tools文件夹&#xff0c;查看里面是…

【机器学习基础】一元线性回归(适合初学者的保姆级文章)

&#x1f680;个人主页&#xff1a;为梦而生~ 关注我一起学习吧&#xff01; &#x1f4a1;专栏&#xff1a;机器学习 欢迎订阅&#xff01;后面的内容会越来越有意思~ &#x1f4a1;往期推荐&#xff1a; 【机器学习基础】机器学习入门&#xff08;1&#xff09; 【机器学习基…

SecureCRT 9.2.4最新

SecureCRT是一款功能强大的终端仿真软件&#xff0c;它通过提供安全的、高效的会话&#xff0c;帮助用户在远程设备上完成各种任务。SecureCRT具有出色的性能和可靠性&#xff0c;能够处理复杂的网络环境&#xff0c;提供高效的远程访问和管理。 SecureCRT的主要特点包括&…

百度智能云文档汇总【2】

百度智能云文档汇总目录2&#xff1a; 一、内容审核-->https://cloud.baidu.com/doc/ANTIPORN/index.html 百度内容审核基于深度学习的智能内容审核方案&#xff0c;准确识别图片和视频中的涉黄、涉暴涉恐、政治敏感、微商广告、恶心等内容&#xff0c;也能从美观和清晰等维…

Git企业开发级讲解(一)

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、Git初识1、提出问题2、如何解决--版本控制器3、注意事项 二、Git 安装1、Linux-centos2、…

互联网Java工程师面试题·微服务篇·第一弹

目录 ​编辑 1、您对微服务有何了解&#xff1f; 2、微服务架构有哪些优势&#xff1f; 3、微服务有哪些特点&#xff1f; 4、设计微服务的最佳实践是什么&#xff1f; 5、微服务架构如何运作&#xff1f; 6、微服务架构的优缺点是什么&#xff1f; 7、单片&#xff0c…

卡尔曼家族从零解剖-(06) 一维卡尔曼滤波编程(c++)实践、透彻理解公式结果

讲解关于slam一系列文章汇总链接:史上最全slam从零开始&#xff0c;针对于本栏目讲解的 卡尔曼家族从零解剖 链接 :卡尔曼家族从零解剖-(00)目录最新无死角讲解&#xff1a;https://blog.csdn.net/weixin_43013761/article/details/133846882 文末正下方中心提供了本人 联系…

pytorch深度学习快速入门

from PIL import Image img_path"E:\\code\\learn_pytorch\\dataset\\train\\ants\\0013035.jpg" img Image.open(img_path)显示图片 获取很多图 def __init__(self,root_dir,label_dir):self.root_dir root_dirself.label_dir label_dirself.path os.path.joi…