Указание предварительных условий файла для задачи Rake - PullRequest
1 голос
/ 27 ноября 2011

У меня есть вспомогательный класс, который сканирует весь каталог моего проекта и собирает список исходных файлов и соответствующих (целевых) объектных файлов.Зависимости от задачи компиляции определяются после сканирования исходного каталога, как показано ниже.

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 () вызывается при вызове любой из задач, включая clean и clobber.Это замедляет выполнение задач clean и clobber, что нежелательно.

Чтобы обойти проблему, я перенес все поколения зависимостей файлов в задачу по умолчанию.Это ускоряет выполнение моих задач clean и clobber, однако теперь я не могу независимо вызывать мои задачи компиляции или компоновки.

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 ]

3 голосов
/ 27 ноября 2011

Вы можете попробовать двухэтапный подход.

Создать новое задание 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. создайте пустой файл «generate_dependencies.rb» (чтобы при первом вызове скрипта не возникало ошибок)
  2. звонок rake generate_dependencies
  3. Проверьте сгенерированный файл - если это не хорошо, замените генератор;)
  4. вызов rake compile или rake link (или rake, если вы хотите использовать задачу по умолчанию) ... - зависимости определены в сгенерированном файле.

    • Когда что-то меняется (новые файлы), продолжайте с шага 2.
    • Если структура остается прежней (нет новых файлов, только изменения кода), вам нужен только шаг 4.
0 голосов
/ 25 августа 2012

Мне удалось обойти эту проблему элегантно, используя шаблон проектирования 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 выполняются быстро, и я все еще могу вызывать задачи компиляции / компоновки независимо.

...