安庆大理运城常德铜陵江西
投稿投诉
江西南阳
嘉兴昆明
铜陵滨州
广东西昌
常德梅州
兰州阳江
运城金华
广西萍乡
大理重庆
诸暨泉州
安庆南充
武汉辽宁

Makefile学习

5月1日 楚倾云投稿
  Makefile在开源项目中还是相当的常见的,熟悉他的基本语法,还是很有必要的,其次是Makefile相对于shell脚本的优点就是他的关联性,和前置条件等都很好的解决的构建链条的问题。有些学ccpp的同学可能比较熟悉,我们这个核心不关注于这个,主要是使用在日常中make一些cli参数n参数:使用n参数,让make命令输出将要执行的操作步骤,而不是真正执行这些操作;makefilegit:(master)touchMakefile2makefilegit:(master)makenrmfMakefile1Makefile2Makefile3makefilegit:(master)lsMakefileMakefile1Makefile2f参数:使用f参数,后面可以接一个文件名,用于指定一个文件作为makefile文件。如果没有使用f选项,则make命令会在当前目录下查找名为makefile的文件,如果该文件不存在,则查找名为Makefile的文件。C参数一般当我们调用其他目录的makefile,可以直接makeC执行完退回当前make命令,类似于shellinclude可以引用用其他的makefile,类似于其他编程语言的import,和环境变量MAKEFILES等效
  Makefile文件includea。makeb。makeall:echoaechobechohello
  a。make文件echoa:echohelloa
  b。make文件echob:echohellob
  执行
  1)可以发现include却是是把它完完全全的copy到了头部makefilegit:(master)makehelloa
  2)继续,完全符合makefilegit:(master)makeallhelloahellobhellomakefile一些环境变量MAKE
  其实就是你的make环境变量的,whichmake即可。PHONY:allall:echomake路径:(MAKE)
  输出makefilegit:(master)makemake路径:LibraryDeveloperCommandLineToolsusrbinmakeRM
  这个主要是当作rmf参数。PHONY:allclean:(RM)Makefile1Makefile2Makefile3
  输出:makefilegit:(master)makermfMakefile1Makefile2Makefile3MAKEFILELIST
  MAKEFILELIST的变量,它是个列表变量,在每次make读入一个make文件时,都把它添加到最后一项,gnumake有效。Makefile文件all:echo当前makefile:(MAKEFILELIST)(MAKE)fMakefile2Makefile文件2all:echo当前makefile:(MAKEFILELIST)
  输出makefilegit:(master)make当前makefile:Makefile当前makefile:Makefile2
  所以依靠这个可以获取当前路径,但是目前没有模拟出MAKEFILELIST多个列表。PHONY:first:echo(MAKEFILELIST)second:echo(lastword(MAKEFILELIST))third:echo(realpath(lastword(MAKEFILELIST)))latest:firstsecondthirdecho(shelldirname(realpath(lastword(MAKEFILELIST))))
  执行gosourcegit:(master)makelatestMakefileMakefileUsersfanhaodonggocodegosourceMakefileUsersfanhaodonggocodegosourcemakefile文件书写规则
  makefile文件由一组依赖关系和规则构成。每个依赖关系都由一个目标(即将要创建的文件)和一个该目标所依赖的源文件组成;规则描述了如何通过这些依赖文件创建目标。简单的来说,makefile文件的写法如下:target:prerequisitescommand1command2。。。
  其中,target是即将要创建的目标(通常是一个可执行文件),target后面紧跟一个冒号,prerequisite是生成该目标所需要的源文件(依赖),一个目标所依赖的文件可以有多个,依赖文件与目标之间以及各依赖文件之间用空格或制表符Tab隔开,这些元素组成了一个依赖关系。随后的命令command就是规则,也就是make需要执行的命令,它可以是任意的shell命令。另外,makefile文件中,注释以号开头,一直延续到该行的结束。
  比如下面这个,target就是hello,prerequisite是hello。c的文件hello:hello。c(CC)ohello。sShello。c(CC)ohello。ochello。s(CC)ohellohello。o
  构建c项目all:testtest:test。oanotherTest。ogccWalltest。oanotherTest。ootesttest。o:test。cgcccWalltest。canotherTest。o:anotherTest。cgcccWallanotherTest。cclean:rmrf。otest
  GNU的make工作时的执行步骤如下:读入所有的Makefile。读入被include的其它Makefile。初始化文件中的变量。推导隐晦规则,并分析所有规则。为所有的目标文件创建依赖关系链。根据依赖关系,决定哪些目标要重新生成。执行生成命令。
  15步为第一个阶段,67为第二个阶段。第一个阶段中,如果定义的变量被使用了,那么,make会把其展开在使用的位置。但make并不会完全马上展开,make使用的是拖延战术,如果变量出现在依赖关系的规则中,那么仅当这条依赖被决定要使用了,变量才会在其内部展开。
  当然,这个工作方式你不一定要清楚,但是知道这个方式你也会对make更为熟悉。有了这个基础,后续部分也就容易看懂了。申明变量类似宏一样,他会对变量进行引用,在执行时扩展,允许递归扩展:如果变量申明符合先来后到,和含义一样,但是如果申明a引用了b但是b还没有申明,此时认为b为空a(b)1b2c:(d)1d2all:echo(a)echo(c)
  输出makefilegit:(master)make211
  奇怪的现象:可以发现我们申明a变量后,但是输出的时候却是100,可以发现cli传递的优先级最高,不可以被覆盖makefilegit:(master)makea1001001?如果a变量前面已经申明过了,那么后面a?xxx则因为前面已经申明了a,所以不进行赋值,也就是a?xxxx无效,如果前面没有申明则有效AhelloA?helloworldall:echo(A)
  输出:hello这个类似于a1,意思就是在原来的基础上,很方便,下面提供demobuildargs:raceifeq((vendor),true)buildargsmodvendorendifall:echo(buildargs)
  输出:makefilegit:(master)makevendortrueracemodvendor命令行参数echo:echo(arg)
  执行:makefilegit:(master)makeargruoyuruoyu执行函数1、calldefine宏定义
  类似于C语言的宏定义编译生成到bin目录下definebuildsh。build。sh(1)。bin(strip(2))endef脚手架脚本gobuild:pre(callbuild,cmdgobuildmain。go,gobuild)2、自带函数
  格式(命令参数)all:echo(lastword123)
  输出makefilegit:(master)make33、调用shell函数all:echo(shelldirnamedatatest)
  执行makefilegit:(master)makedataMakefile文件的语法target:prerequisites〔tab〕commandstarget:目标,支持模式匹配prerequisites:前置条件,可以有多个,支持模式匹配commands:前面必须有tab,是shell命令makefile函数命令1、注释
  注释一般使用开头表示,但是如果注释在目标的命令包含一般all定义了全部all:hello
  执行makefilegit:(master)makehello2、关闭回声
  这个其实很简单,就是在执行shell命令的时候,往往会打印日志,所以这里提供了很好的解决方式,使用符号all:echohelloworld
  执行后会发现,每次执行的时候都会打印回声makefilegit:(master)makeechohelloworldhelloworld
  所以可以将makefile文件改成以下all:echohelloworld
  输出makefilegit:(master)makehelloworld3、通配符
  和bash一样,主要有等通配符,主要是在shell脚本中使用new:forxin{1,2,3,4};dotouchx。doneclean:(RM)。test
  执行makefilegit:(master)makenewforxin{1,2,3,4};dotouchx。donemakefilegit:(master)lsgreptest1。test2。test3。test4。testmakefilegit:(master)makecleanrmf。testmakefilegit:(master)lsgreptest4、模式匹配
  主要是对文件名的支持!主要是在目标和依赖中使用,使用匹配符,可以将大量同类型的文件,只用一条规则就完成构建。。o:。c
  等同于f1。o:f1。cf2。o:f2。c
  不懂的可以看一下这篇文章,对比一下模式匹配和通配符的区别:https:blog。csdn。netBobYuan888articledetails88640923
  理解模式匹配必须了解下面这四个
  :目标的名字
  :构造所需文件列表所有所有文件的名字
  :构造所需文件列表的第一个文件的名字
  ?:构造所需文件列表中更新过的文件
  大致原理:我要找f1。o的构造规则,看看Makefile中那个规则符合。然后找到了。o:。c来套一下来套一下。o和我要找的f1。o匹配套上了,得到f1。所以在后面的。c就表示f1。c了。OK进行构造
  1、例子一(编译c文件)。o:。c。hecho目标的名字:,依赖的第一个文件:,依赖的全部文件:,所更新的文件:?(CC)all:utils。oecho编译clean:(RM)。i。s。omain
  执行,可以看到完全符合我们的例子目标的名字:utils。o,依赖的第一个文件:utils。c,依赖的全部文件:utils。cutils。h,所更新的文件:utils。cutils。hccoutils。ocutils。c编译for循环1、makefile:foreach循环
  语法:(foreach,(gvar),;),这里需要变量引用需要使用()list:(shellls)all:(foreachitem,(list),echo(item);echo(realpath(item));)
  输出:makefilegit:(master)makeMakefileUsersfanhaodongnotenotedemomakefileMakefileMakefile1UsersfanhaodongnotenotedemomakefileMakefile1Makefile2UsersfanhaodongnotenotedemomakefileMakefile23、shell:for循环list:(shellls)all:forxin(list);done
  记住一点就好,符号转移需要使用
  执行makefilegit:(master)makemforMakefileMakefile1Makefile2a。makeb。makeif函数1、makefile:if函数
  命令格式:(if,;,;)all:(if(shellcommandv(arg)),echocommand(arg)isexist,echocommand(arg)isnotexist)
  执行makefilegit:(master)makearggocommandgoisexistmakefilegit:(master)makearggo1commandgo1isnotexist2、shell:if函数all:if〔commandv(arg)〕;thenechocommand〔(arg)〕elseechocommand〔(arg)〕fi
  执行makefilegit:(master)makearggocommand〔go〕isexistmakefilegit:(master)makearggo1command〔go1〕isnotexist执行多个命令echo:echohelloworldecho2:echohelloworld2
  执行:makefilegit:(master)makeechoecho2helloworldhelloworld2宏定义defineechoechohello,(1)!endefARG:ifdefargARG:(arg)elseARG:NULLendifall:print(callecho,world)echo(ARG)print:echoarg:(arg)
  执行makefilegit:(master)makeargworldarg:worldhello,world!world系统环境变量
  申明推荐:export变量名称,获取使用{变量名称}GOPROXY:https:goproxy。cn,directexportGOPROXYall:echo{GOPROXY}编译C项目
  c项目往往很复杂,设计到预编译,编译,汇编,链接的过程
  1、文件(头文件、main文件)
  1、utils。hifndefADDHdefineADDHintadd(inta,intb);endif
  2、utils。cintadd(intx,inty){}
  3、main。c
  注意:头文件的寻找方式先搜索当前目录然后搜索I指定的目录,例如I。head再搜索gcc的环境变量CPLUSINCLUDEPATH(C程序使用的是CINCLUDEPATH)最后搜索gcc的内定目录includestdio。hincludeutils。hintmain(intargc,charconstargv〔〕){printf(12d,add(1,2));return0;}
  假如。h文件放在head目录cppgit:(master)lsheadutils。h可以发现编译异常,异常时。h文件未找到cppgit:(master)gcccmain。comain。omain。c:2:10:fatalerror:utils。hfilenotfoundincludeutils。h1errorgenerated。修改I参数可以发现通过cppgit:(master)gccI。headcmain。comain。ocppgit:(master)lsgrepmain。omain。o2、预编译E
  E:预编译,这一步主要是将头文件,宏定义展开到文件,是文本形式cppgit:(master)gccEmain。comain。icppgit:(master)tailf10main。itail:10:Nosuchfileordirectorymain。i可以看到这里是把utils。h的头文件信息copy过来了intadd(inta,intb);3main。c2intmain(intargc,charconstargv〔〕){printf(12d,add(1,2));return0;}3、编译S
  编译为汇编代码,是文本形式cppgit:(master)gccSmain。iomain。s
  4、汇编c
  就是编译成二进制的汇编文件,是可重定位目标程序,属于二进制文件cppgit:(master)gcccmain。somain。ocppgit:(master)hexdumpCmain。o00000000cffaedfe070000010300000001000000。。。。。。。。。。。。。。。。0000001004000000080200000020000000000000。。。。。。。。。。。。。。。0000002019000000880100000000000000000000。。。。。。。。。。。。。。。。0000003000000000000000000000000000000000。。。。。。。。。。。。。。。。00000040b0000000000000002802000000000000。。。。。。。。(。。。。。。。00000050b0000000000000000700000007000000。。。。。。。。。。。。。。。。0000006004000000000000005f5f746578740000。。。。。。。。text。。0000007000000000000000005f5f544558540000。。。。。。。。TEXT。。0000008000000000000000000000000000000000。。。。。。。。。。。。。。。。0000009042000000000000002802000004000000B。。。。。。。(。。。。。。。000000a0d8020000030000000004008000000000。。。。。。。。。。。。。。。。cppgit:(master)objdumpdmain。omain。o:fileformatMachO64bitx8664DisassemblyofsectionTEXT,text:0000000000000000main:0:55pushqrbp1:4889e5movqrsp,rbp4:4883ec20subq32,rsp8:c745fc00000000movl0,4(rbp)f:897df8movledi,8(rbp)12:488975f0movqrsi,16(rbp)16:bf01000000movl1,edi1b:be02000000movl2,esi20:e800000000callq0main0x2525:488d3d16000000leaq22(rip),rdi2c:89c6movleax,esi2e:b000movb0,al30:e800000000callq0main0x3535:31c9xorlecx,ecx37:8945ecmovleax,20(rbp)3a:89c8movlecx,eax3c:4883c420addq32,rsp40:5dpopqrbp41:c3retq5、链接
  对于ccpp语言来说,最难的就是链接了!这里也设计到隐晦规则了,首先。o是符合main。o,utils。o的,所以会执行两次cc,最终链接成功伪目标,这里定义的目标不会去文件系统里寻找。PHONY:allcleanCC属于makefile的全局变量,已经定义好了,但是我们使用gcc需要指定CC:gcc目前的目标项目名称也就是。目前的依赖项目。o:。c(CC)oall:installrunclean当依赖符合模式匹配时候,会执行上面的。o:。cinstall:utils。omain。ogccomainutils。omain。orun:。mainclean:(RM)。i。s。omain
  执行cppgit:(master)makegcccutils。coutils。ogcccmain。comain。ogccomainutils。omain。o。main123rmf。i。s。omain帮助
  如果你想写help,可以使用下面那个表达式。PHONY:helpecho:打印echoechohelloall:打印echo1help:帮助awkBEGIN{FS:。?}〔azAZ〕:。?{sub(n,sprintf(22c,),2);printf33〔36m20s33〔0ms,1,2}(MAKEFILELIST)
  其实很简单,了解awk语法的话,知道awk条件动作文件名所谓条件就是正则表达式,分隔符是:。?,然后匹配的条件是以字母开头的〔root19096dee708bdata〕catdemo。txt11221112233
  匹配一下〔root19096dee708bdata〕awk{printf1s2s,1,2}demo。txt11122211112122233
  我们要拿到我们的结果!所以需要匹配有空格的,匹配空格就是s〔root19096dee708bdata〕awks{printf1s2s,1,2}demo。txt111222122233
投诉 评论 转载

Makefile学习Makefile在开源项目中还是相当的常见的,熟悉他的基本语法,还是很有必要的,其次是Makefile相对于shell脚本的优点就是他的关联性,和前置条件等都很好的解决的构建链……郭艾伦太惨了,到手的fmvp奖杯被姚明算法规则挡在门外由于广厦男篮的两大主力核心赵岩昊和胡金秋皆因为伤病问题直接导致赛季报销,CBA本赛季总决赛也几乎成为了最没有悬念的总决赛之一,两支球队的差距完全不在一个层次上,辽宁男篮有99。……中药美容之菟丝子的美容功效及方法【药材简介】菟丝子为旋花科一年生寄生缠绕性草本菟丝子CuscutachinensisLam。的干燥成熟种子。主产江苏、辽宁、吉林、河北、山东等地。秋季采收。生用或盐水炙用,或煮……性格太软的人,建议你疯狂做这几件事相信每个人,刷看朋友圈,刷短视频时,看到别人的日常分享,自己却没有时,就会感到莫名的伤感和自卑。觉得别人触手可及的日常事物,对于自己却是那么的遥不可及。但我想跟你说……改革亲历者访谈中国巨石张毓强混改成功的秘诀在充分信任和授权党的十八大以来,习近平总书记针对国有企业改革发展和党的建设发表了一系列重要讲话,作出了一系列重要指示,为深入推进新时代国有企业改革发展提供了强大思想武器和科学行动指南。十……宋清辉预计未来磷矿石供应将延续紧张态势价格上行态势或持续著名经济学家宋清辉表示,从供给端来看,磷矿石属于不可再生资源,特别是随着环保政策趋严,磷矿从建设到投产需要相当长的时间。总体来看,未来我国磷矿石供需总体上仍将呈现紧平衡态势,价……月兔要不别返乡了,气的肚子疼,这只会跳舞的兔子,我真谢谢你昨天玩生肖游乐园集生肖卡的活动,前60层感觉还挺简单,61层突然就变慢了,65层突然又快了,后面也会一会快一会慢,90层以后更甚,好几次在了98层被撞飞,你说气不气人?6……护肤技巧丨脸上出现细纹怎么办?脸部一旦开始出现细纹就需要引起警惕了,是时候开始保养了。25岁以后,正是细胞的新陈代谢从顶峰慢慢下降的时候,皮肤的老化细纹已经在不知不觉中发生了。脸部出现细纹怎么办?今天,美妆……世界杯最具特色的帐篷体育场长什么样?阿尔拜特体育场FIFTH。阿尔拜特体育馆是本届世界杯开幕式的场地,也是一个重要的国际活动场所。它坐落在北方海港艾尔科尔,可以容纳60,000人。同时,可折叠的可伸展……56岁离家出走的阿姨现状曝光余生很贵,请远离消耗你的人还记得前段时间爆红全网,56岁逃离家庭、一人一车一帐篷自驾游的苏敏阿姨吗?今天,在网上偶然刷到了她发布的一条视频。视频中,苏敏满脸都是藏不住的喜悦和自豪,她靠在房车……常州,比苏州更小众好吃不输南京,这座低调水城把生活过成诗江南大部分地区,今天已经感受到降温的苗头了。过几天温度继续下坡,最低居然要到1。天一冷就想泡温泉,一想泡温泉江浙沪范围必然少不了溧阳天目湖的温泉常州恐龙园图虫创意……夜读灵魂相似的人,总会相逢美好终会遇见美好。生命中,山一程水一程,每个人都在渴望遇到一个灵魂相似的人。在偌大的世界中,只有频率相同的人,才能看见彼此内心深处不为人知的优雅。三观契合,才……
真香!2512,东契奇最佳搭档诞生,一个首轮签换回二当家很划一个人如此越界,其实是对你动情了尿路感染,令人懊恼,做好这7件事,才能避免复发构筑人才高地,激发潜力动能C罗与梅西同样辉煌的生涯却不一样的归途英雄迟暮,也问归处F1与摩纳哥的古老婚姻竟亮起红灯!石油金元已成新欢妊娠纹的六种颜色对比,看看哪种最严重?什么样子最容易修复2022年下半年最值得入手的四款新机,综合表现出色,有你喜欢散文人过五十,尽人事,听天命延期免息!多家商用车企出台延期还贷举措,机构预测今年市场有望健康的基础直男斩发型原来黑长直也可以这样整?绝美

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找七猫云易事利