Search code examples
rubyrake

Rake, how to create a task with multiple inputs and one output?


We have a rails app, and we use webpack which takes multiple javascript files and outputs one single javascript file. It takes a long time to run, and I'd like to create a rake task for this. But being new to rake I need some help.

I'd like to use rake's build system so that I can get automatic checking of the time stamps between the input and output .js files. So that if any of the input files are newer than the output file it will execute webpack. Otherwise if the none of the input files are newer than the output file, than the task does nothing.

In MSBuild, this is a cakewalk and lightning fast. But in Ruby I'm kind of lost.

I'm guessing it might consist of writing file tasks, and looping through and making the one output file depend on the inputs. Or should I use a rule, like this?

outputfile = "~/foo.js"
inputfiles = Dir["~/**/*.js"]

rule outputfile => inputfiles do
  bin/webpack bla bla bla
end

Solution

  • You can use Rake::FileList to achieve this. Something like this:

    file "foo.js" => Rake::FileList["**/*.js"] do
      ...
    end
    

    And, I'm not sure whether rake allows to use ~ in paths, I believe a full path is required. Or just use a "#{Dir.home}/foo.js" rule.

    Then call it using:

    rake ~/foo.js
    

    And when you have multiple outputs:

    task :build => Rake::FileList["config1.xml", "config2.xml"] do  
      # all that stuff is run only when the FileList above is changed
      touch 'foo1.js'
      touch 'foo2.js'
      sh "compile foo3.js"
      sh "do-anything-else foo4.js"
    end
    

    Run it using:

    rake build