原创作者: andyhu1007   阅读:2168次   评论:2条   更新时间:2011-05-26    

简介

 

简单而言,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 条 请登录后发表评论
2 楼 Firede 2009-12-31 02:24
很实用,有帮助。
1 楼 netfork 2009-07-20 00:07
写的真好,学到了。

发表评论

您还没有登录,请您登录后再发表评论

文章信息

Global site tag (gtag.js) - Google Analytics