Created
January 20, 2012 21:02
-
-
Save noonat/1649543 to your computer and use it in GitHub Desktop.
Rake Quick Reference
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Rake Quick Reference | |
# by Greg Houston | |
# http://ghouston.blogspot.com/2008/07/rake-quick-reference.html | |
# ----------------------------------------------------------------------------- | |
# Running Rake | |
# ----------------------------------------------------------------------------- | |
# running rake from the command-line: | |
# rake --help | |
# --help shows all the command-line options, a few are listed here. | |
# rake | |
# (no arguments, runs the default task) | |
# rake uses the script: rakefile, Rakefile, rakefile.rb or Rakefile.rb | |
# rake will search parent directories for the file. | |
# rake -f build.rb | |
# -f specifies the rakefile file to run | |
# rake target target2 | |
# target and target2 are the names of the tasks to run (instead of default) | |
# rake -n | |
# -n shows a dry-run of which tasks would get called | |
# rake -T | |
# -T shows all task which have descriptions | |
# rake -P | |
# -P shows task dependencies | |
# ----------------------------------------------------------------------------- | |
# Tasks | |
# ----------------------------------------------------------------------------- | |
task :default => :target | |
# defines a task named :default | |
# rake will run :default when no other task is specified on the command line | |
# => :target, makes the task named :target a prerequisite | |
# rake will ensure prerequisite tasks have completed before invoking this task | |
task :target => :source | |
# defines a task named :target with prerequisite :source | |
# e.g. rake will ensure :source is invoked before :target | |
task :source => [:x, :y] | |
# defines a task named :source | |
# => [:x, :y] shows how to set multiple prerequisites | |
# all prerequisites must complete before this task will execute | |
# right now we have defined a chain of prerequisites | |
# :default => :target => :source => [:x, :y] | |
# invoking :default will first invoke :x, :y, :source, :target | |
task :a => :b | |
task :b => :a | |
# rake will raise an error if you invoke tasks with circular dependencies: | |
# Circular dependency detected: TOP => a => b => a | |
task :hello_world do | |
puts 'hello world!' | |
end | |
# task behavior is given as a block of code using "do ... end" | |
# dont use ruby's { } block syntax, precedence rules will break it | |
# when the task is invoked, the block of code is executed | |
task :target => :z do | |
# ruby code | |
end | |
# since :target is already defined | |
# +adds+ the prerequisite :z | |
# +adds+ code to execute when :target is invoked | |
# tasks in rake have a collection of dependencies | |
# and a collection of blocks to execute | |
task :target2 => :source | |
# defines :target2 which also depends on :source | |
# rake will only invoke :source once, even if both | |
# :target and :target2 are invoked | |
# tasks are only invoked once! | |
task :example_target do | |
puts Rake::Task[:target].inspect | |
# Rake::Task holds a collection of all tasks. Access a task using: [name] | |
puts Rake::Task[:target].investigation | |
# investigation displays some details about a task. | |
# useful for figuring out why a task was called or not. | |
end | |
task :target do |t| | |
puts t.name #=> target | |
puts t.class #=> Rake::Task | |
end | |
# task code blocks can accept an option argument (t in this example) | |
# which is a reference to the task object. | |
task :call_invoke do | |
Rake::Task[:target].invoke | |
end | |
# calling invoke on a task directly (not recommended). | |
# :target is only run once, even if invoke is called many times. | |
# calling invoke will execute the prerequisites of :target | |
task :call_execute do | |
Rake::Task[:target].execute( nil ) | |
end | |
# execute the task directly (not recommended). | |
# execute can run :target many times. | |
# calling execute will +not+ execute prerequisites. | |
task :example_failure do | |
raise 'i do not like green eggs and ham!' | |
end | |
# raising an exception is a good way to exit rake with a detailed error message | |
# most continuous integration tools will detect the failure | |
task :copy, :source, :target, :needs => :other_task do |t, args| | |
puts "copy #{args.source} to #{args.target}" | |
# args[:source] also works | |
end | |
# rake 0.8 adds support for task arguments | |
# | |
# task named :copy with arguments :source and :target, depends on :other_task | |
# t = task object | |
# args = arguments (instance of Rake::TaskArguments) | |
# | |
# command-line usage: | |
# rake copy[file1,file2] | |
# rake "copy[path with spaces/file1,file2]" | |
# | |
# rakefile usage: | |
# none (as of rake v0.8.1) | |
# calling .invoke and .execute is possible (not recommended) | |
task :copy_some_files do | |
cp 'one_file', 'destination' | |
cp 'another_file', 'destination', :verbose => true | |
end | |
# rake includes the FileUtils module which has many | |
# file system manipulation methods. FileUtils#cp copies a file. | |
# see http://www.ruby-doc.org/core/classes/FileUtils.html | |
# rake wraps FileUtils in Rake::FileUtils to add the :verbose option | |
task :additional_commands do | |
ruby 'my_ruby_script.rb' # run a ruby interpreter | |
sh 'build.bat' # run a shell command | |
safe_ln 'fileone.txt', 'filetwo.txt' # link or copy (as supported by OS) | |
split_all("a/b/c") #=> ['a', 'b', 'c'] (split directory into an array) | |
end | |
# rake adds a few new commands | |
# see http://rake.rubyforge.org/classes/FileUtils.html | |
multitask :c_and_d_in_parallel => [:c, :d] | |
# using multitask, immediate prerequisites are invoked on separate threads | |
# ----------------------------------------------------------------------------- | |
# File and Directory Tasks | |
# ----------------------------------------------------------------------------- | |
directory 'tests/out' | |
# defines a directory task named 'tests/out' which will | |
# create the 'tests/out' directory if it doesn't | |
# already exist. | |
file 'path/target.txt' => 'path/source.txt' do | |
cp 'path/source.txt', 'path/target.txt' | |
end | |
# defines a file task named 'path/target.txt' which will | |
# get invoked if the file 'path/source.txt' is newer. | |
# file tasks look at the timestamp of the prerequisites | |
def copy_file( source_file, target_file, task_symbol ) | |
desc "cp from #{source_file}" | |
file target_file => [source_file] do |t| | |
cp source_file, target_file, :verbose => true | |
end | |
task task_symbol => target_file | |
end | |
# example of a method which creates tasks. | |
# copy_file makes a file task to copy the source_file to target_file | |
# copy_file make task named task_symbol to depend on the target_file | |
# | |
# usage: | |
copy_file( 'path/foo.txt', 'path/foobar.txt', :copy_foo ) | |
# ----------------------------------------------------------------------------- | |
# FileList | |
# ----------------------------------------------------------------------------- | |
FileList['data/**/*', 'out/non-existing-file.txt'] | |
# rake FileList can glob files from the disk, | |
# and/or collect files that dont exist. | |
# FileList globs are lazy, they are resolved when first used. | |
FileList['data/**/*'].exclude('*.txt') | |
# .exclude globs | |
# resolves against the file system, e.g. wont match files that don't exist | |
FileList['data/**/*'].exclude {|path| path =~ /delete_me/ } | |
# .exclude can use block to exclude everything where the block returns true. | |
# example: exclude files when path matches the regular expression /delete_me/ | |
# FileList contains many other useful methods. | |
# see http://rake.rubyforge.org/classes/Rake/FileList.html | |
FileList['data/*'].each do |source| | |
target = source.sub('data', 'out') | |
file target => source do | |
cp source, target, :verbose => true | |
end | |
desc "copies all data files" | |
task :copy_data_files => target | |
end | |
# example using FileList to create tasks to perform a copy | |
file 'target.txt' => 'source.txt' do |f| | |
cp f.prerequisites[0], f.name, :verbose => true | |
end | |
# file tasks blocks can access the task object | |
# f.prerequisites[0] is 'source.txt' | |
# f.name is 'target.txt' | |
# ----------------------------------------------------------------------------- | |
# String extensions | |
# ----------------------------------------------------------------------------- | |
# Rake adds methods to String... | |
# see http://rake.rubyforge.org/classes/String.html | |
# | |
'path/file.txt'.ext( 'html') #=> path/file.html (replace extension) | |
'path/file.txt'.pathmap('%p') #=> 'path/file.txt' (full path) | |
'path/file.txt'.pathmap('%f') #=> 'file.txt' (file) | |
'path/file.txt'.pathmap('%n') #=> 'file' (file name, no ext) | |
'path/file.txt'.pathmap('%x') #=> '.txt' (file extension) | |
'path/file.txt'.pathmap('%X') #=> 'path/file' (full path, no extension) | |
'x/y/z/file.txt'.pathmap('%d') #=> 'x/y/z' (directory path) | |
'x/y/z/file.txt'.pathmap('%2d') #=> 'x/y' (directory path depth 2) | |
'x/y/z/file.txt'.pathmap('%-2d') #=> 'y/z' (directory path depth 2 from end) | |
'x/y/z/file.txt'.pathmap('%d%s%f') #=> 'x/y/z\file.txt' (%s = alt separator) | |
'x/y/z/file.txt'.gsub('/','\\') #=> 'x\y\z\file.txt' (gsub works better) | |
''.pathmap('%%') #=> '%' (percent sign) | |
'a/b/c'.pathmap('%{a,apple}p') #=> 'apple/b/c' use {} to replace using regex | |
'a/b/c'.pathmap('%{a,x;b,y}p') #=> 'x/y/c' use {;} to replace multiple patterns | |
'a/b/c'.pathmap('%{a,*}p') {|m| "(#{m})"} #=> '(a)/b/c' * calls block for match | |
# ----------------------------------------------------------------------------- | |
# Namespace | |
# ----------------------------------------------------------------------------- | |
namespace :ns do | |
task :target | |
end | |
task :default => "ns:target" | |
# defines a namespace named :ns | |
# defines a task named "ns:target" | |
# sets "ns:target" as a prerequisite of :default | |
# use namespace to organize code and avoid task name conflicts | |
namespace :ns do | |
task :alpha => :beta | |
task :beta | |
end | |
# within a namespace, you can refer to another task in the namespace directly | |
# you dont need | |
# task :alpha => 'ns:beta' | |
task :dog | |
task :farmer | |
namespace :animal do | |
task :cat => :dog | |
task :dog => :farmer | |
end | |
# namespaces will look for tasks within their own namespace | |
# animal:cat's prerequisite is animal:dog, not :dog | |
# i dont know of a way to reference :dog instead of animal:dog inside | |
# the namespace block. animal:dog hides :dog! | |
# animal:dog's prerequisite is :farmer (outer scope) since there isn't | |
# an animal:farmer defined. | |
task 'animal:cow' => :dog | |
# animal:cow is defined outside the namespace block | |
# animal:cow's prerequisite is :dog, not animal:dog | |
# animal:cow will look for prerequisites in the outer scope | |
# animal:cow will not automatically look for tasks in the animal namespace | |
namespace :animal do | |
task :calf => :cow | |
end | |
# animal:calf's prerequisite is the 'animal:cow' defined above. as expected. | |
namespace :demo do | |
file 'out/demo.txt' => ['in/demo.txt', :hello] | |
task :hello | |
end | |
# file task name is only 'out/demo.txt', the namespace doesn't change the name | |
# however the scope lookup applies, 'out/demo.txt' prereq is demo:hello | |
# ----------------------------------------------------------------------------- | |
# Rules | |
# ----------------------------------------------------------------------------- | |
rule /out\/.*\.txt/ => proc {|t| t.pathmap('data/%n.txt')} do |t| | |
cp t.source, t.name | |
end | |
task :use_rule => 'out/some_file.txt' | |
# see the rake documentation and tutorials for rules. | |
# rake allows defining rules, they describe how to generate a file from another | |
# in practice, i've found rules can get hard to read | |
# instead i generate tasks using a FileList (more readable)... | |
FileList.new('data/*.txt').each do |f| | |
target = f.pathmap('out/%f') | |
file target => f do | |
cp f, target, :verbose => true | |
end | |
task :use_rule => target | |
end | |
# ----------------------------------------------------------------------------- | |
# Clean and Clobber | |
# ----------------------------------------------------------------------------- | |
require 'rake/clean' | |
# creates two tasks: :clean and :clobber | |
# :clean is used to remove temporary files | |
# :clobber is used to remove all generated files | |
# also creates two constants: CLEAN and CLOBBER | |
# they are FileLists of files to remove | |
# :clean is a prerequisite of :clobber | |
# examples: | |
CLEAN << 'file_to_remove.txt' | |
CLEAN.include( '*_to_remove.txt' ) | |
CLEAN.add( 'delete_me.txt' ) | |
CLEAN.exclude( 'dont_remove.txt' ) | |
# ----------------------------------------------------------------------------- | |
# Import and Libraries | |
# ----------------------------------------------------------------------------- | |
# rakefile usage: | |
# import 'more_tasks.rb' | |
# import is like require, except it loads +after+ the current file is finished. | |
# the rake command-line can specify a library folder (default is rakelib) | |
# rake -R=another_rakelib | |
# rake will automatically +import+ all *.rake files found in the directory | |
# ----------------------------------------------------------------------------- | |
# Task Generation | |
# ----------------------------------------------------------------------------- | |
# Sometimes you want to create a bunch of similar tasks. Task Generators | |
# are classes that create tasks. | |
# | |
# For example, building rdoc documentation from ruby source code may | |
# involve three tasks: | |
# rake rdoc # build rdoc | |
# rake clobber_rdoc # remove rdoc output | |
# rake rerdoc # force a rebuild of rdoc | |
# | |
# Rake provides a class which creates these tasks from a single call: | |
# see http://rake.rubyforge.org/classes/Rake/RDocTask.html | |
require 'rake/rdoctask' | |
Rake::RDocTask.new do |rd| | |
rd.main = "README.rdoc" | |
rd.rdoc_files.include("README.rdoc", "lib/**/*.rb") | |
end | |
# Rake::TestTask is another task generator, for running ruby unit tests | |
# tasks: test (has several command-line options) | |
# see http://rake.rubyforge.org/classes/Rake/TestTask.html | |
require 'rake/testtask' | |
Rake::TestTask.new do |t| | |
t.libs << "test" | |
t.test_files = FileList['test/test*.rb'] | |
t.verbose = true | |
end | |
# Rake::GemPackageTask is another task generator, for packaging gems | |
# tasks: "package_dir/name-version.gem" | |
# see http://rake.rubyforge.org/classes/Rake/GemPackageTask.html | |
require 'rubygems' | |
spec = Gem::Specification.new do |s| | |
s.name = 'mygem' | |
s.version = '0.1' | |
# ...etc ... | |
end | |
require 'rake/gempackagetask' | |
Rake::GemPackageTask.new(spec) do |package| | |
package.need_zip = true | |
end | |
# Writting your own Task Generator is easy to develop. | |
# For example, GetPastie will create a task to download a pastie: | |
require 'rake/tasklib' | |
class GetPastie < Rake::TaskLib | |
attr_accessor :name, :id, :target | |
# initialize sets the name and calls a block to get | |
# the rest of the options | |
def initialize( name=:get_pastie ) | |
@name = name | |
yield self if block_given? | |
define | |
end | |
# define creates the new task(s) | |
def define | |
raise "id must be defined" if @id.nil? | |
raise "target must be defined" if @target.nil? | |
require 'open-uri' | |
desc "download http://pastie.org/pastes/#{@id} to #{target}" | |
task @name do | |
open(@target,"w").write(open("http://pastie.org/pastes/#{@id}/download").read) | |
end | |
end | |
end | |
# creates the task :rake_quick_ref | |
GetPastie.new( :rake_quick_ref ) do |t| | |
t.id = 239387 # the first quick ref published | |
t.target = 'out/pastie_239387.rb' | |
end | |
# ----------------------------------------------------------------------------- | |
# Tips | |
# ----------------------------------------------------------------------------- | |
# tracing is turned on using the command-line -t flag | |
# rake -t | |
# or within the rake file... | |
Rake.application.options.trace = true | |
# name=value pairs given at the end of the command-line are accessible | |
# using the ENV hash | |
# | |
# for example: | |
# rake mytask CONFIG=DEBUG | |
task :show_config do | |
puts ENV['CONFIG'] #=> DEBUG | |
end | |
# for and example of combining command-line args with configuration options | |
# see Rake::TestTask | |
task :x # referenced above | |
task :y | |
task :z |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thx, this seems like a pretty handy resource.
However, I can't get a task with arguments and depending on another task to work like you describe.
For example:
I can only get it to work with an explicit call to invoke as in t2, not with the hash like definition in t3 like you seem to suggest in your reference. Am I missing something?
Using rake, version 10.4.2.
EDIT: got it to work by specifying the argument as an array: