我有一个 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
有没有办法像调用方法一样调用任务?或者我怎样才能达到类似的效果?
Rake::Task["build"].invoke
的东西比使用 system rake build
的性能要高得多,因为它不必创建新线程并加载 Rails 环境,而 system rake build
确实必须这样做。
如果您需要将任务用作方法,那么使用实际方法怎么样?
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
这首先重置任务的 already_invoked 状态,然后允许任务再次执行,依赖关系和所有:Rake::Task["build"].reenable Rake::Task["build"].invoke
请注意,除非重新启用,否则已调用的依赖项不会自动重新执行。在 Rake >= 10.3.2 中,您也可以使用以下命令重新启用它们:Rake::Task["build"].all_prerequisite_tasks.each(&:reenable)
例如:
Rake::Task["db:migrate"].invoke
task :build_all do
[ :debug, :release ].each do |t|
$build_type = t
Rake::Task["build"].reenable
Rake::Task["build"].invoke
end
end
那应该可以解决您的问题,我自己也需要同样的东西。
task :invoke_another_task do
# some code
Rake::Task["another:task"].invoke
end
task :build_all do
[ :debug, :release ].each do |t|
$build_type = t
Rake::Task["build"].execute
end
end
如果您希望每个任务都运行而不考虑任何失败,您可以执行以下操作:
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
我建议不要创建一般的调试和发布任务,如果项目真的是被编译的东西,因此会产生文件。正如您所说,您应该使用在您的示例中非常可行的文件任务,即您的输出进入不同的目录。假设您的项目只是使用 gcc 将 test.c 文件编译为 out/debug/test.out 和 out/release/test.out,您可以像这样设置您的项目:
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 文件)。如果您想触发发布构建或调试构建,您可以轻松完成所有任务。这个例子包括一种方法来定义调试和发布版本之间的细微差别。无需重新启用使用全局变量参数化的构建任务,因为现在不同的构建具有不同的任务。构建任务的代码重用是通过重用代码来定义构建任务来完成的。看看循环如何不执行两次相同的任务,而是创建任务,以后可以触发(通过 all-task 或在 rake 命令行上选择其中一个)。
Rake::Task['db:reset'].invoke
Rake::Task['with:args'].invoke("pizza")
ENV['VERSION'] = '20110408170816'; Rake::Task['db:migrate'].invoke
有关详细说明,请参阅 here。#reenable()
不会重新启用 pre-req,并且需要它。 This addition 到 Rake (>= 10.3.2),#all_prerequisite_tasks()
将迭代所有任务,包括 pre-req 的 pre-req 的。所以,Rake::Task[task].all_prerequisite_tasks.each &:reenable
rake db:reset db:migrate
上)。你能做类似的事情吗:Rake::Task["db:reset", "db:migrate"].invoke