Pregunta

I've got a helper class that scans my entire project directory and collects a list of source files and the corresponding (target) object files. The dependencies on the compile task is defined after scanning the source directory as shown below.

CLEAN.include(FileList[obj_dir + '**/*.o'])
CLOBBER.include(FileList[exe_dir + '**/*.exe'])

$proj = DirectoryParser.new(src_dir)

$proj.source_files.each do |source_file|
  file source_file.obj_file do
    sh "gcc -c ..."
  end
end

$proj.obj_files.each do |obj_file|
  task :compile => obj_file
end

task :compile do
end

Since $proj is global, the DirectoryParser.new() is invoked when any of the tasks are called including clean and clobber. This makes the clean and clobber tasks slow and that is not desirable.

To get around the problem I moved all the generation of File dependencies into the default task. This makes my clean and clobber tasks fast, however, I can't call my compile or link tasks independently now.

CLEAN.include(FileList[obj_dir + '**/*.o'])
CLOBBER.include(FileList[exe_dir + '**/*.exe'])

task :compile => $proj.source_files do   # Throws error!
end

task :default => do
  $proj = DirectoryParser.new(src_dir)

  $proj.source_files.each do |source_file|
    file source_file.obj_file do
      sh "gcc -c ..."
    end
  end

  $proj.obj_files.each do |obj_file|
    task :compile => obj_file
  end

  ... compile
  ... link
  ... execute
end

How do I get around this problem? I am sure someone has previously encountered a similar problem. I'd appreciate any help.

¿Fue útil?

Solución 2

I managed to get around this problem elegantly by using the Singleton design pattern and moving away from using Rake file/task dependencies completely. DirectoryParser is now a singleton class (by mixing in Ruby's built-in 'singleton' library)

CLEAN.include(FileList[obj_dir + '**/*.o'])
CLOBBER.include(FileList[exe_dir + '**/*.exe'])

task :compile do
  $proj = DirectoryParser.instance
  $proj.source_files.each do |source_file|
      sh "gcc -c ..." unless uptodate?(obj_file, source_file)
  end
end

task :link do
  $proj = DirectoryParser.instance
  ...
end

Now my clean/clobber tasks are fast and I can still call compile/link tasks independently.

Otros consejos

You could try a two step approach.

Create a new task generate_dependencies. This task builds a (static) rake file with your dependencies and actions.

This generated rakefile can be loaded in your rake file.

Some sample code (untested):

GENERATED = 'generated_dependencies.rb'

task :generate_dependencies do
  $proj = DirectoryParser.new(src_dir)

  File.open(GENERATED, 'w') do |f|
    $proj.source_files.each do |source_file|
      f << <<-code
      file #{source_file.obj_file} do
        sh "gcc -c " #etc.
      end
      code
    end

    $proj.obj_files.each do |obj_file|
      f << "task :compile => #{obj_file}"
    end

    #~ ... compile
    #~ ... link
    #~ ... execute
  end
end

require GENERATED

Now you have two steps:

  1. create an empty 'generated_dependencies.rb' (so you get no error when you call the script the first time)
  2. call rake generate_dependencies
  3. Check the generated file - if it's not good, change the generator ;)
  4. call rake compile or rake link (or rake if you want to use the default task) ... - the dependencies are defined in the generated file.

    • When something changes (new files), continue from step 2.
    • If the structure stays the same (no new files, only code changes) you need only step 4.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top