为什么要有 Rake?

为什么要有 Rake?

容我先声明:我从来没想过要写这段代码。我不确定它是否真有用,也不确定有没有人会对它感兴趣。只能说,Why(Ruby 社区有名的“why the lucky stiff”)的洋葱卡车那天一定经过了俄亥俄河谷。

我在说什么?——一个用 Ruby 写的 Make。

看,我已经能感觉到你在皱眉了,我也同意:世界确实不需要再来一个 “make” 的翻版。我们已经有了 “ant”,还不够吗?

事情始于昨天。我帮同事修项目里的一个 Makefile。问题本身并不复杂,但聊着聊着我开始抱怨 make 的某些缺点。比如,在我的某个 Makefile 里,我想动态地算出一个文件名,不得不写点简单脚本(用 Ruby)才能搞定。“要是能在 Makefile 里直接用 Ruby 就好了,” 我说。

同事(最近刚迷上 Ruby)也觉得不错,但想知道那会长什么样。于是我在白板上随手画了:

task "build" do
  java_compile(...args, etc ...)
end

“task 函数会把 ‘build’ 注册成一个目标,随后的块就是当构建系统判断该执行 build 时真正跑的动作。”

我们都觉得挺酷,但从头写一个 make 工作量太大,话题就此结束。

……然而我脑子里挥之不去。要让上面那段代码真的像 make 那样跑起来,到底缺什么?嗯,需要注册任务、需要声明依赖、需要触发流程。嘿!要是……十五分钟后,我就得到了一个能跑的原型,带依赖、带动作,完整实现了 make 的惊人功能,却只写了一页纸的 Ruby。我俩看着代码哈哈大笑:区区几十行就复刻了 make 的大部分本事,Ruby 的威力把我们震住了。

但它还没实现 make 的全部特性,尤其是“按时间戳判断是否过期”的文件依赖(某个文件若比它的先决文件旧就要重新生成)。显然,这会很痛苦,于是 Ruby Make 只能算是个有趣的小实验。

……然而走回工位的路上,我又开始想:文件依赖到底需要什么?可恶,我又上钩了。再加一个新类、两个新方法,文件/时间戳依赖就搞定了。

现在我彻底上瘾。昨晚(看《犯罪现场调查》时)我把代码又揉了揉、理了理,最后成了一个 100 行的 make 替代品,放在:

  • doc/proto_rake.rdoc

至于名字——我在白板上写完示例时,同事大叫:“哦!完美名字:Rake!懂吗?Ruby-make → Rake!” 他说想象任务像落叶,Rake 会把它们耙起来……总之,名字就这么定了。

几个快速示例:

简单任务:删除备份文件

task :clean do
  Dir['*~'].each { |fn| rm fn rescue nil }
end

任务名用符号(比引号省敲几下,当然你愿意也可以用字符串)。Rake 直接把 FileUtils 模块的方法混进来,所以 rm 随手可用。rescue nil 忽略删不掉的错误。

跑它只需敲 rake clean。Rake 会自动在当前目录(或上层目录)找 Rakefile,并执行命令行指定的目标;如果没给目标,就执行默认任务 default

带依赖的任务:

task :clobber => [:clean] do
  rm_r "tempdir"
end

:clobber 依赖 :clean,所以先跑 :clean,再跑 :clobber

文件型任务用 file,名字代表真实文件,只有当文件不存在或比先决文件旧时才会执行。示例:把 hello.cc 编译成 hello.o:

file "hello.cc"
file "hello.o" => ["hello.cc"] do |t|
  srcfile = t.name.sub(/\.o$/, ".cc")
  sh %{g++ #{srcfile} -c -o #{t.name}}
end

我一般用字符串给文件任务命名,因为文件名里可能有符号打不出来的字符,也更醒目。

如果每个文件都手写 task 就太烦了。我打算搞一套库,比如:

require 'rake/ctools'
Dir['*.c'].each { |fn| c_source_file(fn) }

c_source_file 会自动生成编译该 C 文件所需的所有任务。类似的库还能写一大堆。

就这些。目前没有文档(除了这封信)。有人感兴趣吗?有,我就继续整理、写文档、发到 RAA;没有,就让它继续当一个有趣的练习,纪念 Ruby 的魔力。

为什么 Ruby 程序员可能会喜欢 Rake?也许因为:

  • 没有古怪的 make 语法(只有古怪的 Ruby 语法:-)

  • 不用编辑或阅读 XML(咳咳,ant)

  • 构建脚本跨平台

  • 只要 Ruby 能跑的地方就能跑,不需要系统自带 make。如果不用 sh 而用 ftools 之类,就能做到纯 Ruby 跨平台。而且 Rake 只有 100 行,随手就能塞进项目里。

好了,碎碎念到此为止。正如我开头所说,我真没打算写这段代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南姜先生

Give me a coffe

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值