指定Rake任务的文件先决条件

时间:2011-11-27 07:39:54

标签: ruby rake rake-task rakefile

我有一个帮助程序类,它扫描整个项目目录并收集源文件列表和相应的(目标)目标文件。扫描源目录后定义编译任务的依赖关系,如下所示。

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

由于$proj是全局的,因此在调用包括cleanclobber的任何任务时会调用DirectoryParser.new()。这使得cleanclobber任务变慢,这是不可取的。

为了解决这个问题,我将所有生成的File依赖项都移到了默认任务中。这使我的cleanclobber任务变得很快,但是,我现在无法单独调用我的编译或链接任务。

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

如何解决这个问题?我相信有人之前遇到过类似的问题。我很感激任何帮助。

2 个答案:

答案 0 :(得分:3)

您可以尝试两步法。

创建新任务generate_dependencies。 此任务使用您的依赖项和操作构建(静态)rake文件。

这个生成的rakefile可以加载到你的rake文件中。

一些示例代码(未经测试):

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

现在您有两个步骤:

  1. 创建一个空的'generated_dependencies.rb'(因此第一次调用脚本时不会出错)
  2. 致电rake generate_dependencies
  3. 检查生成的文件 - 如果不合适,请更改生成器;)
  4. 调用rake compilerake link(或rake如果您要使用默认任务)... - 依赖项在生成的文件中定义。

    • 当某些内容发生变化时(新文件),请从步骤2继续。
    • 如果结构保持不变(没有新文件,只有代码更改),则只需要执行第4步。

答案 1 :(得分:0)

我设法通过使用Singleton设计模式并完全不使用Rake文件/任务依赖关系来优雅地解决这个问题。 DirectoryParser现在是一个单例类(通过混合Ruby的内置'singleton'库)

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

现在我的clean / clobber任务很快,我仍然可以独立调用编译/链接任务。