120 likes | 594 Views
Rake rake and make A program can consist of many source code files This is always true in Rails! The files may need to be compiled in a certain order Some parts of the program may depend on other parts being up to date A UNIX makefile is a file that describes these dependencies
E N D
rake and make • A program can consist of many source code files • This is always true in Rails! • The files may need to be compiled in a certain order • 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 • file "file_1" => ["file_2", "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"] do# code to create file_1 from file_2 and file_3end • 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"endfile 'greet.o' => ['greet.c'] do sh "cc -c -o greet.o greet.c"endfile "hello" => ["main.o", "greet.o"] do sh "cc -o hello main.o greet.o"end
Running rake • The syntax for running a rake command israke [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 • Non-file tasks use the task keyword instead of file • We can specify a default task, such as "hello", like this: • 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}" endend • 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}"endfile "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