6
votes

I want my projects top level Rakefile to build things using rakefiles deeper in the tree; i.e. the top level rakefile says how to build the project (big picture) and the lower level ones build a specific module (local picture).

There is of course a shared set of configuration for the minute details of doing that whenever it can be shared between tasks: so it is mostly about keeping the descriptions of what needs building, as close to the sources being built. E.g. /Source/Module/code.foo and cie should be built using the instructions in /Source/Module/Rakefile; and /Rakefile understands the dependencies between modules.

I don't care if it uses multiple rake processes (ala recursive make), or just creates separate build environments. Either way it should be self-containable enough to be processed by a queue: so that non-dependent modules could be built simultaneously.

The problem is, how the heck do you actually do something like that with Rake!? I haven't been able to find anything meaningful on the Internet, nor in the documentation. I tried creating a new Rake::Application object and setting it up, but whatever methods I try invoking, only exceptions or "Don't know how to build task ':default'" errors get thrown. (Yes, all rakefiles have a :default). Obviously one could just execute 'rake' in a sub directory for a :modulename task, but that would ditch the options given to the top level; e.g. think of $(MAKE) and $(MAKEFLAGS).

Anyone have a clue on how to properly do something like a recursive rake?

4

4 Answers

3
votes

you can require rake files from other rake files and run the tasks from the required file.

put this in rakefile.rb:

require 'foo/rakefile.rb'

task :default => [:bar]

put this in foo/rakefile.rb:

task :bar do
  puts "baz"
end

run the root level rakefile and it will print "baz" to the screen. you should be able to organize your rake files and common code however you want using this idea

2
votes

As mentioned in my earlier post, here is the code snippet that supports almost like recursive rake behavior including options passing, dry-run, trace, top-level-task.

rake:

#!/usr/bin/env ruby

begin
  require 'rubygems'
  gem 'rake'
rescue LoadError
end

$sub_directories = []
$top_level_task_provided__skip_subdir = 0
module Rake
   REDUCE_COMPAT = true if ARGV.include?("--reduce-compat")
   RAKE_OPTS = ARGV.clone.join(" ") 
   module DSL
     def subdirs dirs
        puts "DIRS: #{dirs}"
        $sub_directories = dirs
     end
   end
end

require 'rake'

Rake.application.standard_exception_handling do
   Rake.application.init
   $top_level_task_provided__skip_subdir = 1 if Rake.application.top_level_tasks.size >= 1 and Rake.application.top_level_tasks[0] != "default"
   Rake.application.load_rakefile
   if Rake.application.tasks.size == 0 and $sub_directories.size != 0 then
      desc "Default task when only subdirs is present in a rakefile"
      task :default do
         puts "Default subdir task"
      end
   end
   Rake.application.top_level
end

if $top_level_task_provided__skip_subdir == 0 then
    $sub_directories.each do |d|
        unless rake_system("cd #{d} && pwd && ruby #{File.expand_path $0} #{Rake::RAKE_OPTS}") then
            exit(1)
        end
    end
end
0
votes

If I understood well your problem is that you need to call a Rake task within another Rake task from a different RakeFile.

You can built your needed tasks in /Source/Module/Rakefile the way you need it and make another Rakefile in /Rakefile and run tasks that way.

desc 'Description'
task :foo do
    %x[rake -f /Source/Module/RakeFile foo:bar]
end

-f let you define where the Rakefile is located

You could also specify where your rakelib folder is located with -R.

rake -f /path/to/Rakefile -R /path/to/rakelib foo:bar

I hope this will help you.

0
votes

I have also the similar requirement and created the following function

rakeutils.rb:

def subdirs dirs
    dirs.each do |d|
      task d do |t|
        sh("cd #{t.name} && pwd && rake")
      end
    end
    task :default => dirs
end

and in Rakefiles, wherever i want to have this feature, i just include it... for eg

Rakefile:

require 'rakeutils'

task :test1 do
  puts "Hi"
end

task :default => :test1
subdirs ["ab", "cd"]

regarding options, i didnt find any automatic way of passing them...other than editing "rake" and capturing the options before it is consumed by the rake's option processing