1

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

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是全局的,当调用任何任务时都会调用 DirectoryParser.new() ,包括cleanand clobber。这使得cleanandclobber任务变慢,这是不可取的。

为了解决这个问题,我将所有文件依赖项的生成都移到了默认任务中。这使我的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

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

4

2 回答 2

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 步。
于 2011-11-27T12:39:11.257 回答
0

通过使用 Singleton 设计模式并完全摆脱使用 Rake 文件/任务依赖项,我设法优雅地解决了这个问题。DirectoryParser 现在是一个单例类(通过混合 Ruby 的内置“单例”库)

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

现在我的清理/破坏任务很快,我仍然可以独立调用编译/链接任务。

于 2012-08-25T07:42:12.670 回答