Как запускать задачи Rake из задач Rake?
У меня есть Rakefile, который компилирует проект двумя способами в соответствии с глобальной переменной $build_type
, которая может быть :debug
или :release
(результаты хранятся в отдельных каталогах):
task :build => [:some_other_tasks] do
end
Я хочу создать задачу, которая по очереди компилирует проект с обеими конфигурациями, примерно так:
task :build_all do
[ :debug, :release ].each do |t|
$build_type = t
# call task :build with all the tasks it depends on (?)
end
end
Есть ли способ вызвать задачу, как если бы это был метод? Или как я могу добиться чего-то подобного?
Ответов (7)7
Я бы посоветовал не создавать общие задачи отладки и выпуска, если проект действительно компилируется и приводит к файлам. Вам следует использовать файловые задачи, что вполне выполнимо в вашем примере, поскольку вы заявляете, что ваш вывод попадает в разные каталоги. Скажем, ваш проект просто компилирует файл test.c в out / debug / test.out и out / release / test.out с помощью gcc, вы можете настроить свой проект следующим образом:
WAYS = ['debug', 'release']
FLAGS = {}
FLAGS['debug'] = '-g'
FLAGS['release'] = '-O'
def out_dir(way)
File.join('out', way)
end
def out_file(way)
File.join(out_dir(way), 'test.out')
end
WAYS.each do |way|
desc "create output directory for #{way}"
directory out_dir(way)
desc "build in the #{way}-way"
file out_file(way) => [out_dir(way), 'test.c'] do |t|
sh "gcc #{FLAGS[way]} -c test.c -o #{t.name}"
end
end
desc 'build all ways'
task :all => WAYS.map{|way|out_file(way)}
task :default => [:all]
Эту настройку можно использовать как:
rake all # (builds debug and release)
rake debug # (builds only debug)
rake release # (builds only release)
Это немного больше, чем просили, но показывает мою точку зрения:
- выходные каталоги создаются по мере необходимости.
- файлы перекомпилируются только при необходимости (этот пример верен только для простейшего из файлов test.c).
- у вас есть все задачи под рукой, если вы хотите запустить сборку выпуска или сборку отладки.
- этот пример включает способ определения небольших различий между отладкой и сборкой выпуска.
- нет необходимости повторно включать задачу сборки, параметризованную с помощью глобальной переменной, потому что теперь разные сборки имеют разные задачи. повторное использование кода задачи сборки выполняется путем повторного использования кода для определения задач сборки. посмотрите, как цикл не выполняет одну и ту же задачу дважды, а вместо этого создает задачи, которые позже могут быть запущены (либо с помощью общей задачи, либо путем выбора одной из них в командной строке rake).
Если вы хотите, чтобы каждая задача выполнялась независимо от сбоев, вы можете сделать что-то вроде:
task :build_all do
[:debug, :release].each do |t|
ts = 0
begin
Rake::Task["build"].invoke(t)
rescue
ts = 1
next
ensure
Rake::Task["build"].reenable # If you need to reenable
end
return ts # Return exit code 1 if any failed, 0 if all success
end
end
Если вам нужно, чтобы задача вела себя как метод, как насчет использования реального метода?
task :build => [:some_other_tasks] do
build
end
task :build_all do
[:debug, :release].each { |t| build t }
end
def build(type = :debug)
# ...
end
Если вы предпочитаете придерживаться rake
русских идиом, вот ваши возможности, составленные из прошлых ответов:
Это всегда выполняет задачу, но не выполняет ее зависимости:
Rake::Task["build"].execute
Этот выполняет зависимости, но он выполняет задачу только в том случае, если она еще не была вызвана:
Rake::Task["build"].invoke
Это сначала сбрасывает состояние уже_invoked задачи, позволяя выполнить задачу снова, зависимости и все остальное:
Rake::Task["build"].reenable Rake::Task["build"].invoke
Обратите внимание, что уже вызванные зависимости не выполняются автоматически повторно, если они не включены повторно. В Rake> = 10.3.2 вы можете использовать следующее, чтобы снова включить их:
Rake::Task["build"].all_prerequisite_tasks.each(&:reenable)