前端入門->makefile
來自: 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呀~ 寶寶看不懂)
我們來看一下例子吧:
</div>
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的路徑,并存入變量中:
</div>
MOCHA=./node_modules/.bin/mocha ISTANBUL=./node_modules/.bin/istanbul
OK,這樣就夠了。 有的同學,可能會發現node_modules下并沒有.bin文件夾呀~ 親莫急。你可以使用 ls -a 來查看所有的。相信你一定能找到的。
現在我們已經定義了變量,接下來要做的就是引用定義的變量了。
在makefile中,使用$(...)進行相關的定義。
像這樣:
</div>
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里面,變量分為兩種:
</div>
引用式變量
如果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的值是沒有意義的。
如果使用引用變量的話,會有這樣的結果:
</div>
A=good B=$(A) job A=bad
最后輸出:
B=bad job
A=bad
就是醬汁,大家了解就over了。
其實,大部分時候我還是會選擇引用變量的,因為簡單,靈活性更大。 而直接展開式變量通常寫給leader看的,大家注意一下就沒什么問題了。
另外變量的定義一共有 四種方法
</div>
VARIABLE = value在執行時擴展,允許遞歸擴展。
VARIABLE := value
在定義時擴展。
VARIABLE ?= value
只有在該變量為空時才設置值。
VARIABLE += value
將值追加到變量的尾端。</pre>
由于剩下兩種使用的頻率不是很高,這里也就不贅述了。
偽目標
一門深邃的語言,首先必須要有一個裝逼的名字。偽目標這個名字好,能一眼讓你不知道他根本是干什么的。
意淫完畢~
其實,偽目標就是為了解決命令和文件名沖突的。
比如,我的makefile是這樣書寫的
clean: rm *.jpg create: touch clean首先,我執行make clean,他會完全的刪除當前目錄下的jpg文件。然后我運行make create 生成一個clean文件。但是當我再次使用make clean的時候。 執行的效果并不是我預期的那樣,提示jpg文件不存在。而是提示:
make: `clean' is up to date.那么問題來了: 是你傻逼,還是電腦傻逼?
你: 肯定是電腦傻逼.
電腦: xxx&&*%^^^^%. 好吧.為了給你點信心學下去,是我傻逼
</div>
這里,涉及到了GUN make的一條tip: 隱含規則 。
由于這個隱含規則主要是針對于C語言的童鞋的。這里,作為前端的寶寶,我們了解一下就可以了。
隱含規則就是指一些約定俗成語句可以不需要寫出來,make可以自己去推測,并且執行。(由于隱含規則大部分是針對C的,我這里就不列了)。
這樣,像上文一樣,make clean 會首先查找隱含文件,檢查clean的文件,由于已經存在clean文件,這里會被認為是最新的,就不會去執行定義的規則了。(大家如果有興趣可以去翻閱一下詳細資料). 另外,我覺得這樣我們前端去理解這個,這是要上天呀~~~ 說白了,就是,如果你的文件下,有和命令同名的文件的話,你的命令是不會被執行的。
所以,我們需要偽命令,來解決這一沖突.
使用 .PHONY: 來進行定義:
在makefile中,我們加上一句:
.PHONY: clean然后繼續執行 make clean
這樣,他就能正常的執行你所定義的command了。
通常情況下,我們需要把自己寫的命令都在.PHONY里面過一遍,有備無患吧~
</div>
最后說兩句
前端懂makefile沒壞處寫好makefile更沒壞處
</div>本文由用戶 2551129937 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!相關資訊