共计 3758 个字符,预计需要花费 10 分钟才能阅读完成。
个创建好的项目都有各式各样的构建过程,不论它是大型的 web 应用,或者小型可重用的 AMD 组建。已有一大堆的工具可帮你自动的完成构建过程,很多流行的工具例如非常抢眼的工具 grunt。
不论如何,一些项目中 grunt 工具未必就是你需要的,有时候对你而言简单的 shell 脚本会比 node.js 的工具更具有生产力。今天我将非常简洁的介绍 GNU Make 工具,以及你如何使用它来创建很爽的自动化构建几个步骤。
makefile 的概念
一个 makefile 保存了一堆很有特殊目的的 词目。正如我们相当喜爱 UNIX,现在真是时候提醒你自己:“写一些词目来做一件事儿,并且把它做好”的规则。这些词目包括:
- 一个 目标 ,你知道
make install
吗?install 就是目标。它也可能是一个文件,例如:make bundle.min.js
。 - 依赖,一些由 目标 所依赖的一些可选的文件。
- 以及最后运行的命令。
当你创建词目的时候,要尽可能的简单,同时要注意灵活性。例如,你想默认最小化一些预定义的文件,但偶尔你想配置其他的一些文件给 makefile,并且弄出这些命令。
创建灵活的 目标
为了更具灵活性,预定义的目标依赖可以被命令行列出的覆盖掉,要把依赖列表写在目标名称的后边。
$ make min index.js plugins.js
$ make min // 默认依赖 index.js
还有一种常见玩法,就是在 makefile 文件中把路径设置成变量,然后允许用户像如下的方式来覆盖:
$ make JSMIN=./bin/jsmin min
实现 min 目标
OK,那么我们开始创建一个 Makefile。
一个 目标 的格式是:
<target>: <dependencies>
commands...
As I mentioned earlier, the target can be a general name or a file, for now we’ll keep to names such as min or install. Dependencies are a space separated list of files you want to process or of other targets you want to run. Let’s create our first target.
min: index.js plugins.js
uglify --output scripts.min.js $^
he $^
is a variable which holds a space separated list of the dependencies. It will be expanded into: uglify --output scripts.min.js index.js plugins.js
.
Now this is entry is somewhat flexible as you could run make min plugins.js
to replace the default dependencies and only minimize plugins.js
. However, let’s refactor this into something prettier.
A web project makefile
First lets define some variables.
# ?= means the variable can be overridden from the command line like:
# make UGLIFY=./node_modules/.bin/uglify min
UGLIFY ?= uglify
OUTPUT ?= scripts.min.js
JS_FILES := index.js plugins.js
min: $(JS_FILES)
$(UGLIFY) --output $(OUTPUT) $^
Now let’s split out the concat task so we can use it separately
UGLIFY ?= uglify
OUTPUT ?= scripts.min.js
JS_FILES := index.js plugins.js
min: $(JS_FILES)
make concat $(JS_FILES)
$(UGLIFY) --output $(OUTPUT) $(OUTPUT)
concat: $(JS_FILES)
cat $^ > $(OUTPUT)
Now we’re getting somewhere, however the min task looks really ugly. Let’s put in some awesome sauce.
UGLIFY ?= uglify
OUTPUT ?= script.js
JS_FILES := index.js plugins.js
# For each file in JS_FILES, replace .js by .min.js and run it as the target
# with the original as a dependency.
# In plain English, iterate over each file and minimize as well as rename it.
min: $(JS_FILES:.js=.min.js)
# $@ is the target and $< is the dependency.
%.min.js: %.js
$(UGLIFY) --output $@ $<
concat: $(JS_FILES)
cat $^ > $(OUTPUT)
You better let that sink in for a bit. Next up is tying everything up in a nice bow.
UGLIFY ?= uglify
DIST ?= dist
OUTPUT ?= $(DIST)/script.js
JS_FILES := index.js plugins.js
# When you run make without a target, the first entry is the one to run,
# usually this is named `all` by convention.
all: concat min
# Rather than minifying every file, default to only minifying the final output.
min: $(OUTPUT:.js=.min.js)
# $@ is the target and $< is the dependency.
# When you put a `@` in front of a command, the stdout will be suppressed,
# making for a cleaner terminal.
%.min.js: %.js
@$(UGLIFY) --output $@ $<
concat: $(JS_FILES)
@cat $^ > $(OUTPUT)
# It's useful to have a cleanup task as well.
clean:
@rm -f $(DIST)/*
# Phony targets are targets that do not accept dependencies, it's good
# practice to define this as targets might have the same name as files from time
# to time and therefore create confusion. Also it's a small performance
# improvement.
.PHONY: clean all
Alright, that’s our makefile
.
How to use it
Concat and minify index.js and plugins.js into dist/script.min.js (these all do the same thing).
$ make
$ make all
$ make concat min
Specify the location of uglify
$ make UGLIFY=./node_modules/.bin/uglify
Concat some other files
$ make OUTPUT=temp.js concat js/*
Minify all files but put them in a separate directory
$ make DIST=minified min js/*
Clean up all the distribution files created
$ make clean
u-boot Makefile 完全解读 http://www.linuxidc.com/Linux/2013-04/83529.htm
实验平台上 Makefile 详细的解释 http://www.linuxidc.com/Linux/2014-01/94827.htm
Makefile 之 Linux 内核模块的 Makefile 写法分析 http://www.linuxidc.com/Linux/2013-06/85842.htm
Makefile 之写 demo 时的通用 Makefile 写法 http://www.linuxidc.com/Linux/2013-05/84679.htm
Makefile 之大型工程项目子目录 Makefile 的一种通用写法 http://www.linuxidc.com/Linux/2013-05/84678.htm
本文永久更新链接地址:http://www.linuxidc.com/Linux/2015-03/115251.htm