rake prepare gem

R

Roeland Moors

I'm using rake to create a gem, but I have some questions.

Before creating a gem in Rake i would like to copy some files to
a different directory and then create the package.

I tried something like this:

task :gem => [:prepare_gem]

task :prepare_gem do
# do stuff here
gem_task.gem_spec.files = files.to_a
end

But the problem is that the prepare_gem is executed AFTER the gem
task. Is this normal?
 
J

Jim Weirich

Roeland Moors said:
I'm using rake to create a gem, but I have some questions.
Great!

Before creating a gem in Rake i would like to copy some files to
a different directory and then create the package.

I tried something like this:

task :gem => [:prepare_gem]

task :prepare_gem do
# do stuff here
gem_task.gem_spec.files = files.to_a
end

But the problem is that the prepare_gem is executed AFTER the gem
task. Is this normal?

Actually, yes. First the explain why, and then the fix ...

Rake invokes a task, it will first invoke all the dependencies (aka
prerequisites) of that task before it executes the actions (the do/end
block) of that task. So you are guaranteed that the actions of a task
will execute only after the actions of all its all dependencies are
executed. You have no guarantee that the dependencies will be executed in
any particular order.

When debugging problems like this, the -P option on rake is your friend.
Here is the output for your rakefile (non-relevant portions elided).

rake gem
pkg/demo-0.0.0.gem
prepare_gem
rake pkg/demo-0.0.0.gem
pkg
a
b
rake prepare_gem

(NOTE: I created a package named 'demo' with version 0.0.0 and it depends
on two files named 'a' and 'b'. I don't know what you were using.)

We can see that the :gem task depends upon the "pkg/demo-0.0.0.gem" file
task which is where the gem file is actually created. Since :gem depends
on "pkg/demo-0.0.0.gem", the gem file will be built before the :gem
actions are executed. Also the actions of :prepare_gem will be executed
before :gem's actions. But since :prepare_gem and "pkg/demo-0.0.0.gem"
are sibling dependents of :gem, their order is not specified, hence the
gem is built before the :prepare_gem actions are performed.

The Fix
-------

You need to specify that :prepare_gem is a dependency of
"pkg/demo-0.0.0.gem" instead of :gem. To to this, add the following line
to your Rakefile ...

file "pkg/demo-0.0.0.gem" => [:prepare_gem]

Now, the proper dependencies are declared and prepare_gem is guaranteed to
execute before the gem file is built.

The answer to almost any problem with Rake dependencies is to correctly
declare the real dependencies in the project.

An aside: It is tempting to just move the "task :gem => [:prepare_gem]"
task before the creation of the gem package task. This makes sure that
:prepare_gem comes first in the list of dependencies for :gem. And this
works because all other things being equal, rake will execute
dependencies in the order discovered. However, this is very fragile.
Other dependencies can easily override the "in order rule".
 
R

Roeland Moors

Roeland Moors said:
I'm using rake to create a gem, but I have some questions.
Great!

Before creating a gem in Rake i would like to copy some files to
a different directory and then create the package.

I tried something like this:

task :gem => [:prepare_gem]

task :prepare_gem do
# do stuff here
gem_task.gem_spec.files = files.to_a
end

But the problem is that the prepare_gem is executed AFTER the gem
task. Is this normal?

Actually, yes. First the explain why, and then the fix ...
[snip]

Thanks a lot for the detailed information.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top