[Rake-devel] Environment changes in the beta

James M. Lawrence quixoticsycophant at gmail.com
Mon Mar 7 01:48:28 EST 2011

On Sat, Mar 5, 2011 at 3:36 PM, Jim Weirich <jim.weirich at gmail.com> wrote:
>  I would have never thought of just extending the actual top level "main" object.

Ha, you didn't have to divulge that. I assumed you thought of it but
that your focus was on 'import'.

My suggestion was a bit more drastic, though: it implicitly called for
the annihilation of environment.rb. There have been times when I, too,
have not realized that a change suddenly obsoletes a hunk of code :)
All of the following are now equivalent,

  Rake::Environment.run do
    task :a do
      p 'task a'

  Rake::DSL.environment do
    task :b do
      p 'task b'

  module Rake::Environment
    task :c do
      p 'task c'

  Rake::Environment.module_eval do
    task :d do
      p 'task d'

  task :default => [:a, :b, :c, :d]

Option c is clearly the winner, with d being needed for access to
top-level locals (probably uncommon). Aren't a and b vestigial
structures from the old 'import' workaround device?

But what is Rake::Environment doing now?

  module MyStuff
    extend Rake::DSL

    task :default do
      # ...

In my first email, I asked if an example like that in the readme could
replace the need for environment.rb. Meaning, rather than give users
an empty bucket (Rake::Environment), teach them how to make their own
bucket (MyStuff). At least _I_ would prefer a fresh module over

load_string also looks like a vestigial artifact. It's the same as
module_eval now.

  Rake::Environment.load_string %{
    task :x do
      p 'task x'

  Rake::Environment.module_eval %{
    task :y do
      p 'task y'

  task :default => [:x, :y]

(They are not quite the same; load_string uses eval() which treats
constants differently.)

Lastly there is load_rakefile, which is effectively


But this has the same problem shown in my first email on beta.1
Indeed running the examples from that email,

  % rake --version
  rake, version 0.9.0.beta.2

  % rake
  rake aborted!
  uninitialized constant #<Class:0x489f7c>::MyStuff::CONST_B

Ah, but what is that anonymous class? It's the load_string/module_eval
difference mentioned above. Rake::Environment is simultaneously a
named module and an anonymous module because eval() doesn't understand
that the module is really Rake::Environment. (In C terms,
rb_mod_module_eval calls eval_under while rb_f_eval does not.) But
this is moot because replacing load_string with module_eval gives the
equally undesirable

  uninitialized constant Rake::Environment::MyStuff::CONST_B

The constants in a Rakefile are placed inside Rake::Environment, but
since the Rakefile may require files, and since require starts a new
scope, it all goes to pot. The lesson from beta.1 is that Rakefiles
can't be sandboxed into Rake::Environment.

> I don't like the explicit test for JRuby (that means some Rakefile
> wouldn't run in JRuby, yuck). Instead I'm going to deprecate
> 'import' and promote the use of Rake.import.

'import' is not a built-in jruby method; it's only defined with
'require "jruby"', and that is only needed for jruby-specific things
like enabling/disabling ObjectSpace.

Additionally, jruby + Rake seems an unlikely choice for a build tool.
The launch time for jruby is excruciating in this context. JRuby is
aimed at the opposite use case where startup time is not important.
Does *anyone* regularly use jruby with Rake?

I would be interested to see a real-life example where jruby + Rake +
'require "jruby"' is needed. There are viable workarounds even if that
did happen. It's not immediately obvious to me that Rake should change
its API to accommodate that case. If Rake weren't the most popular gem
of all time with 15K downloads per day, the issue might be different.

More information about the Rake-devel mailing list