Search code examples
rubyrake

Rake rules to generate multiple targets from single source/dependency


I have a Rakefile as follows -

src_files = Rake::FileList["*.src"]
dst_files = src_files.ext 'dst'

task :default => dst_files

rule '.dst' => '.src' do |task|
  sh "cmd -o #{task.name} -i #{task.source}"
end

This Rakefile can find all .src files and generate corresponding .dst files.

Now, From list of .src files say file_a.src, file_b.src, file_c.src, I want -

  • file_a.src to create file_a.dst (works with current rule)
  • file_b.src to create file_b.dst (works with current rule)
  • file_c.src to create file_c1.dst, file_c2.dst and file_c3.dst (?!)

Question is -

How can I write rules to create files file_c<n>.dst from file_c.src?

-- where, n is array of numbers.


Solution

  • Do you need a rule for it? You may try to create multiple file tasks for it:

    n = 1..6   #Your n-Array
    
    n.each do |i|
      targetfile = 'file_c%i.dst' % i                 #Define the file to be created
      desc 'Create %s based n %s' % [ targetfile, 'file_c.src']
      file  targetfile => 'file_c.src' do |task|      #Define task to create targetfile
        puts "cmd1 -o #{task.name} -i #{task.source}" #Command to create targetfile
      end
    end
    

    In my tests I had no problem to combine it with the already defined rule.

    Below my complete testcode:

    require 'rake'
    src_files = Rake::FileList["*.src"]
    dst_files = src_files.ext 'dst'
    
    task :default => dst_files
    
    def build_dst(dst, src)
      puts "cmd -o #{dst} -i #{src}" #Command to create targetfile
      File.open(dst,'w'){|f|}        #Dummy to simulate generation
    end  
    
    rule '.dst' => '.src' do |task|
      build_dst task.name, task.source
    end
    
    N = 1..6  #array of numbers.
    
    N.each do |i|
      targetfile = 'file_c%i.dst' % i            #Define the file to be created
      desc 'Create %s based n %s' % [ targetfile, 'file_c.src']
      file  targetfile => 'file_c.src' do |task| #Define task to create targetfile
        build_dst task.name, task.source
      end
    end
    
    #Make dummy-sources.
    File.open('file_c.src','w'){|f|}
    File.open('x.src','w'){|f|}
    
    Rake.application['x.dst'].invoke
    Rake.application['file_c3.dst'].invoke
    

    You will see, the commands are exectuted as expected:

    cmd -o x.dst -i x.src
    cmd -o file_c3.dst -i file_c.src
    

    One addition - out of the scope of your question: I have some problems to see a real use case of your question.

    If the command to generate file_c<n>.dst depends only on the same sourcecode, then the generated dst-files would be the same - you could just copy the result. I would expect some other differences in dependecies.

    If your file_c<n>.dst depends an file_c<n>.src and file_c.src then you could use something like:

    require 'rake'
    
    rule '.dst' => '.src' do |task|
      puts "cmd -o #{task.name} -i #{task.prerequisites}" #Command to create targetfile
      File.open(task.name,'w'){}        #Dummy to simulate generation
    end
    
    #Add additional prerequsites (cold also defined generic)
    file 'file_c3.dst' => 'file_c.src'
    
    #Make dummy-sources.
    #~ File.open('file_c.src','w'){|f|}
    #~ File.open('file_c3.src','w'){|f|}
    
    Rake.application['file_c3.dst'].invoke
    

    I add additional prerequisites and replaced task.source by task.prerequisites.