class Buildr::Project

A project definition is where you define all the tasks associated with the project you're building.

The project itself will define several life cycle tasks for you. For example, it automatically creates a compile task that will compile all the source files found in src/main/java into target/classes, a test task that will compile source files from src/test/java and run all the JUnit tests found there, and a build task to compile and then run the tests.

You use the project definition to enhance these tasks, for example, telling the compile task which class path dependencies to use. Or telling the project how to package an artifact, e.g. creating a JAR using package :jar.

You can also define additional tasks that are executed by project tasks, or invoked from rake.

Tasks created by the project are all prefixed with the project name, e.g. the project foo creates the task foo:compile. If foo contains a sub-project bar, the later will define the task foo:bar:compile. Since the compile task is recursive, compiling foo will also compile foo:bar.

If you run:

buildr compile

from the command line, it will execute the compile task of the current project.

Projects and sub-projects follow a directory heirarchy. The Buildfile is assumed to reside in the same directory as the top-level project, and each sub-project is contained in a sub-directory in the same name. For example:

/home/foo
|__ Buildfile
|__ src/main/java
|__ foo
    |__ src/main/java

The default structure of each project is assumed to be:

src
|__main
|  |__java           <-- Source files to compile
|  |__resources      <-- Resources to copy
|  |__webapp         <-- For WARs
|__test
|  |__java           <-- Source files to compile (tests)
|  |__resources      <-- Resources to copy (tests)
|__target            <-- Packages created here
|  |__classes        <-- Generated when compiling
|  |__resources      <-- Copied (and filtered) from resources
|  |__test/classes   <-- Generated when compiling tests
|  |__test/resources <-- Copied (and filtered) from resources
|__reports           <-- Test, coverage and other reports

You can change the project layout by passing a new Layout to the project definition.

You can only define a project once using define. Afterwards, you can obtain the project definition using project. The order in which you define projects is not important, project definitions are evaluated when you ask for them. Circular dependencies will not work. Rake tasks are only created after the project is evaluated, so if you need to access a task (e.g. compile) use project('foo').compile instead of task('foo:compile').

For example:

define 'myapp', :version=>'1.1' do

  define 'wepapp' do
    compile.with project('myapp:beans')
    package :war
  end

  define 'beans' do
    compile.with DEPENDS
    package :jar
  end
end

puts projects.map(&:name)
=> [ 'myapp', 'myapp:beans', 'myapp:webapp' ]
puts project('myapp:webapp').parent.name
=> 'myapp'
puts project('myapp:webapp').compile.classpath.map(&:to_spec)
=> 'myapp:myapp-beans:jar:1.1'

Attributes

name[R]

The project name. For example, 'foo' for the top-level project, and 'foo:bar' for its sub-project.

parent[R]

The parent project if this is a sub-project.

Public Class Methods

clear click to toggle source

Discard all project definitions.

# File lib/buildr/core/project.rb, line 298
def clear
  @projects.clear if @projects
end
local_task(name) click to toggle source
local_task(name) { |name| ... }

Defines a local task with an optional execution message.

A local task is a task that executes a task with the same name, defined in the current project, the project's with a base directory that is the same as the current directory.

Complicated? Try this:

buildr build

is the same as:

buildr foo:build

But:

cd bar
buildr build

is the same as:

buildr foo:bar:build

The optional block is called with the project name when the task executes and returns a message that, for example “Building project #{name}”.

# File lib/buildr/core/project.rb, line 324
def local_task(*args, &block)
  task *args do |task, args|
    args = task.arg_names.map {|n| args[n]}
    local_projects do |project|
      info block.call(project.name) if block
      task("#{project.name}:#{task.name}").invoke *args
    end
  end
end
on_define(&block) click to toggle source

Deprecated Check the Extension module to see how extensions are handled.

# File lib/buildr/core/project.rb, line 335
def on_define(&block)
  Buildr.application.deprecated 'This method is deprecated, see Extension'
  (@on_define ||= []) << block if block
end

Public Instance Methods

_(*names)
Alias for: path_to
base_dir → path click to toggle source

Returns the project's base directory.

The Buildfile defines top-level project, so it's logical that the top-level project's base directory is the one in which we find the Buildfile. And each sub-project has a base directory that is one level down, with the same name as the sub-project.

For example:

/home/foo/          <-- base_directory of project 'foo'
/home/foo/Buildfile <-- builds 'foo'
/home/foo/bar       <-- sub-project 'foo:bar'
# File lib/buildr/core/project.rb, line 444
def base_dir
  if @base_dir.nil?
    if parent
      # For sub-project, a good default is a directory in the parent's base_dir,
      # using the same name as the project.
      @base_dir = File.expand_path(name.split(':').last, parent.base_dir)
    else
      # For top-level project, a good default is the directory where we found the Buildfile.
      @base_dir = Dir.pwd
    end
  end
  @base_dir
end
defined?() click to toggle source
# File lib/buildr/core/project.rb, line 619
def defined?
  @defined
end
file(path) → Task click to toggle source
file(path=>prereqs) → Task
file(path) { |task| ... } → Task

Creates and returns a new file task in the project. Similar to calling Rake's file method, but the path is expanded relative to the project's base directory, and the task executes in the project's base directory.

For example:

define 'foo' do
  define 'bar' do
    file('src') { ... }
  end
end

puts project('foo:bar').file('src').to_s
=> '/home/foo/bar/src'
# File lib/buildr/core/project.rb, line 506
def file(*args, &block)
  task_name, arg_names, deps = Buildr.application.resolve_args(args)
  task = Rake::FileTask.define_task(path_to(task_name))
  task.set_arg_names(arg_names) unless arg_names.empty?
  task.enhance Array(deps), &block
end
layout() click to toggle source

Returns the layout associated with this project.

# File lib/buildr/core/project.rb, line 459
def layout
  @layout ||= (parent ? parent.layout : Layout.default).clone
end
path_to(*names) → path click to toggle source

Returns a path from a combination of name, relative to the project's base directory. Essentially, joins all the supplied names and expands the path relative to base_dir. Symbol arguments are converted to paths based on the layout, so whenever possible stick to these. For example:

path_to(:source, :main, :java)
=> 'src/main/java'

Keep in mind that all tasks are defined and executed relative to the Buildfile directory, so you want to use path_to to get the actual path within the project as a matter of practice.

For example:

path_to('foo', 'bar')
=> foo/bar
path_to('/tmp')
=> /tmp
path_to(:base_dir, 'foo') # same as path_to('foo")
=> /home/project1/foo
# File lib/buildr/core/project.rb, line 483
def path_to(*names)
  File.expand_path(layout.expand(*names), base_dir)
end
Also aliased as: _
project(name) → project click to toggle source
project → self

Same as Buildr#project. This method is called on a project, so a relative name is sufficient to find a sub-project.

When called on a project without a name, returns the project itself. You can use that when setting project properties, for example:

define 'foo' do
  project.version = '1.0'
end
# File lib/buildr/core/project.rb, line 578
def project(*args, &block)
  if Hash === args.last
    options = args.pop
  else
    options = {}
  end
  if args.empty?
    self
  else
    Project.project *(args + [{ :scope=>self.name }.merge(options)]), &block
  end
end
projects(*names) → projects click to toggle source

Same as Buildr#projects. This method is called on a project, so relative names are sufficient to find sub-projects.

# File lib/buildr/core/project.rb, line 596
def projects(*args)
  if Hash === args.last
    options = args.pop
  else
    options = {}
  end
  Project.projects *(args + [{ :scope=>self.name }.merge(options)])
end
recursive_task(name→prereqs) { |task| ... } click to toggle source

Define a recursive task. A recursive task executes itself and the same task in all the sub-projects.

# File lib/buildr/core/project.rb, line 558
def recursive_task(*args, &block)
  task_name, arg_names, deps = Buildr.application.resolve_args(args)
  task = Buildr.options.parallel ? multitask(task_name) : task(task_name)
  parent.task(task_name).enhance [task] if parent
  task.set_arg_names(arg_names) unless arg_names.empty?
  task.enhance Array(deps), &block
end
root_project() click to toggle source

Returns the root project for this project.

If this project is a subproject it will find the top level project and return it, else it will return itself.

# File lib/buildr/core/project.rb, line 423
def root_project
  p = project
  while p.parent
    p = p.parent
  end
  p
end
task(name) → Task click to toggle source
task(name=>prereqs) → Task
task(name) { |task| ... } → Task

Creates and returns a new task in the project. Similar to calling Rake's task method, but prefixes the task name with the project name and executes the task in the project's base directory.

For example:

define 'foo' do
  task 'doda'
end

puts project('foo').task('doda').name
=> 'foo:doda'

When called from within the project definition, creates a new task if the task does not already exist. If called from outside the project definition, returns the named task and raises an exception if the task is not defined.

As with Rake's task method, calling this method enhances the task with the prerequisites and optional block.

# File lib/buildr/core/project.rb, line 536
def task(*args, &block)
  task_name, arg_names, deps = Buildr.application.resolve_args(args)
  if task_name =~ /^:/
    task = Buildr.application.switch_to_namespace [] do
      Rake::Task.define_task(task_name[1..-1])
    end
  elsif Buildr.application.current_scope == name.split(':')
    task = Rake::Task.define_task(task_name)
  else
    unless task = Buildr.application.lookup(task_name, name.split(':'))
      raise "You cannot define a project task outside the project definition, and no task #{name}:#{task_name} defined in the project"
    end
  end
  task.set_arg_names(arg_names) unless arg_names.empty?
  task.enhance Array(deps), &block
end

Protected Instance Methods

base_dir = dir click to toggle source

Sets the project's base directory. Allows you to specify a base directory by calling this accessor, or with the :base_dir property when calling define.

You can only set the base directory once for a given project, and only before accessing the base directory (for example, by calling file or path_to). Set the base directory. Note: you can only do this once for a project, and only before accessing the base directory. If you try reading the value with base_dir, the base directory cannot be set again.

# File lib/buildr/core/project.rb, line 640
def base_dir=(dir)
  raise 'Cannot set base directory twice, or after reading its value' if @base_dir
  @base_dir = File.expand_path(dir)
end
define(name, properties?) { |project| ... } → project click to toggle source

Define a new sub-project within this project. See Buildr#define.

# File lib/buildr/core/project.rb, line 656
def define(name, properties = nil, &block)
  Project.define "#{self.name}:#{name}", properties, &block
end
define!() click to toggle source
# File lib/buildr/core/project.rb, line 624
def define!
  @defined = true
end
layout=(layout) click to toggle source

Sets the project layout. Accepts Layout object or class (or for that matter, anything that can expand).

# File lib/buildr/core/project.rb, line 647
def layout=(layout)
  raise 'Cannot set directory layout twice, or after reading its value' if @layout
  @layout = layout.is_a?(Class) ? layout.new : layout
end