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() が呼び出されます。これによりおよびタスクが遅くなり、望ましくありません。cleanclobbercleanclobber

この問題を回避するために、ファイルの依存関係のすべての生成をデフォルト タスクに移動しました。これにより、タスク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

2段階のアプローチを試すことができます。

新しいタスクを作成します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

次の 2 つのステップがあります。

  1. 空の「 generated_dependencies.rb 」を作成します(スクリプトを初めて呼び出すときにエラーが発生しないようにします)
  2. 電話rake generate_dependencies
  3. 生成されたファイルを確認してください - うまくいかない場合は、ジェネレータを変更してください ;)
  4. rake compileまたはrake link(またはrakeデフォルトのタスクを使用する場合) ... を呼び出します - 依存関係は生成されたファイルで定義されます。

    • 何かが変更された場合 (新しいファイル)、手順 2 から続行します。
    • 構造が同じままである場合 (新しいファイルはなく、コードの変更のみ)、ステップ 4 のみが必要です。
于 2011-11-27T12:39:11.257 に答える
0

シングルトンデザインパターンを使用し、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 に答える