doc/rantfile.rdoc in rant-0.4.8 vs doc/rantfile.rdoc in rant-0.5.0

- old
+ new

@@ -40,36 +40,36 @@ task name may be a string or symbol: task :taskname That's it, your first task. Not very useful, because it doesn't do anything. To associate an action with the task, add a block: task :mytask do - puts "Hello, mytask running." + puts "Hello, mytask running." end Put these 3 lines of code into a file called +Rantfile+ and run rant: % rant mytask Hello, mytask running. Note: you could have omited the mytask argument to rant because it is the only task in the Rantfile. You can add a block parameter which will be a reference to the created task: task :mytask do |t| - puts t.name + puts t.name end Running rant now: % rant mytask Add prerequisites to create relations between tasks: task :first => [:t1, :t2] do |t| - puts t.name + puts t.name end task :t1 do |t| - puts t.name + puts t.name end task :t2 do |t| - puts t.name + puts t.name end In the definition of the "first" task we told Rant that it _depends_ on task "t1" and task "t2". "t1" and "t2" are called prerequisites for "first". Try it out: % rant first @@ -92,11 +92,11 @@ In this example we use the <tt>sys.touch</tt> method to test our file task. (This method works the same as the Unix touch command: Update the modification time of a file or create an empty file): file "testfile" do |t| - sys.touch t.name + sys.touch t.name end Now run rant: % rant touch testfile This would have been the same with a normal task. But now run rant a @@ -105,11 +105,11 @@ This time rant doesn't run the action, because "testfile" is up to date. Of course you can add prerequisites the same way as for a normal task. Additionally you can add filenames as prerequisites. Assuming the files "a.o" and "b.o" are in the same directory as the Rantfile: file "myprog" => %w(a.o b.o) do |t| - sys %w(cc -o), t.name, t.prerequisites + sys %w(cc -o), t.name, t.prerequisites end Running rant: % rant cc -o myprog a.o b.o Running a second time: @@ -124,62 +124,62 @@ The +desc+ function lets you describe your tasks. A small example Rantfile: # Generate C source file ls.c with the xgen command. file "ls.c" => %w(ls1.x ls2.x) do |t| - sys %w(xgen -o), t.name, t.prerequisites + sys %w(xgen -o), t.name, t.prerequisites end desc "Build ls program." file "ls" => "ls.c" do - sys "cc -o ls ls.c" + sys "cc -o ls ls.c" end desc "Remove autogenerated files." task :clean do - sys.rm_f %w(ls.c ls) + sys.rm_f %w(ls.c ls) end (Note that xgen is a hypothetical command ;) The <tt>--tasks</tt> (or the short form, <tt>-T</tt>) option of rant shows this descriptions: % rant -T - rant ls # Build ls program. - rant clean # Remove autogenerated files. + rant ls # Build ls program. + rant clean # Remove autogenerated files. Only the tasks which have a description are listed. -=== The +sys+ command +=== The +sys+ method -After using the +sys+ command quite often in the examples, I should -explain it a little bit. The +sys+ command can be used in three ways: +After using the +sys+ method quite often in the examples, I should +explain it a little bit. It can be used in three ways: 1. <b>File system operations</b> The first form is with no arguments. It returns an object on which - you can invoke the methods of the +FileUtils+ module that comes - with ruby. + you can invoke methods for common file system operations: + Examples are: - sys.rm "file1", "file2", ... # remove files - sys.cp "src", "dest" # copy from "src" do "dest" - sys.mkdir "dir" # create directory "dir" - For a list of all available methods invoke ri: - % ri FileUtils - which will also show documentation for them. - Additionally you have the following methos which are not in the - FileUtils module: - sys.ruby "arg1", "arg2", ... # invoke the ruby interpreter - sys.safe_ln "src", "dest" # create a hardlink or fall back to - # copying + sys.rm ["file1", "file2"] # remove files + sys.cp "src", "dest" # copy from "src" do "dest" + sys.mkdir "dir" # create directory "dir" + + For a list of all available methods read + doc/sys.rdoc[link:files/doc/sys_rdoc.html]. + 2. <b>Running external commands</b> - Invoke the +sys+ command with a string as argument to run a shell: - sys "echo *.c" + Invoke the +sys+ method with a string as argument to run a shell: + + sys "echo *.c" + will print a list of C files to stdout. When given multiple arguments, +sys+ invokes the program named with the first argument giving it the remaining arguments as arguments: - sys "echo", "*.c" + + sys "echo", "*.c" + will print "*.c" to stdout. When the external program returns with an exit code other than 0, Rant will abort with an error message. Sometimes this is not desirable. E.g. the +diff+ program, which compares two files, @@ -204,101 +204,123 @@ 3. <b>Selecting files</b> To select files with the help of glob patterns use +sys+ with the <tt>[]</tt> operator: - file "program" => sys["*.o"] + + file "program" => sys["*.o"] + The task "program" depends on all files ending in ".o". Rant uses the Dir::glob method internally to resolve patterns, so you can read the ri docs to get an overview: - ri Dir::glob + ri Dir::glob + From now on we'll call <tt>sys[...]</tt> the <em>glob operator</em>. You can give more patterns: - c_files = sys["**/*.h", "**/*.c"] + + c_files = sys["**/*.h", "**/*.c"] + gives a list of all files ending in ".h" or ".c" in the current directory and all subdirectories. - The object returned by the glob operator _behaves_ like a list of + The object returned by the glob operator _behaves_ like an array of strings, so it is possible to pass it to methods expecting an array. If you're getting errors or experience strange behaviour convert the list explicetely to an array: - sys.touch c_files.to_a + # method foo_bar is hardcoded to check for an object of class + # Array + foo_bar(c_files.to_a) + === Generators The *gen* function takes a generator which usually creates one or more tasks for you. The following list of generators is immediately available: -+Directory+:: Create directories. -+Task+:: Define custom task. -+Rule+:: Define a rule (a rule produces tasks on the fly). -+Action+:: Run a block of code immediately. - The Action generator is discussed in - doc/advanced.rdoc[link:files/doc/advanced_rdoc.html]. ++Directory+:: Create directories. ++Task+:: Define custom task. ++Rule+:: Define a rule (a rule produces tasks on the fly). ++Action+:: Run a block of code immediately. + The Action generator is discussed in + doc/advanced.rdoc[link:files/doc/advanced_rdoc.html]. + === The +Directory+ generator An example usage of the +Directory+ generator would be the backup example shown in the README file: + file "misc/backup/data" => %w(misc/backup data) do |t| - sys.cp "data", t.name + sys.cp "data", t.name end gen Directory, "misc/backup" + Now rant will create the directories "misc" and "backup" on demand. Assuming "misc/backup" doesn't exist: + % rant mkdir misc mkdir misc/backup cp data misc/backup/data === The +Task+ generator The +Task+ generator allows you to determine by hand when your task action needs to be run: + desc "Install with setup.rb" gen Task, :install do |t| - t.needed { !File.exist? "InstalledFiles" } - t.act do - sys.ruby "setup.rb" - end + t.needed { !File.exist? "InstalledFiles" } + t.act do + sys.ruby "setup.rb" + end end + The +act+ block of the "install" task will only be run if "InstalledFiles" doesn't exist. Of course you can add prerequisites like with any other task. === Rules A Rule allows you to tell Rant how it should build files matching a common pattern, e.g. how to build files ending in ".o". A standard rule usage is to create C object files: + gen Rule, '.o' => '.c' do |t| - sys "cc -c -o #{t.name} #{t.source}" + sys "cc -c -o #{t.name} #{t.source}" end + Assuming that we have the C source file util.c in the current directory: + % rant util.o cc -c -o util.o util.c + Because Rant didn't find a task for util.o, it looked for a matching rule and created a task for util.o. The first line above could also be written as: + gen Rule, :o => :c do |t| The +source+ method of the task object gives us the first dependency. So the following line has the same effect: - sys "cc -c -o #{t.name} #{t.prerequisites.first}" + sys "cc -c -o #{t.name} #{t.prerequisites.first}" + You can also refine the rule pattern by using a regular expression. To refine dependency selection give a block as source argument: + src = lambda { |target| [target.sub_ext("c"), target.sub_ext("h")] } gen Rule, /^my_[^.]+\.o$/ => src do |t| - sys "cc -c -o #{t.name} #{t.source}" + sys "cc -c -o #{t.name} #{t.source}" end + This rule generates a task for files beginning with "my_" and ending in ".o" (like "my_program.o"). The task has a file ending in ".c" and one ending in ".h" as dependencies (like "my_program.c" and "my_program.h") . Since <tt>t.source</tt> gives us the *first* dependency, the ".c" file will appear as argument to cc, but not the @@ -309,21 +331,29 @@ === Importing additional generators The +import+ function lets you import additional generators. Currently the following come with Rant: + Clean:: Remove selected files. AutoClean:: Remove all files generated by any file task (including those generated by rules). DirectedRule:: A Rule which takes sources from one or more directories and puts generated files into a specified directory. SubFile:: Create file task and necessary directory tasks. +Command:: Tasks with command change recognition. RubyTest:: Run Test::Unit tests for your Ruby code. RubyDoc:: Run RDoc. RubyPackage:: Generate tar, zip and gem packages of your Ruby application/library. +Archive::Tgz:: Create gzipped tar archives. +Archive::Zip:: Create zip archives. +Package::Tgz:: Create gzipped tar packages. +Package::Zip:: Create zip packages. +C::Dependencies:: Determine dependencies between C/C++ source/header + files caused by #include statements. Win32::RubyCmdWrapper:: Create .cmd wrapper scripts for installation of Ruby scripts on Windows. Read doc/advanced.rdoc[link:files/doc/advanced_rdoc.html] and doc/rubyproject.rdoc[link:files/doc/rubyproject_rdoc.html] for @@ -336,45 +366,45 @@ Rantfiles. The tasks defined in those subdirectories can be referenced from your main Rantfile and vice versa. A small example: We are assuming the following files: myprog/ - Rantfile # the main Rantfile - README - src/ - Rantfile - main.c - lib.c - lib.h + Rantfile # the main Rantfile + README + src/ + Rantfile + main.c + lib.c + lib.h Then the main Rantfile could look like: desc "Build myprog." file "myprog" => "src/myprog" do - sys.cp "src/myprog", "myprog" + sys.cp "src/myprog", "myprog" end desc "Remove compiler products." task :clean => "src/clean" do - sys.rm_f "myprog" + sys.rm_f "myprog" end # Tell Rant to look in src for an Rantfile, # we could list more directories here. subdirs "src" And src/Rantfile: file "lib.o" => %w(lib.c lib.h) do - sys "cc -c -o lib.o lib.c" + sys "cc -c -o lib.o lib.c" end file "main.o" => "main.c" do - sys "cc -c -o main.o main.c" + sys "cc -c -o main.o main.c" end file "myprog" => %w(lib.o main.o) do - sys "cc -o myprog main.o lib.o" + sys "cc -o myprog main.o lib.o" end task :clean do - sys.rm_f Dir["*.o"] + %w(myprog) + sys.rm_f Dir["*.o"] + %w(myprog) end Note that we refer to the task in subdirectory simply by prepending the directory name and a slash to the task name. file "myprog" => "src/myprog" do This tells Rant that the "myprog" task depends on the "myprog" task