写一个漂亮Rakefile的方法

所属分类: 脚本专栏 / ruby专题 阅读数: 840
收藏 0 赞 0 分享

Rake 我就不再介绍了,Ruby 的 Make ,许多方面都比 Make 要更好用一些。和 Makefile 不同的是,Rakefile 本身其实就是一段 Ruby 代码,这样的好处有很多,一方面在 Rake 里面就可以很直接地做任何 Ruby 能做的事了,另一方面由于 Ruby 对 DSL 支持良好,所以 Rakefile 通常看起来也并不那么“代码”。

不过,代码始终是代码,Makefile 尚且可以写得很乱,Rakefile 要写乱就更容易了,幸运地是,Rake 提供了一些功能让我们可以来对 Rakefile 做一些组织工作。

其中之一就是 import 功能,把不同功能的 task 写到不同的文件中,例如,像这个样子:

复制代码 代码如下:

Rakefile
task/
  +-- doc.rake
  +-- compile.rake
  `-- deploy.rake

这样,在 Rakefile 里写上
复制代码 代码如下:

import("task/doc.rake")

这样的语句导入各个子任务即可,不同的任务写到不同的文件里面就不会一团糟了。而且,import 同 Ruby 自己的 require 不一样,import 并不是立即进行导入的,而是在整个 Rakefile 执行结束之后才全部导入,因此,可以在任意的地方写 import ,而不用担心依赖关系,需要共享的变量之类的只要在主 Rakefile 中定义了即可。

import 是组织不同的功能模块,除此之外,Rake 还允许我们对一些重复性的任务进行抽象,具体来说,就是自定义的 task 。通常情况下,我们使用 Rake 提供的通用 task 和文件 task 来构造我们需要完成的工作,除此之外,Rake 还自带了一些针对特殊任务的 task 类型,例如构建 rdoc 或者运行 test 等。实际上,一种任务就是一个普通的 Ruby 类,我们可以继承 Rake 里的 Task 类并重新定义相关的函数来实现自定义的 task 类型。不过,这样多少有些麻烦,实际上,很多时候我们要定义的任务都可以分解为一些小任务用内置的通用 task 和 file task 来实现的,这个时候可以用 Tasklib 来更方便地定义自定义的任务。

具体地来说,就是写一个类,继承自 Tasklib (虽然实际上只是约定而并不是必须的),然后在这个类的初始化函数里用 task 或者 file 来定义实际完成任务的子 task 即可。用一个实际的例子来说,比如说,我们可以定义一个 ErlcTask ,可以用来把一些 Erlang 文件编译到某个目录下,并在 clean 的时候自动能把编译出来的 .beam 文件清理掉:

复制代码 代码如下:

require 'rake'
require 'rake/clean'
require 'rake/tasklib'

class ErlcTask < Rake::TaskLib
  attr_accessor :name
  attr_accessor :sources
  attr_accessor :dest_dir
  attr_accessor :include_path
  attr_accessor :flags
  attr_accessor :extra_dep

  def initialize(name = :erlc)
    # default values
    if name.is_a? Hash
      @name = name.keys.first
      @extra_dep = name.values.first
    else
      @name = name
      @extra_dep = []
    end
    @sources = FileList[]
    @dest_dir = '.'
    @include_path = []
    @flags = "-W +warn_unused_vars +warn_unused_import"

    yield self if block_given?
    define
  end

 
  def define
    beams = @sources.pathmap(File.join(@dest_dir, '%n.beam'))

    include_path = Array(@include_path).map{|incl|"-I"+incl}.join(" ")

    directory @dest_dir
    beams.zip(@sources).each do |beam, source|
      file beam => source do
        sh "erlc -pa #{@dest_dir} #{@flags} #{include_path} -o #{@dest_dir} #{source}"
      end
    end

    task @name => beams + Array(@extra_dep)
    CLEAN.include(beams)
  end
end

首先定义一些 Task 相关的属性,在初始化函数里设置初值,然后调用 block 来填充实际的值,最后调用 define 函数,define 函数就使用 directory 、file 和 task 分别定义了建立目录、编译和清理的任务。如果了解 Ruby 和 Rake 的基本语法的话,应该很容易看明白了。

接下来把这个文件保存到某个 .rb 里,然后在 Rakefile 里 require 之,就可以这样写了:

复制代码 代码如下:

ErlcTask.new :compile do |t|
    t.sources = FileList['src/*.erl']
    t.dest_dir = '../ebin'
    t.include_path = '../include'
    t.extra_dep = :library
end

看起来就清爽多了!并且可以重复利用。  末了,顺便再感叹一下,虽然最近都是用 Python 用得多一些,但是每次再写 Ruby 都能感觉到写起来很舒服,这是基本不可能在 Python 里找到的感觉啊!

更多精彩内容其他人还在看

Ruby中用线程实现经典的生产者消费者问题代码实例

这篇文章主要介绍了Ruby中用线程实现经典的生产者消费者问题代码实例,本文直接给出实现代码和运行效果,需要的朋友可以参考下
收藏 0 赞 0 分享

Ruby中常用的字符串处理函数使用实例

这篇文章主要介绍了Ruby中常用的字符串处理函数使用实例,本文总结了Ruby中最常用的字符串处理函数,如返回字符串的长度、判断字符串中是否包含另一个串、字符串插入、字符串分隔、默认分隔符为空格等内容,需要的朋友可以参考下
收藏 0 赞 0 分享

Windows下ruby语言安装教程

这篇文章主要介绍了Windows下ruby语言安装教程,本文使用rubyinstaller提供的安装包安装,并给出图文说明,非常简单,需要的朋友可以参考下
收藏 0 赞 0 分享

ruby环境中自动编译sass教程

这篇文章主要介绍了ruby环境中自动编译sass教程,本文讲解了ruby环境的安装、sass环境的安装以及sass的常用编译命令使用示例,需要的朋友可以参考下
收藏 0 赞 0 分享

Ruby中相等性判断的4种方法

这篇文章主要介绍了Ruby中相等性判断的4种方法,本文讲解了“==” 最常见的相等性判断、“===” 用于 case 语句的相容判断、“equal?” 相同对象判断、“eql?” 对象 hash 值判断等内容,需要的朋友可以参考下
收藏 0 赞 0 分享

Rails中使用MySQL分区表一个提升性能的方法

这篇文章主要介绍了Rails中使用MySQL分区表一个提升性能的方法,本文总结出了一个简单的方法实现避免扫描全部的分区表,从而提升性能,需要的朋友可以参考下
收藏 0 赞 0 分享

Rails应用程序中同时修改操作冲突问题的解决方案

这篇文章主要介绍了Rails应用程序中同时修改操作冲突问题的解决方案,本文讲解使用Rails 的 乐观锁解决这个问题并给出了代码救命,需要的朋友可以参考下
收藏 0 赞 0 分享

Ruby中的p和puts的使用区别浅析

这篇文章主要介绍了Ruby中的p和puts的使用区别浅析,本文用一个实例讲解了它们之间的区别,并总结出结论,需要的朋友可以参考下
收藏 0 赞 0 分享

Ruby中的block、proc、lambda区别总结

这篇文章主要介绍了Ruby中的block、proc、lambda区别总结,本文讲解了yield 和 block call 的区别、block 和 proc、lambda 的区别、proc 和 lambda 的区别,需要的朋友可以参考下
收藏 0 赞 0 分享

Ruby的运算符和语句优先级介绍

这篇文章主要介绍了Ruby的运算符和语句优先级介绍,本文先是给出了一些小例子来验证运算符和语句优先级,然后总结出一个优先级表,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多