Transcript Rake

Rake
26-Jul-16
rake and make

A program can consist of many source code files


The files may need to be compiled in a certain order




This is always true in Rails!
Some parts of the program may depend on other parts being up to date
A UNIX makefile is a file that describes these dependencies
UNIX make is a program that reads a makefile, determines the correct
order in which to update files, and updates them
Ruby programs are interpreted, not compiled; but...



Rails uses metaprogramming to create source files and data files from
other files
Consequently, something like make is still needed
rake provides the same functionality as make, but is implemented very
differently
Rakefiles


Rakefiles are written in Ruby 
The following code fragment expresses that a file file_1 depends on files file_2
and file_3


We can use this code fragment with a block that tells what to do with the
dependency



file "file_1" => ["file_2", "file_3"]
file "file_1" => ["file_2", "file_3"] do
# code to create file_1 from file_2 and file_3
end
A rakefile can consist simply of a number of these blocks
Like make, rake looks at the modification dates of files and only updates
them as necessary
First example, I


This example uses C files as examples
Suppose we have the files main.c, greet.h, and greet.c



main.c is our usual “Hello World” program, but includes greet.h, which
specifies a greet method (on greet.c)
Our target (the file we want to build) is hello.o
We have the following dependencies:




file "main.o" => ["main.c", "greet.h"]
file "greet.o" => ["greet.c"]
file "hello" => ["main.o", "greet.o"]
To create the target, we need to execute these commands:



cc -c -o main.o main.c
cc -c -o greet.o greet.c
cc -o hello main.o greet.o
First example, II

Here’s the rakefile:

file 'main.o' => ["main.c", "greet.h"] do
sh "cc -c -o main.o main.c"
end
file 'greet.o' => ['greet.c'] do
sh "cc -c -o greet.o greet.c"
end
file "hello" => ["main.o", "greet.o"] do
sh "cc -o hello main.o greet.o"
end
Running rake



The syntax for running a rake command is
rake [options ...] [VAR=VALUE] [targets ...]
Unless we use the option -f filename , rake will read
its commands from a file named rakefile
Our target (the thing we want to make) is named "hello"
in this file, so (assuming the program on the previous
slide is on a file named rakefile), we run rake by saying
rake hello
Additional targets


file targets check modification dates, hence these tasks are only
done when needed
Non-file tasks are always performed


We can specify a default task, such as "hello", like this:


Non-file tasks use the task keyword instead of file
task :default => ["hello"]
Other non-file tasks are:



clean -- Remove temporary files created during the build process
clobber -- Remove all files generated during the build process
The Rake library implements clean and clobber for you, but you have to
tell it what files to clean or clobber




Do this with FileLists
clean and clobber use the lists named CLEAN and CLOBBER, respectively
Example: CLEAN = FileList["greet.o"]
You can use wildcards: CLOBBER = FileList["*.o"]
Dynamically building tasks

Example:


SRC = FileList['*.c']
SRC.each do |fn|
obj = fn.sub(/\.[^.]*$/, '.o')
file obj do
sh "cc -c -o #{obj} #{fn}"
end
end
Notes:



Remember that Ruby will do substitution in double-quoted strings
The file list depends on the source files (.c files), because the object files
(.o files) may or may not be present
The dependencies between source and object files are specified elsewhere

Rake can figure this out
Automatically building tasks

Rather than dynamically building tasks, it’s usually
easier just to generate them automatically

For example, In C the object .o files depend on the source .c
files, so we can say:

rule '.o' => '.c' do |t|
sh "cc -c -o #{t.name} #{t.source}"
end
Final result

require 'rake/clean'
CLEAN.include('*.o')
CLOBBER.include('hello')
task :default => ["hello"]
SRC = FileList['*.c']
OBJ = SRC.ext('o')
rule '.o' => '.c' do |t|
sh "cc -c -o #{t.name} #{t.source}"
end
file "hello" => OBJ do
sh "cc -o hello #{OBJ}"
end
# File dependencies go here ...
file 'main.o' => ['main.c', 'greet.h']
file 'greet.o' => ['greet.c']
Credit

These slides cover only the most basic use of rake

The extended example used in these slides is taken from
http://docs.rubyrake.org/read/book/1

A more comprehensive explanation of rakefiles can be
found at
http://www.martinfowler.com/articles/rake.html
The End