【Makefile】Makefile与shell命令的联系

【makefile】makefile与shell命令为何总是藕断丝连? 1 写在前面 博主最近在项目实践过程中,需要深度定制项目的makefile,其中有些复杂的流程必须得借助shell脚本才能高效地完成,为此博主特意深入学习了在makefile种调用shell命令的方法。
大家都知道shell命令是linux的神器,学会灵活应用它可以大大提升执行的自动化效率。
makefile也是gnu的另一大神器,大家要知道,大名鼎鼎的linux内核的编译就是靠makefile来支撑的,连这么庞大、复杂的系统编译它都可以轻松驾驭,可想而知,它也是牛逼哄哄的存在。
我们试想一下,如果把makefile和shell命令这两大神器联合在一起,会有怎样的效果,我们一起来看下。
2 什么是makefile? 这个问题,我在之前的博文中就有介绍过,感兴趣的可以点过去看一看:【linux + makefile】十分钟教你学会makefile的force。
下面我再总结下,到底什么是makefile?
makefile的基本形式如下所示:
target : dependences cmd
# target:生成的目标,可以是一个文件,也可以是一个虚拟符号(非真实文件) # dependences: 生成目标的所有依赖,它是一个集合,可以只有一个文件,或者很多文件;也可以是虚拟符号 # cmd:把所有依赖生成目标的执行命令,其中cmd前面是一个tab键,而不能是空格 makefile的基本规则,归纳起来就是一句话:【当一个target (欲生成的目标)比它的任何一个dependences(依赖的文件)旧时,这个target就要重新生成】。
这段话读起来很简单,就是makefile在执行编译的时候,会先去判断target和其依赖文件的时间差,如果target的时间比较旧,意味着依赖文件已经更新了,那么target就要重新生成;反之,如果target的时间比较新,意味着在target生成后,依赖文件是没有改变过的,自然就不用重新去生成target。
说白了,就是搞清楚【target 和 dependences 的时间关系】,弄明白了这个,你就可以读懂makefile了。
3 如何调试makefile? 以下makefile给大家演示下如何在makefile中写注释以及如何调试makefile的变量。
# this is an annotation for this makefile.# call shell cmd in these ways ...cur_path = `pwd`ls_files = `ls`ls_test_files = $(shell ls test*)debug_variable = debug# debug your makefile variables ...$(info this is a info msg ...)$(warning this is a warning msg ... debug_variable=$(debug_variable))$(error this is a error msg ... it will make this makefile to exist beacuse of an 'error' accur.)# begin you targets and dependencesinfo: @echo cur_path = $(cur_path) @echo ls_files = $(ls_files) @echo ls_test_files = $(ls_test_files) 我们执行下make info可以看下,输出信息:
分别对应info,warning,error;这三个函数是makefile中内置的,在任意makefile中都可以使用。但是需要注意的,这三个函数可以在makefile的任意位置调用,但是必须符合语法规则,比如在cmd部分(见第一章节的引用内容)调用时,必须时tab开头。
我们试下这个的效果:
4 makefile定义变量的时候调用shell命令 还是拿上面的makefile来分析,我们一开始定义了几个变量:
cur_path = `pwd`ls_files = `ls`ls_test_files = $(shell ls test*) 其中curpath是保存当前makefile的路径,我们都知道shell命令有个pwd可以获取到当前目录的路径,所以 curpath 变量正是利用了这个命令来取得当前路径。其中,值得注意的是 表示的是获取pwd命令的返回值,这个,不是分号 ' ',而是键盘左上角数字1左边的那个键值,新手一般非常容易搞错这一点。
第二个变量ls_files的定义,使用同样的方式调用了 ls 命令,但是它在返回值的左右,加了 “ ”;这样做的主要目的是,ls的返回值通常是一个字符串,中间每个文件名用空格隔开的;如果我们想把这一系列的字符串连起来而不是分散的,我们就必须使用 把它们包起来,这样makefile变量就会把它当作一个字符串整体来处理。
第三个变量lstestfiles,它就换了一种方式来调用shell命令,它的格式是 $(shell xxx),其中xxx就是一个可以在shell环境下执行的shell命令,比如本例子中,xxx就是 ls test*。
两者方法没有本质的区别,结合自己的实际情况来使用即可,从易读性来说,推荐使用$(shell xxx)的调用方式。
5 makefile在执行命令的时候调用shell命令 以下面的makefile为例子:
# this is an annotation for this makefile.shell_cmd: @ls test* @pwd @echo shell_cmd test ... 执行make shell_cmd,我们可以看到输出:
只要是shell执行的命令,都可以运行,这就方便我们做一些自动化操作,比如创建目录、删除文件、下载文件、上传文件等等。
6 makefile以函数的形式调用shell命令 请看下面的makefile内容
# this is an annotation for this makefile.debug_variable = debug# this is a shell function.define function_test_shell param1=$1;\ local_variable=12345678;\ debug_variable=$(debug_variable);\ echo param1=$$param1;\ echo local_variable=$$local_variable;\ echo debug_variable=$$debug_variable;\ i=0;\ cnt=10;\ for i in `seq $$cnt`; do\ echo i=$$i;\ done;\ ls -al;\ ls -al test*endef# begin you targets and dependencesshell_function: @$(call function_test_shell,$(debug_variable)) 我们执行make shell_function可以看到输出:
对应就是shell函数里面的操作。
在makefile调用shell函数的写法上,有几点特别需要注意:
1)makefile定义函数是使用define 和 endef,务必配对使用;函数里面的实现可以调用shell命令,也可以调用makefile内置的函数,也可以调用自定义的makefile函数;
2)makefile函数的调用方式是$(call function,xx,yy,zz),其中function是函数名,也就是define后面的名字,xx/yy/zz分别是函数的三个入参;当然有几个参数就填几个,每一个使用 , 隔开;
3) 在函数里面使用$1 $2 $3获取输入的参数,即$+数字的方式获取入参;
4)如果函数里面使用的是shell组合命令,请务必在每一条shell命令后面加上 ; 符号,并且每一行加上 \ 连起来;这样对于shell解析器而言,它会认为是一条长长的组合输入命令,而不报语法错误;
5)函数内部使用shell的变量,比如是变量a,正确的写法是$$a;而不是常规的shell写法$a,也不是makefile获取变量的方法$(a)或${a};这一点特别需要注意。
6)如果函数内部访问的是makefile定义的变量,比如示例中的访问debugvariable变量,还是采用$(debugvariable)的方式。
好了,本期分享就到这里,有疑问的话,欢迎联系我。
7 更多分享 欢迎关注我的github仓库01workstation,日常分享一些开发笔记和项目实战,欢迎指正问题。
同时也非常欢迎关注我的csdn主页和专栏:
【csdn主页-架构师李肯】
【rt-thread主页-架构师李肯】
【c/c++语言编程专栏】
【gcc专栏】
【信息安全专栏】
【rt-thread开发笔记】
【freertos开发笔记】
【ble蓝牙开发笔记】
【arm开发笔记】
【risc-v开发笔记】
有问题的话,可以跟我讨论,知无不答,谢谢大家。


3D电视沦为2010失败科技产品
高通宣布将与Rokid联合打造企业级AR眼镜
广东移动携手合作伙伴共同推动5G等技术与数字化大桥建设深度融合
IP远程数字KVM相较于常规KVM的优势分析
贴片电容知识,Chip capacitor
【Makefile】Makefile与shell命令的联系
检查线路使用万用表还是兆欧表?
千分表的结构有哪些
e络盟供货Rohde & Schwarz新型 NGU源测量单元
5G带给我们什么?
废LiCoO2电池机械化学升级循环再生为新型电池
用摇表怎样测绝缘电阻
第三届全国基础教育信息化应用展举行,AR/VR设备让抽象知识更生动
光通信系统中基于四波混频(FWM)效应的幅度限制器
欧菲光拟15.8亿元收购索尼电子华南
植物营养测定仪的功能特点以及用途意义
打破传统技术,普莱信发布面板级封装巨量转移设备P-XBonder
成都高新区出台《关于科技创新驱动高质量发展的若干政策》
特斯拉市值一天跌73亿的背后解析 SEC调查始末
小米鸿蒙系统刷机包下载 安装教程如下