Thursday, February 16, 2006

Add dependency support to custom rake tasks

I previously wrote about creating a NUnitTask for Rake. The NUnitTask is based on the PackageTask that comes standard with Rake. I assumed that the PackageTask would have support for adding dependencies at construction time. This turned out to be a false assumption. To add a PackageTask and dependency for that task they need to be declared separately.
Rake::PackageTask.new "foo","1.2.3" do |pkg|
pkg.need_zip = true
pkg.package_files.include("build_helpers/*.rb")
end
task :package => :test
I had expected it to work much like a standard task and dependency.
#this will not work
Rake::PackageTask.new "foo","1.2.3" => :init do |pkg|
pkg.need_zip = true
pkg.package_files.include("build_helpers/*.rb")
end
Upon discovery, I decided to alter NUnitTask to take a dependency in the expected manner. The only change required is to alter the assignment of the name variable.
def initialize(name=:nunit)
@name = name
..
end
Becomes
def initialize(params=:nunit)
@name = case params
when Hash
task params.keys[0] => params[params.keys[0]]
params.keys[0]
else
params
end
..
end
Hopefully, Jim Weirich can add the same capability to the next version of the Rake Tasks.

2 comments:

  1. Hi Jay,
    after reading your posts about rake I've started to convert my nant task in rake.
    I've create a CscTask and for the dependencies problem I've adopted this solution:

    require 'rake'
    require 'rake/tasklib'

    module Rake

    class CscTask < TaskLib
    # Name of the main, top level task. (default is :csc)
    attr_accessor :name, :task_dependencies, :out, :target, :sources, :resources, :references, :lib

    # Create an Csc task named csc. Default task name is +csc+.
    def initialize(name=:csc) # :yield: self
    @name = name
    @path_to_console = "csc.exe"
    yield self if block_given?
    define
    end

    # Create an Csc task named csc. Default task name is +csc+.
    def initialize(name=:csc, task_dependencies=[]) # :yield: self
    @task_dependencies = task_dependencies
    @name = name
    @path_to_console = "csc.exe"
    yield self if block_given?
    define
    end

    # Create the tasks defined by this task lib.
    def define
    task name => task_dependencies do
    sh "#{@path_to_console} #{out} #{target} #{sources} #{resources} #{references} #{lib}"
    end
    self
    end

    def out
    "/out:#{@out}" if @out
    end

    def target
    "/target:#{@target}" if @target
    end

    def sources
    "#{@sources.join(" ")}" if @sources
    end

    def resources
    #"/res:#{@resources}" if @resources
    end

    def references
    "/r:#{@references.join(";")}" if @references
    end

    def lib
    "/lib:#{@lib}" if @lib
    end
    end
    end

    ReplyDelete
  2. Hi Jay.

    I ran into this as well. I especially have a problem where my PackageTask does a Dir.chdir("somedir") inside it. I try to make that "somdir" exist via a directory task. But I can't make the package task depend on it. Even your trick with separating the package task from the task :package didn't work.
    Maybe I have to create a custom PackageTask.

    ReplyDelete

Note: Only a member of this blog may post a comment.