doc/pages/extending.textile in vic-buildr-1.3.1 vs doc/pages/extending.textile in vic-buildr-1.3.3

- old
+ new

@@ -1,19 +1,12 @@ h1. Extending Buildr h2. Organizing Tasks -A couple of things we learned while working on Buildr. Being able to write -your own Rake tasks is a very powerful feature. But if you find yourself -doing the same thing over and over, you might also want to consider functions. -They give you a lot more power and easy abstractions. +A couple of things we learned while working on Buildr. Being able to write your own Rake tasks is a very powerful feature. But if you find yourself doing the same thing over and over, you might also want to consider functions. They give you a lot more power and easy abstractions. -For example, we use OpenJPA in several projects. It's a very short task, but -each time I have to go back to the OpenJPA documentation to figure out how to -set the Ant MappingTool task, tell Ant how to define it. After the second -time, you're recognizing a pattern and it's just easier to write a function -that does all that for you. +For example, we use OpenJPA in several projects. It's a very short task, but each time I have to go back to the OpenJPA documentation to figure out how to set the Ant MappingTool task, tell Ant how to define it. After the second time, you're recognizing a pattern and it's just easier to write a function that does all that for you. Compare this: {{{!ruby file('derby.sql') do @@ -44,73 +37,47 @@ :properties=>_(:source, :main, :sql, 'derby.xml'), :classpath=>projects('store', 'utils') end }}} -I prefer the second. It's easier to look at the Buildfile and understand what -it does. It's easier to maintain when you only have to look at the important -information. +I prefer the second. It's easier to look at the Buildfile and understand what it does. It's easier to maintain when you only have to look at the important information. -But just using functions is not always enough. You end up with a Buildfile -containing a lot of code that clearly doesn't belong there. For starters, I -recommend putting it in the @tasks@ directory. Write it into a file with a -@.rake@ extension and place that in the @tasks@ directory next to the -Buildfile. Buildr will automatically pick it up and load it for you. +But just using functions is not always enough. You end up with a Buildfile containing a lot of code that clearly doesn't belong there. For starters, I recommend putting it in the @tasks@ directory. Write it into a file with a @.rake@ extension and place that in the @tasks@ directory next to the Buildfile. Buildr will automatically pick it up and load it for you. -If you want to share these pre-canned definitions between projects, you have a -few more options. You can share the @tasks@ directory using SVN externals. -Another mechanism with better version control is to package all these tasks, -functions and modules into a "Gem":http://rubygems.org/ and require it from -your Buildfile. You can run your own internal Gem server for that. +If you want to share these pre-canned definitions between projects, you have a few more options. You can share the @tasks@ directory using SVN externals. Another mechanism with better version control is to package all these tasks, functions and modules into a "Gem":http://rubygems.org/ and require it from your Buildfile. You can run your own internal Gem server for that. -For individual task files, you can also use -"Sake":http://errtheblog.com/post/6069 for system-wide Rake tasks deployment. +For individual task files, you can also use "Sake":http://errtheblog.com/post/6069 for system-wide Rake tasks deployment. h2. Creating Extensions -The basic mechanism for extending projects in Buildr are Ruby modules. In -fact, base features like compiling and testing are all developed in the form -of modules, and then added to the core Project class. +The basic mechanism for extending projects in Buildr are Ruby modules. In fact, base features like compiling and testing are all developed in the form of modules, and then added to the core Project class. -A module defines instance methods that are then mixed into the project and -become instance methods of the project. There are two general ways for -extending projects. You can extend all projects by including the module in -Project: +A module defines instance methods that are then mixed into the project and become instance methods of the project. There are two general ways for extending projects. You can extend all projects by including the module in Project: {{{!ruby class Project include MyExtension end }}} -You can also extend a given project instance and only that instance by -extending it with the module: +You can also extend a given project instance and only that instance by extending it with the module: {{{!ruby define 'foo' do extend MyExtension end }}} -Some extensions require tighter integration with the project, specifically for -setting up tasks and properties, or for configuring tasks based on the project -definition. You can do that by adding callbacks to the process. +Some extensions require tighter integration with the project, specifically for setting up tasks and properties, or for configuring tasks based on the project definition. You can do that by adding callbacks to the process. -The easiest way to add callbacks is by incorporating the Extension module in -your own extension, and using the various class methods to define callback -behavior. +The easiest way to add callbacks is by incorporating the Extension module in your own extension, and using the various class methods to define callback behavior. |_. Method |_. Usage | -| @first_time@ | This block will be called once for any particular -extension. You can use this to setup top-level and local tasks. | -| @before_define@ | This block is called once for the project with the project -instance, right before running the project definition. You can use this to add -tasks and set properties that will be used in the project definition. | -| @after_define@ | This block is called once for the project with the project -instance, right after running the project definition. You can use this to do -any post-processing that depends on the project definition. | +| @first_time@ | This block will be called once for any particular extension. You can use this to setup top-level and local tasks. | +| @before_define@ | This block is called once for the project with the project instance, right before running the project definition. You can use this to add tasks and set properties that will be used in the project definition. | +| @after_define@ | This block is called once for the project with the project instance, right after running the project definition. You can use this to do any post-processing that depends on the project definition. | This example illustrates how to write a simple extension: {{{!ruby module LinesOfCode @@ -150,31 +117,21 @@ }}} h2. Using Alternative Layouts -Buildr follows a common convention for project layouts: Java source files -appear in @src/main/java@ and compile to @target/classes@, resources are -copied over from @src/main/resources@ and so forth. Not all projects follow -this convention, so it's now possible to specify an alternative project -layout. +Buildr follows a common convention for project layouts: Java source files appear in @src/main/java@ and compile to @target/classes@, resources are copied over from @src/main/resources@ and so forth. Not all projects follow this convention, so it's now possible to specify an alternative project layout. -The default layout is available in @Layout.default@, and all projects inherit -it. You can set @Layout.default@ to your own layout, or define a project with -a given layout (recommended) by setting the @:layout@ property. Projects -inherit the layout from their parent projects. For example: +The default layout is available in @Layout.default@, and all projects inherit it. You can set @Layout.default@ to your own layout, or define a project with a given layout (recommended) by setting the @:layout@ property. Projects inherit the layout from their parent projects. For example: {{{!ruby define 'foo', :layout=>my_layout do ... end }}} -A layout is an object that implements the @expand@ method. The easiest way to -define a custom layout is to create a new @Layout@ object and specify mapping -between names used by Buildr and actual paths within the project. For -example: +A layout is an object that implements the @expand@ method. The easiest way to define a custom layout is to create a new @Layout@ object and specify mapping between names used by Buildr and actual paths within the project. For example: {{{!ruby my_layout = Layout.new my_layout[:source, :main, :java] = 'java' my_layout[:source, :main, :resources] = 'resources' @@ -185,33 +142,22 @@ {{{!ruby my_layout = Layout.new my_layout[:source, :main] = '' }}} -If you need anything more complex, you can always subclass @Layout@ and add -special handling in the @expand@ method, you'll find one such example in the -API documentation. +If you need anything more complex, you can always subclass @Layout@ and add special handling in the @expand@ method, you'll find one such example in the API documentation. -The built-in tasks expand lists of symbols into relative paths, using the -following convention: +The built-in tasks expand lists of symbols into relative paths, using the following convention: |_. Path |_. Expands to | -| @:source, :main, <lang/usage>@ | Directory containing source files for a -given language or usage, for example, @:java@, @:resources@, @:webapp@. | -| @:source, :test, <lang/usage>@ | Directory containing test files for a given -language or usage, for example, @:java@, @:resources@. | -| @:target, :generated@ | Target directory for generated code -(typically source code). | -| @:target, :main, <lang/usage>@ | Target directory for compiled code, for -example, @:classes@, @:resources@. | -| @:target, :test, <lang/usage>@ | Target directory for compile test cases, -for example, @:classes@, @:resources@. | -| @:reports, <framework/usage>@ | Target directory for generated reports, for -example, @:junit@, @:coverage@. | +| @:source, :main, <lang/usage>@ | Directory containing source files for a given language or usage, for example, @:java@, @:resources@, @:webapp@. | +| @:source, :test, <lang/usage>@ | Directory containing test files for a given language or usage, for example, @:java@, @:resources@. | +| @:target, :generated@ | Target directory for generated code (typically source code). | +| @:target, :main, <lang/usage>@ | Target directory for compiled code, for example, @:classes@, @:resources@. | +| @:target, :test, <lang/usage>@ | Target directory for compile test cases, for example, @:classes@, @:resources@. | +| @:reports, <framework/usage>@ | Target directory for generated reports, for example, @:junit@, @:coverage@. | -All tasks are encouraged to use the same convention, and whenever possible, we -recommend using the project's @path_to@ method to expand a list of symbols -into a path, or use the appropriate path when available. For example: +All tasks are encouraged to use the same convention, and whenever possible, we recommend using the project's @path_to@ method to expand a list of symbols into a path, or use the appropriate path when available. For example: {{{!ruby define 'bad' do # This may not be the real target. puts 'Compiling to ' + path_to('target/classes')