lib/core/project.rb in buildr-0.18.0 vs lib/core/project.rb in buildr-0.19.0
- old
+ new
@@ -1,250 +1,294 @@
+require "core/rake_ext"
+
module Buildr
- # A project is a convenient mechanism for managing all the tasks
- # related to a given project. For complex applications, you may have
- # several projects, or sub-projects for each of the modules.
+ # An inherited attribute gets its value an accessor with the same name.
+ # But if the value is not set, it will obtain a value from the parent,
+ # so setting the value in the parent make it accessible to all the children
+ # that did not override it.
+ module InheritedAttributes
+
+ class << self
+ private
+ def included(mod)
+ mod.extend(self)
+ end
+ end
+
+ # :call-seq:
+ # inherited_attr(symbol, default?)
+ # inherited_attr(symbol) { |obj| ... }
+ #
+ # Defines an inherited attribute. The first form can provide a default value
+ # for the top-level object, used if the attribute was not set. The second form
+ # provides a default value by calling the block.
+ #
+ # For example:
+ # inherited_attr :version
+ # inherited_attr :src_dir, "src"
+ # inherited_attr(:created_on) { Time.now }
+ def inherited_attr(symbol, default = nil, &block)
+ block ||= proc { default }
+ attr_accessor symbol
+ define_method "#{symbol}_with_inheritence" do
+ unless value = send("#{symbol}_without_inheritence")
+ value = parent ? parent.send(symbol) : self.instance_eval(&block)
+ send "#{symbol}=", value
+ end
+ value
+ end
+ alias_method_chain symbol, :inheritence
+ end
+ end
+
+
+ # A project definition is where you define all the tasks associated with
+ # the project you're building.
#
- # A project definition creates its own set of tasks, prefixed with
- # the project name. For example, each project has a clean, build
- # and deploy task. For project +foo+ the task names are +foo:clean+,
- # +foo:build+ and +foo:deploy+.
+ # 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.
#
- # Projects have properties, some of which they inherit from their
- # parent project. Built in tasks use these properties, for example,
- # the +clean+ task will remove the target directory specified by
- # the +target_dir+ property. The +compile+ tasks uses the compiler
- # option: you can set these options on the parent project and they
- # will be inherited by all sub-projects.
+ # 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 <tt>package :jar</tt>.
#
+ # 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:
+ # rake compile
+ # from the command line, it will execute the compile task of the current project.
+ #
+ # Projects and sub-projects follow a directory heirarchy. The Rakefile 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
+ # |__ Rakefile
+ # |__ 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
+ # | |__test-classes <-- Generated when compiling tests
+ #
# You can only define a project once using #define. Afterwards, you
# can obtain the project definition using #project. However, when
# working with sub-projects, one project may reference another ahead
# of its definition: the sub-project definitions are then evaluated
# based on their dependencies with each other. Circular dependencies
# are not allowed.
#
# For example:
- # define "project1" do
- # self.version = "1.1"
+ # define "myapp", :version=>"1.1" do
#
- # define "module1" do
- # package :jar
+ # define "wepapp" do
+ # compile.with project("myapp:beans")
+ # package :war
# end
#
- # define "module2" do
- # compile.with project("project1:module1")
+ # define "beans" do
+ # compile.with DEPENDS
# package :jar
# end
# end
#
- # projects.map(&:name)
- # => [ "project", "project:module1", "project1:module2" ]
- # project("project1").sub_projects.map(&:name)
- # => [ "project1:module1", "project1:module2" ]
- # project("project1:module1").parent.name
- # => "project1"
- # project("project1:module1").version
- # => "1.1"
- #
- # Each project has a base directory (see #base_dir). By default,
- # a top-level project uses the current directory, and each sub-project
- # uses a sub-directory relative to the parent project.
- #
- # For the above example, the directory structure is:
- # project1/
- # |__Rakefile
- # |__module1/
- # |__module2/
- #
- # The project definition tasks a block and executes it in the context of
- # the project object. For example:
- # define "project1" do
- # project.version = "1.1"
- # end
- # puts project("project1").version
- # => "1.1"
+ # 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"
class Project < Rake::Task
class << self
# See Buildr#define.
- def define(*args, &block)
- name, properties = name_and_properties_from_args(*args)
+ def define(name, properties, &block) #:nodoc:
# Make sure a sub-project is only defined within the parent project,
# to prevent silly mistakes that lead to inconsistencies (e.g.
# namespaces will be all out of whack).
Rake.application.current_scope == name.split(":")[0...-1] or
- raise "You can only define a sub project (#{name}) within the definition of its parent process"
+ raise "You can only define a sub project (#{name}) within the definition of its parent project"
@projects ||= {}
raise "You cannot define the same project (#{name}) more than once" if @projects[name]
Project.define_task(name).tap do |project|
+ # Define the project to prevent duplicate definition.
@projects[name] = project
- project.enhance { |project| @on_define.each { |callback| callback[project] } } if @on_define
# Set the project properties first, actions may use them.
- properties.each { |name, value| project.send "#{name}=", value }
- # Enhance the project definition with the block.
- if block
- project.enhance { project.instance_eval &block }
- end
-
+ properties.each { |name, value| project.send "#{name}=", value } if properties
+ project.enhance do |project|
+ @on_define.each { |callback| callback[project] }
+ end if @on_define
+ # Enhance the project using the definition block.
+ project.enhance { project.instance_eval &block } if block
+
+ # Top-level project? Invoke the project definition. Sub-project? We don't invoke
+ # the project definiton yet (allow project() calls to establish order of evaluation),
+ # but must do so before the parent project's definition is done.
if project.parent
project.parent.enhance { project.invoke }
else
project.invoke
end
end
end
# See Buildr#project.
- def project(name)
+ def project(name) #:nodoc:
@projects && @projects[name] or raise "No such project #{name}"
- returning(@projects[name]) { |project| project.invoke }
+ @projects[name].tap { |project| project.invoke }
end
# See Buildr#projects.
- def projects(*args)
+ def projects(*names) #:nodoc:
@projects ||= {}
- if args.empty?
+ if names.empty?
@projects.keys.map { |name| project(name) }.sort_by(&:name)
else
- args.map { |name| project(name) or raise "No such project #{name}" }.
- uniq.sort_by(&:name)
+ names.map { |name| project(name) or raise "No such project #{name}" }.uniq.sort_by(&:name)
end
end
+ # :call-seq:
+ # clear()
+ #
# Discard all project definitions.
def clear()
@projects.clear if @projects
end
- # Enhances this task into a local task. A local task executes the same
- # task on the project in the local directory.
+ # :call-seq:
+ # local_task(name)
+ # local_task(name) { |name| ... }
#
- # For example, if the current directory project is +foo+, then
- # +rake build+ executes +rake foo:build+.
+ # Defines a local task with an optional execution message.
#
- # The current directory project is a project with the base directory
- # being the same as the current directory. For example:
+ # 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:
+ # rake build
+ # is the same as:
+ # rake foo:build
+ # But:
# cd bar
# rake build
- # Will execute the +foo:bar:build+ task, after switching to the directory
- # of the sub-project +bar+.
- def local_task(task)
- task = task(task) unless Rake::Task === task
- task.enhance do |task|
+ # is the same as:
+ # rake 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}".
+ def local_task(args, &block)
+ task args do |task|
projects = Project.projects.select { |project| project.base_dir == Rake.application.original_dir }
- if verbose && projects.empty?
- warn "No projects defined for directory #{Rake.application.original_dir}"
+ if projects.empty?
+ warn "No projects defined for directory #{Rake.application.original_dir}" if verbose
+ else
+ projects.each do |project|
+ puts block.call(project.name) if block && verbose
+ task("#{project.name}:#{task.name}").invoke
+ end
end
- projects.each { |project| task("#{project.name}:#{task.name}").invoke }
end
- task
end
- # The Project class defines minimal behavior for new projects.
- # Use #on_define to add behavior when defining new projects.
- # Whenever a new project is defined, it will yield to the block
- # with the project object.
+ # :call-seq:
+ # on_define() { |project| ... }
#
+ # The Project class defines minimal behavior, only what is documented here.
+ # To extend its definition, other modules use Project#on_define to incorporate
+ # code called during a new project's definition.
+ #
# For example:
# # Set the default version of each project to "1.0".
- # Project.on_define do |project|
- # project.version ||= "1.0"
- # end
+ # Project.on_define { |project| project.version ||= "1.0" }
#
- # Keep in mind that the order in which #on_define blocks are
- # called is not determined. You cannot depend on a previous
- # #on_define to set properties or create new tasks. You would
- # want to use the #enhance method instead, by calling it
- # from within #on_define.
- #
- # For example:
- # Project.on_define do |project|
- # puts "defining"
- # project.enhance { puts "defined" }
- # end
- # define "foo" do
- # puts "block"
- # end
- # => defining
- # block
- # defined
+ # Since each project definition is essentially a task, if you need to do work
+ # at the end of the project definition (after the block is executed), you can
+ # enhance it from within #on_define.
def on_define(&block)
(@on_define ||= []) << block if block
end
- # :nodoc:
- def name_and_properties_from_args(*args)
- if Hash === args.last
- properties = args.pop.dup
- else
- properties = {}
- end
- if String === args.first
- name = args.shift
- else
- name = properties.delete(:name)
- end
- raise ArgumentError, "Expected project name followed by (optional) project properties." unless args.empty?
- raise ArgumentError, "Missing project name, this is the first argument to the define method" unless name
- [ name, properties ]
- end
-
- # :nodoc:
- def warnings()
- returning([]) do |msgs|
+ def warnings() #:nodoc:
+ [].tap do |msgs|
msgs << "There are no project definitions in your Rakefile" if @projects.nil? || @projects.empty?
# Find all projects that:
# * Are referenced but never defined. This is probably a typo.
# * Do not have a base directory.
(@projects || {}).each do |name, project|
msgs << "Project #{name} refers to the directory #{project.base_dir}, which does not exist" unless File.exist?(project.base_dir)
end
end
end
- def scope_name(scope, task_name)
+ def scope_name(scope, task_name) #:nodoc:
task_name
end
end
- include Attributes
+ include InheritedAttributes
- # The project name. If this is a sub-project, it will be prefixed
- # by the parent project's name. For example, "foo" and "foo:bar".
+ # The project name. For example, "foo" for the top-level project, and "foo:bar"
+ # for its sub-project.
attr_reader :name
# The parent project if this is a sub-project.
attr_reader :parent
- # :nodoc:
- def initialize(*args)
+ def initialize(*args) #:nodoc:
super
split = name.split(":")
if split.size > 1
- # Get parent project, but do not invoke it's definition to
- # prevent circular dependencies (it's being invoked right now).
+ # Get parent project, but do not invoke it's definition to prevent circular
+ # dependencies (it's being invoked right now, so calling project() will fail).
@parent = task(split[0...-1].join(":"))
raise "No parent project #{split[0...-1].join(":")}" unless @parent && Project === parent
end
- # We want to lazily evaluate base_dir, but default initialize
- # will set it to the current directory.
+ # We only need this because each task (and a project is a task) already has
+ # a @base_dir variable (and base_dir method), and we want it lazily evaluated.
+ # See all the logic that happens when we call base_dir.
@base_dir = nil
end
- # The base directory of this project. The default for a top-level project
- # is the same directory that holds the Rakefile. The default for a
- # sub-project is a child directory with the same name.
+ # :call-seq:
+ # base_dir() => path
#
- # A project definition can change the base directory using the base_dir
- # hash value. Be advised that the base directory and all values that
- # depend on it can only be determined after the project is defined.
+ # Returns the project's base directory.
+ #
+ # The Rakefile defines top-level project, so it's logical that the top-level project's
+ # base directory is the one in which we find the Rakefile. 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/Rakefile <-- builds "foo"
+ # /home/foo/bar <-- sub-project "foo:bar"
def base_dir()
- unless @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.
sub_dir = File.join(@parent.base_dir, name.split(":").last)
@base_dir = File.exist?(sub_dir) ? sub_dir : @parent.base_dir
@@ -255,82 +299,133 @@
end
end
@base_dir
end
+ # :call-seq:
+ # base_dir = dir
+ #
+ # 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.
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 a new sub-project within this project.
- def define(*args, &block)
- name, properties = Project.name_and_properties_from_args(*args)
- Project.define "#{self.name}:#{name}", properties, &block
- end
-
- # Returns a path made from multiple arguments. Relative paths are turned into
- # absolute paths using this project's base directory.
+ # :call-seq:
+ # path_to(*names) => path
#
- # Symbol arguments are converted to paths by calling the attribute accessor
- # on the project. For example:
+ # 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 by calling the attribute accessor on the project.
#
# For example:
+ #
+ # For example:
# path_to("foo", "bar")
- # => /projects/project1/foo/bar
- # path_to(:target_dir, "foo")
- # => /projects/project1/target/foo
+ # => /home/project1/foo/bar
# path_to("/tmp")
# => /tmp
- def path_to(*args)
- File.expand_path(File.join(args.map { |arg| Symbol === arg ? send(arg) : arg.to_s }), base_dir)
+ # path_to(:base_dir, "foo")
+ # => /home/project1/foo
+ def path_to(*names)
+ File.expand_path(File.join(names.map { |name| Symbol === name ? send(name) : name.to_s }), base_dir)
end
+ # :call-seq:
+ # define(name, properties?) { |project| ... } => project
+ #
+ # Define a new sub-project within this project. See Buildr#define.
+ def define(name, properties = nil, &block)
+ Project.define "#{self.name}:#{name}", properties, &block
+ end
+
+ # :call-seq:
+ # project(name) => project
+ #
# Same as Buildr#project.
def project(name)
Project.project(name)
end
+ # :call-seq:
+ # projects(*names) => projects
+ #
# Same as Buildr#projects.
- def projects(*args)
- Project.projects(*args)
+ def projects(*names)
+ Project.projects(*names)
end
- def sub_projects()
- prefix = name + ":"
- Project.projects.select { |project| project.name.starts_with?(prefix) }.sort_by(&:name)
- end
-
- # Create or return a file task. This is similar to Rake's file method,
- # with the exception that all relative paths are resolved relative to
- # the project's base directory.
+ # :call-seq:
+ # file(path) => Task
+ # file(path=>prereqs) => Task
+ # file(path) { |task| ... } => Task
#
- # You can call this from within or outside the project definition.
+ # 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"
def file(args, &block)
task_name, deps = Rake.application.resolve_args(args)
unless task = Rake.application.lookup(task_name, [])
task = Rake::FileTask.define_task(File.expand_path(task_name, base_dir))
task.base_dir = base_dir
end
deps = [deps] unless deps.respond_to?(:to_ary)
task.enhance deps, &block
end
- # Create or return a task. This is similar to Rake's task method,
- # with the exception that the task is always defined within the project's
- # namespace.
+ # :call-seq:
+ # task(name) => Task
+ # task(name=>prereqs) => Task
+ # task(name) { |task| ... } => Task
#
- # If called from within the project definition, it returns a task,
- # creating a new one no such task exists. If called from outside the
- # project definition, it returns a task and raises an error if the
- # task does not exist.
+ # 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.
def task(args, &block)
task_name, deps = Rake.application.resolve_args(args)
- if Rake.application.current_scope == name.split(":")
+ if task_name =~ /^:/
+ Rake.application.instance_eval do
+ scope, @scope = @scope, []
+ begin
+ Rake::Task.define_task(task_name[1..-1]=>deps, &block)
+ ensure
+ @scope = scope
+ end
+ end
+ elsif Rake.application.current_scope == name.split(":")
Rake::Task.define_task(task_name=>deps, &block)
else
if task = Rake.application.lookup(task_name, name.split(":"))
deps = [deps] unless deps.respond_to?(:to_ary)
task.enhance deps, &block
@@ -339,140 +434,121 @@
raise "You cannot define a project task outside the project definition, and no task #{full_name} defined in the project"
end
end
end
- # Define a recursive task.
+ # :call-seq:
+ # recursive_task(name=>prereqs) { |task| ... }
#
- # A recursive task executes the task with the same name in the project,
- # and in all its sub-projects. In fact, a recursive task actually adds
- # itself as a prerequisite on the parent task.
- #
- # For example:
- # define "foo" do
- # define "bar" do
- # define "baz" do
- # end
- # end
- # end
- #
- # rake foo:build
- # Will execute foo:build, foo:bar:build and foo:baz:build
- #
- # Inside the bar directory:
- # rake build
- # Will execute foo:bar:build and foo:baz:build.
- #
- # This method defines a RakeTask. If you need a different type of task,
- # define the task first and then call #recursive_task.
+ # Define a recursive task. A recursive task executes itself and the same task
+ # in all the sub-projects.
def recursive_task(args, &block)
task_name, deps = Rake.application.resolve_args(args)
deps = [deps] unless deps.respond_to?(:to_ary)
- returning(task(task_name=>deps)) do |task|
+ task(task_name=>deps).tap do |task|
if parent
Rake.application.lookup(task_name, parent.name.split(":")).enhance [task]
#Rake::Task["^#{name}"].enhance([ task ])
end
task.enhance &block
end
end
- def execute()
+ def execute() #:nodoc:
Rake.application.in_namespace ":#{name}" do
# Everything we do inside the project is relative to its working directory.
Dir.chdir(base_dir) { super }
end
end
end
# :call-seq:
- # define name { |project| ... }
- # define name, properties { |project| ... }
- # define properties { |project| ... }
+ # define(name, properties?) { |project| ... } => project
#
# Defines a new project.
#
- # The first argument is the project name. Each project must have a unique name,
- # and you can only define a project once.
+ # The first argument is the project name. Each project must have a unique name.
+ # For a sub-project, the actual project name is created by prefixing the parent
+ # project's name.
#
- # The second argument contains any number of properties that are set on the
- # project. The project must have attribute accessors to support these properties.
- # You can also pass the project name in the properties hash.
+ # The second argument is optional and contains a hash or properties that are set
+ # on the project. You can only use properties that are supported by the project
+ # definition, e.g. :group and :version. You can also set these properties from the
+ # project definition.
#
- # The easiest way to define a project and configure its tasks is by passing
- # a block. The #define method executes the block in the context of the project.
+ # You pass a block that is executed in the context of the project definition.
+ # This block is used to define the project and tasks that are part of the project.
+ # Do not perform any work inside the project itself, as it will execute each time
+ # the Rakefile is loaded. Instead, use it to create and extend tasks that are
+ # related to the project.
#
# For example:
# define "foo", :version=>"1.0" do
- # puts version
- # end
#
- # define "bar" do
- # puts name
- # end
-3 # => "1.0"
- # "bar"
- #
- # Each project also has a #define method that operates the same way, but
- # defines a sub-project. A sub-project has a compound name using the parent
- # project's name, and also inherits some of its properties. You can only
- # define a sub-project as part of the parent project's definition.
- #
- # For example:
- # define "foo", :version=>"1.0" do
- # define "bar"
- # puts name
- # puts version
+ # define "bar" do
+ # compile.with "org.apache.axis2:axis2:jar:1.1"
# end
# end
- # => "foo:bar"
- # "1.0"
- def define(*args, &block)
- Project.define(*args, &block)
+ #
+ # puts project("foo").version
+ # => "1.0"
+ # puts project("foo:bar").compile.classpath.map(&:to_spec)
+ # => "org.apache.axis2:axis2:jar:1.1"
+ # % rake build
+ # => Compiling 14 source files in foo:bar
+ def define(name, properties = nil, &block) #:yields:project
+ Project.define(name, properties, &block)
end
- # Returns the named project.
+ # :call-seq:
+ # project(name) => project
#
- # For a sub-project, use the full name, for example "foo:bar" to find
- # the sub-project "bar" of the parent project "foo".
+ # Returns a project definition.
#
- # You cannot reference a project before the project is defined, with one
- # exception. When working with sub-projects, the project definitions are
- # stored but not executed until the parent project is defined. So within
- # a sub-project definition you can reference another sub-project definition.
- # The definitions are then performed (invoked) based on that dependency.
- # You cannot have circular references between project definitions.
+ # You cannot reference a project before the project is defined. When working with
+ # sub-projects, the project definition is stored by calling #define, and evaluated
+ # before a call to the parent project's #define method returns.
#
+ # However, if you call #project with the name of another sub-project, its definition
+ # is evaluated immediately. So the returned project definition is always complete,
+ # and you can access its definition (e.g. to find files relative to the base directory,
+ # or packages created by that project).
+ #
# For example:
- # define "project1" do
+ # define "myapp" do
# self.version = "1.1"
#
- # define "module1" do
- # package :jar
+ # define "webapp" do
+ # # webapp is defined first, but beans is evaluated first
+ # compile.with project("myapp:beans")
+ # package :war
# end
#
- # define "module2" do
- # compile.with project("project1:module1")
+ # define "beans" do
# package :jar
# end
# end
def project(name)
Project.project(name)
end
- # With no arguments, returns a list of all the projects defined so far.
+ # :call-seq:
+ # projects(*names) => projects
#
- # With arguments, returns a list of these projects. Equivalent to calling #project
- # for each named project.
+ # With no arguments, returns a list of all projects defined so far. With arguments,
+ # returns a list of these projects, fails on undefined projects.
#
+ # Like #project, this method evaluates the definition of each project before returning it.
+ # Be advised of circular dependencies.
+ #
# For example:
# files = projects.map { |prj| FileList[prj.path_to("src/**/*.java") }.flatten
# puts "There are #{files.size} source files in #{projects.size} projects"
#
- # projects("project1", "project2").map(&:base_dir)
- def projects(*args)
- Project.projects *args
+ # puts projects("project1", "project2").map(&:base_dir)
+ def projects(*names)
+ Project.projects *names
end
# Add project definition tests.
task("check") { |task| task.note *Project.warnings }