前端入门->makefile

2551129937 8年前

来自: https://segmentfault.com/a/1190000004437816

我第一次见到makefile的时候,是在看js测试的那一块。简直,一开始跟风,觉得makefile这么牛逼,我也想看看。 首先,看了陈老师的 跟我一起学习Makefile . 打开了第一章之后,后面就没有勇气再打开下去了。 后来了解了一下makefile原来是C语言作为工程化处理的一个必杀技。然后就迁移到其他平台上了,但是对于我们这种,对于C的认知度为(0)的人,这不是难为我们吗?后来,就在网上游荡,慢慢找,还是有点入门的感觉,这里,我想把,一些感悟分享给大家,如果有用,您就拿去,没用的话,ctrl+w就over了。

知识 = 学习 + 分享

makefile的基本浅析

前端学习makefile的成本还是蛮大的诶~ 因为好多教程都是用c写的,这也没办法,谁让这是C的工具,我们也只是偷师学学。makefile的基本格式为:

target: prerequisities  [TAB]command

target就是你要执行的命令套件,prerequisties就是依赖,而command就是实际执行的命令。(说人话)上栗子:

create:       touch newMake.js

makefile的解析的过程:

首先makefile会读取你的makefile文件.  读取指定的target.  解析后面的依赖是否更新  如果更新则执行command  没有则do nothing

由于我们这里后面没有什么参数,所以,make会直接执行对应的命令。 然后执行:

make create

接着你会发现,在当前目录下(makefile文件夹下)。会生成一个 newMake.js的文件。这时候就说明你已经成功的入门了makefile了.

基本命令

注释

在makefile中,通常可以用"#"标识来作为注释.

run:          touch a.js #create js file  del:          rm a.js #delete js file

回声

在php中有个输出API echo, 和这个类似,在make中,它会自动打印命令,然后才执行。

//makefile  run:          touch a.js #create js file  //执行make  make run  //结果:  touch a.js #create js file  //这时候,他便会创建a.js文件

当然如果你不想让make打印出来,可以在首行加上"@"表示取消回声.

run:          @touch a.js #create js file

之后,你再使用make run。他便不会打印出什么东西了。

自动变量

$@指代当前构建的目标。 怎么说呢?

show me the code

a.js b.js:      touch $@  //等价于:  a.js b.js:      touch a.js b.js;  //也等价于:  a.js:      touch a.js;  b.js:       touch b.js

这里相当于你定义了两个命令(虽然,看起来像一个)

$<指代第一个依赖的条件。(这些都是什么flag呀~ 宝宝看不懂)

我们来看一下例子吧:

create:a.js b.js      touch $<  //等价于  create:a.js b.js      touch a.js

还有 $^ 指代所有的依赖条件。makefile里面有很多automatic variable 这里只列一些比较常用的。

变量的使用:

在写nodeJS测试的时候,变量的作用 super well.

通常我们需要从node_modules中,引出指定的.bin包。 一般而言就是mocha和istanbul.

使用命令:

npm install mocha istanbul --save-dev

还记得,我们在运行测试的时候的命令吗?

istanbul cover _mocha

由于系统已经把环境变量给配置好了,你执行上面的命令的时候,其实,shell已经从全局中把对应的bin文件提取出来,并且执行了。

而在makefile中,就需要你手动执行进行路径的配置了.

举个例子吧,现在我们处在和 node_modules 同目录下。

然后引入mocha和istanbul的路径,并存入变量中:

MOCHA=./node_modules/.bin/mocha  ISTANBUL=./node_modules/.bin/istanbul

OK,这样就够了。 有的同学,可能会发现node_modules下并没有.bin文件夹呀~ 亲莫急。你可以使用 ls -a 来查看所有的。相信你一定能找到的。

现在我们已经定义了变量,接下来要做的就是引用定义的变量了。

在makefile中,使用$(...)进行相关的定义。

像这样:

MOCHA=./node_modules/.bin/mocha  ISTANBUL=./node_modules/.bin/istanbul  _MOCHA=./node_modules/.bin/_mocha  runTest:          $(ISTANBUL) cover $(_MOCHA)

然后在另外一个zsh中执行:

make runTest;

就可以达到和 istanbul cover _mocha 一样的效果了.

在makefile里面,变量分为两种:

引用式变量

如果es6和commonJS的同学应该知道,在模块的书写上,两者都有自己的一套实现原理。 而es6的实现原理就和引用变量一样的,即,相互引用的模块,会持续影响到对方。举个栗子呗:

    A=$(B);      B=$(C);      C=quote

当在编辑器解析时,会有以下的结果:

A=quote;  B=quote;  C=quote;

这样,其实并没有什么不好,但是如果你不小心写成了一个死循环,呵呵,你电脑也就崩了。像这样的:

A=$(B)  B=$(A)

这样解析器会一直这样,不断的解析,只到你的资源被eat up. 然后你就可以关机重启了。

直接展开式变量

这个就是用来解决上述问题的。使用的赋值符号不在是 = 而变成了 := . 看个例子吧:

A=good  B:=$(A) job  A=stupid

最终的解析结果为:

B=good job

A=stupid

为什么呢? 因为使用":="的使用,他会立即寻找上文引用到的最近的变量,然后放入B中,这时候B的值就已经固定了。如果你后面再去修改A的值是没有意义的。

如果使用引用变量的话,会有这样的结果:

A=good  B=$(A) job  A=bad

最后输出:

B=bad job

A=bad

就是酱汁,大家了解就over了。

其实,大部分时候我还是会选择引用变量的,因为简单,灵活性更大。 而直接展开式变量通常写给leader看的,大家注意一下就没什么问题了。

另外变量的定义一共有 四种方法

VARIABLE = value  # 在执行时扩展,允许递归扩展。    VARIABLE := value  # 在定义时扩展。    VARIABLE ?= value  # 只有在该变量为空时才设置值。    VARIABLE += value  # 将值追加到变量的尾端。

由于剩下两种使用的频率不是很高,这里也就不赘述了。

伪目标

一门深邃的语言,首先必须要有一个装逼的名字。伪目标这个名字好,能一眼让你不知道他根本是干什么的。

意淫完毕~

其实,伪目标就是为了解决命令和文件名冲突的。

比如,我的makefile是这样书写的

clean:          rm *.jpg  create:          touch clean

首先,我执行make clean,他会完全的删除当前目录下的jpg文件。然后我运行make create 生成一个clean文件。但是当我再次使用make clean的时候。 执行的效果并不是我预期的那样,提示jpg文件不存在。而是提示:

make: `clean' is up to date.

那么问题来了: 是你傻逼,还是电脑傻逼?

你: 肯定是电脑傻逼.

电脑: xxx&&*%^^^^%. 好吧.为了给你点信心学下去,是我傻逼

这里,涉及到了GUN make的一条tip: 隐含规则

由于这个隐含规则主要是针对于C语言的童鞋的。这里,作为前端的宝宝,我们了解一下就可以了。

隐含规则就是指一些约定俗成语句可以不需要写出来,make可以自己去推测,并且执行。(由于隐含规则大部分是针对C的,我这里就不列了)。

这样,像上文一样,make clean 会首先查找隐含文件,检查clean的文件,由于已经存在clean文件,这里会被认为是最新的,就不会去执行定义的规则了。(大家如果有兴趣可以去翻阅一下详细资料). 另外,我觉得这样我们前端去理解这个,这是要上天呀~~~ 说白了,就是,如果你的文件下,有和命令同名的文件的话,你的命令是不会被执行的。

所以,我们需要伪命令,来解决这一冲突.

使用 .PHONY: 来进行定义:

在makefile中,我们加上一句:

.PHONY: clean
然后继续执行 make clean

这样,他就能正常的执行你所定义的command了。

通常情况下,我们需要把自己写的命令都在.PHONY里面过一遍,有备无患吧~

最后说两句

前端懂makefile没坏处写好makefile更没坏处

</div>