简介
简单而言,Rake是一个由ruby编写的build工具。
DSL
Rake是由ruby实现的,它的rakefile完全是由ruby语法定义的,所以它是一种内部DSL--基于另一种语言(宿主语言)编写的DSL。
Dependency Based Programming
Rake跟ant和make一样,是一种Dependency Based Programming。
Dependency Based Programming是一种基于依赖的编程方法,它的一条原则是依赖链中的任何任务只执行一次。
task :codeGen do # do the code generation end task :compile => :codeGen do #do the compilation end task :dataLoad => :codeGen do # load the test data end task :test => [:compile, :dataLoad] do # run the tests end
在上面这个例子中,test依赖于compile和dataLoad两个task,而compile和dataLoad都分别依赖于codeGen。当执行test这个task的时候,首先会执行codeGen(但只是一次),再执行compile和dataLoad(执行的顺序跟定义顺序无关)。
Task
Rake的task主要分类为regular task和file task两类。
Regular task类似于ant中的task,而file task类似于make中的task。
上面那个例子就是regular task,再让我们来看一下file task的例子:
file 'main.o' => ["main.c", "greet.h"] do sh "cc -c -o main.o main.c" end file 'greet.o' => ['greet.c'] do sh "cc -c -o greet.o greet.c" end file "hello" => ["main.o", "greet.o"] do sh "cc -o hello main.o greet.o" end
File task创建的目的是为了方便执行如编译等任务。因为在执行编译任务时,并不需要每次都编译所有文件,而只需编译那些还未被编译或者是经过修改的文件。
如上面那个例子中所示,File task的前置条件就是一些文件,而是否执行当前任务的前提就是:当前任务名称中的文件不存在或者它比前置条件中的文件要老。
比如"main.o"任务,它的执行条件是:"main.o"文件不存在,或者"main.c"、"greet.h"中的任一文件要比"main.o"文件要新。(这里的新老比较的是文件的最后修改时间)
lib
Rake的标准库非常丰富,有一些常用的task,这使得rakefile的编写变得更加简单。
调用
Rake任务通过命令行调用, 具体请见:http://docs.rubyrake.org/user_guide/chapter02.html
其它
1. Rule: 为一些类似的task,我们希望可以把它抽象出来。Rule的存在就是为解决这个问题的。
比如我们尝试调用"mycode.o"这个task,但发现并没有这个task的定义存在。那么,rake就会尝试去寻找可以匹配这个任务的rule。然后发现有这样一条rule存在:
rule '.o' => ['.c'] do |t| sh "cc #{t.source} -c -o #{t.name}" end
这条rule会匹配所有以".o"结尾的task,但它有一个前提:必须有一个相同名字,而且以".c"结尾的文件存在。所以,如果rake找到了"mycode.c"文件,它就会自动创建一个把"mycode.c"编译成"mycode.o"的任务。
2. Call one task from inside another task
有时候,我们希望一个task在另一个task运行中的某个环节执行,那么需要在一个task的执行中,而不是前置,去调用另一个task。
task :primary do Rake::Task[:secondary].invoke end task :secondary do puts "Doing Secondary Task" end
Secondary task的执行和其它task无异,secondary task的前置task也会先执行。但最需要注意的一点是,如果secondary task在之前已经被执行过,那么就不会再执行,即使如这样显示的invoke(遵循Dependency Based Programming的原则)。
如果你确实想无论如何都再次执行secondary task,那么就跳出task的范畴,用ruby方法来代替secondary task吧。
Reference
Rake API: http://rake.rubyforge.org/
User Guide: http://docs.rubyrake.org/user_guide/index.html
Using the Rake Build Language: http://martinfowler.com/articles/rake.html
2 楼 Firede 2009-12-31 02:24
1 楼 netfork 2009-07-20 00:07