module Buildr::Extension

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:

class Project
  include MyExtension
end

You can also extend a given project instance and only that instance by extending it with the module:

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.

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:

This example illustrates how to write a simple extension:

module LinesOfCode
  include Extension

  first_time do
    # Define task not specific to any projet.
    desc 'Count lines of code in current project'
    Project.local_task('loc')
  end

  before_define do |project|
    # Define the loc task for this particular project.
    Rake::Task.define_task 'loc' do |task|
      lines = task.prerequisites.map { |path| Dir['#{path}   /*'] }.flatten.uniq.
        inject(0) { |total, file| total + File.readlines(file).count }
      puts "Project #{project.name} has #{lines} lines of code"
    end
  end

  after_define do |project|
    # Now that we know all the source directories, add them.
    task('loc'=>compile.sources + compile.test.sources)
  end

  # To use this method in your project:
  #   loc path_1, path_2
  def loc(*paths)
    task('loc'=>paths)
  end

end

class Buildr::Project
  include LinesOfCode
end