Author: vborja
Date: Thu Feb 14 10:16:11 2008
New Revision: 627821

URL: http://svn.apache.org/viewvc?rev=627821&view=rev
Log:
BUILDR-37 Added groovy joint compiler.

Groovyc is not included by default, doing so would require all buildr users
(even those not using groovy) to download the groovyc jars. Instead if a user
needs groovy support they must require the compiler explicitly:

  require 'java/groovyc'

Once required, the Groovyc compiler is auto selected if .groovy sources are
found on src/main/groovy.

--
Other changes:

A compiler can now define many source file extensions. Groovy for example is 
responsible for .groovy and .java files when selected.

spec_helpers requires optional files when their corresponding specs are run. 
used to require the groovyc compiler for groovy_compilers_spec.rb
---
 lib/buildr.rb                 |    1 +
 lib/core/compile.rb           |   18 ++--
 lib/java/groovyc.rb           |  116 +++++++++++++++++++++
 spec/groovy_compilers_spec.rb |  223 +++++++++++++++++++++++++++++++++++++++++
 spec/spec_helpers.rb          |    6 +
 5 files changed, 357 insertions(+), 7 deletions(-)
 create mode 100644 lib/java/groovyc.rb
 create mode 100644 spec/groovy_compilers_spec.rb


Added:
    incubator/buildr/trunk/lib/java/groovyc.rb
    incubator/buildr/trunk/spec/groovy_compilers_spec.rb
Modified:
    incubator/buildr/trunk/lib/buildr.rb
    incubator/buildr/trunk/lib/core/compile.rb
    incubator/buildr/trunk/spec/spec_helpers.rb

Modified: incubator/buildr/trunk/lib/buildr.rb
URL: 
http://svn.apache.org/viewvc/incubator/buildr/trunk/lib/buildr.rb?rev=627821&r1=627820&r2=627821&view=diff
==============================================================================
--- incubator/buildr/trunk/lib/buildr.rb (original)
+++ incubator/buildr/trunk/lib/buildr.rb Thu Feb 14 10:16:11 2008
@@ -13,6 +13,7 @@
 require 'facets/string/starts_with'
 require 'facets/openobject'
 require 'facets/kernel/tap'
+require 'facets/kernel/ergo'
 require 'facets/enumerable/uniq_by'
 require 'builder' # A different kind of buildr, one we use to create XML.
 

Modified: incubator/buildr/trunk/lib/core/compile.rb
URL: 
http://svn.apache.org/viewvc/incubator/buildr/trunk/lib/core/compile.rb?rev=627821&r1=627820&r2=627821&view=diff
==============================================================================
--- incubator/buildr/trunk/lib/core/compile.rb (original)
+++ incubator/buildr/trunk/lib/core/compile.rb Thu Feb 14 10:16:11 2008
@@ -65,16 +65,18 @@
         # a .java file.  The default implementation looks to see if there are 
any files in the
         # specified path with the extension #source_ext.
         def applies_to?(project, task)
-          paths = task.sources + Array(project.path_to(:source, task.usage, 
sources.to_sym))
-          paths.any? { |path| !Dir["#{path}/**/*.#{source_ext}"].empty? }
+          paths = task.sources + [sources].flatten.map { |src| 
Array(project.path_to(:source, task.usage, src.to_sym)) }
+          paths.flatten!
+          ext_glob = source_ext.ergo { |ext| Array === ext ? 
"{#{ext.join(',')}}" : ext }
+          paths.any? { |path| !Dir["#{path}/**/*.#{ext_glob}"].empty? }
         end
 
         # Implementations can use this method to specify various compiler 
attributes.
         # For example:
         #   specify :language=>:java, :target=>'classes', 
:target_ext=>'class', :packaging=>:jar
         def specify(attrs)
-          attrs[:sources] ||= attrs[:language].to_s
-          attrs[:source_ext] ||= attrs[:language].to_s
+          attrs[:sources] ||= attrs[:language].ergo { |lang| Array === lang ? 
lang.map(&:to_s) : lang.to_s }
+          attrs[:source_ext] ||= attrs[:language].ergo { |lang| Array === lang 
? lang.map(&:to_s) : lang.to_s }
           attrs.each { |name, value| instance_variable_set("@#{name}", value) }
         end
 
@@ -136,7 +138,8 @@
 
       # Expands a list of source directories/files into a list of files that 
have the #source_ext extension.
       def files_from_sources(sources)
-        sources.map { |source| File.directory?(source) ? 
FileList["#{source}/**/*.#{self.class.source_ext}"] : source }.
+        ext_glob = self.class.source_ext.ergo { |ext| Array === ext ? 
"{#{ext.join(',')}}" : ext }
+        sources.flatten.map { |source| File.directory?(source) ? 
FileList["#{source}/**/*.#{ext_glob}"] : source }.
           flatten.reject { |file| File.directory?(file) }.map { |file| 
File.expand_path(file) }.uniq
       end
 
@@ -148,10 +151,11 @@
       def compile_map(sources, target)
         source_ext = self.class.source_ext
         target_ext = self.class.target_ext
-        sources.inject({}) do |map, source|
+        ext_glob = self.class.source_ext.ergo { |ext| Array === ext ? 
"{#{ext.join(',')}}" : ext }
+        sources.flatten.inject({}) do |map, source|
           if File.directory?(source)
             base = Pathname.new(source)
-            FileList["#{source}/**/*.#{source_ext}"].reject { |file| 
File.directory?(file) }.
+            FileList["#{source}/**/*.#{ext_glob}"].reject { |file| 
File.directory?(file) }.
               each { |file| map[file] = File.join(target, 
Pathname.new(file).relative_path_from(base).to_s.ext(target_ext)) }
           else
             map[source] = File.join(target, 
File.basename(source).ext(target_ext))

Added: incubator/buildr/trunk/lib/java/groovyc.rb
URL: 
http://svn.apache.org/viewvc/incubator/buildr/trunk/lib/java/groovyc.rb?rev=627821&view=auto
==============================================================================
--- incubator/buildr/trunk/lib/java/groovyc.rb (added)
+++ incubator/buildr/trunk/lib/java/groovyc.rb Thu Feb 14 10:16:11 2008
@@ -0,0 +1,116 @@
+module Buildr
+  module Compiler
+    # Groovyc compiler:
+    #  compile.using(:groovyc)
+    #
+    # You need to require 'java/groovyc' if you need to use this compiler.
+    #
+    # Used by default if .groovy files are found in the src/main/groovy 
directory (or src/test/groovy)
+    # and sets the target directory to target/classes (or target/test/classes).
+    #
+    # Groovyc is a joint compiler, this means that when selected for a 
project, this compiler is used
+    # to compile both groovy and java sources. It's recommended that Groovy 
sources are placed in the
+    # src/main/groovy directory, even though this compiler also looks in 
src/main/java
+    #
+    # Groovyc accepts the following options:
+    #
+    # * :encoding          -- Encoding of source files
+    # * :verbose           -- Asks the compiler for verbose output, true when 
running in verbose mode.
+    # * :fork              -- Whether to execute groovyc using a spawned 
instance of the JVM; defaults to no
+    # * :memoryInitialSize -- The initial size of the memory for the 
underlying VM, if using fork mode; ignored otherwise. 
+    #                                     Defaults to the standard VM memory 
setting. (Examples: 83886080, 81920k, or 80m)
+    # * :memoryMaximumSize -- The maximum size of the memory for the 
underlying VM, if using fork mode; ignored otherwise. 
+    #                                     Defaults to the standard VM memory 
setting. (Examples: 83886080, 81920k, or 80m)
+    # * :listfiles         -- Indicates whether the source files to be 
compiled will be listed; defaults to no
+    # * :stacktrace        -- If true each compile error message will contain 
a stacktrace
+    # * :warnings          -- Issue warnings when compiling.  True when 
running in verbose mode.
+    # * :debug             -- Generates bytecode with debugging information.  
Set from the debug
+    #                                     environment variable/global option.
+    # * :deprecation       -- If true, shows deprecation messages.  False by 
default.
+    # * :optimise          -- Generates faster bytecode by applying 
optimisations to the program.
+    # * :source            -- Source code compatibility.
+    # * :target            -- Bytecode compatibility.
+    # * :javac             -- Hash of options passed to the ant javac task
+    class Groovyc < Base
+
+      # Which groovy version to use?
+      VERSION = "1.5.3" unless const_defined?('VERSION')
+
+      REQUIRES = Buildr.struct(
+        :groovy => "org.codehaus.groovy:groovy:jar:#{VERSION}",
+        :commons_cli => 'commons-cli:commons-cli:jar:1.0',
+        :asm => 'asm:asm:jar:2.2.3',
+        :antlr => 'antlr:antlr:jar:2.7.7'
+      ) unless const_defined?('REQUIRES')
+      
+      ANT_TASK = 'org.codehaus.groovy.ant.Groovyc'
+      GROOVYC_OPTIONS = [:encoding, :verbose, :fork, :memoryInitialSize, 
:memoryMaximumSize, :listfiles, :stacktrace]
+      JAVAC_OPTIONS = [:optimise, :warnings, :debug, :deprecation, :source, 
:target, :javac]
+      OPTIONS = GROOVYC_OPTIONS + JAVAC_OPTIONS
+
+      class << self
+        def dependencies #:nodoc:
+          Buildr.artifacts(REQUIRES)
+        end
+
+        def applies_to?(project, task) #:nodoc:
+          paths = task.sources + [sources].flatten.map { |src| 
Array(project.path_to(:source, task.usage, src.to_sym)) }
+          paths.flatten!
+          # Just select if we find .groovy files
+          paths.any? { |path| !Dir["#{path}/**/*.groovy"].empty? }
+        end
+      end
+      
+      Java.classpath << dependencies
+      
+      specify :language => [:groovy, :java], :target => 'classes', :target_ext 
=> 'class', :packaging => :jar
+
+      def initialize(project, options) #:nodoc:
+        super
+        options[:debug] = Buildr.options.debug if options[:debug].nil?
+        options[:deprecation] ||= false
+        options[:optimise] ||= false
+        options[:verbose] ||= Rake.application.options.trace if 
options[:verbose].nil?
+        options[:warnings] = verbose if options[:warnings].nil?
+        options[:javac] = OpenObject.new if options[:javac].nil?
+      end
+
+      # http://groovy.codehaus.org/The+groovyc+Ant+Task
+      def compile(sources, target, dependencies) #:nodoc:
+        return if Rake.application.options.dryrun
+        Buildr.ant 'groovyc' do |ant|
+          classpath = dependencies | self.class.dependencies.map(&:to_s)
+          ant.taskdef :name => 'groovyc', :classname => ANT_TASK, :classpath 
=> classpath.join(File::PATH_SEPARATOR)
+          ant.groovyc groovyc_options(sources, target) do
+            sources.each { |src| ant.src :path => src }
+            ant.classpath do
+              classpath.each { |dep| ant.pathelement :path => dep }
+            end
+            ant.javac(javac_options)
+          end
+        end
+      end
+
+     private 
+      def groovyc_options(sources, target)
+        check_options options, OPTIONS
+        groovyc_options = options.only(*GROOVYC_OPTIONS)
+        groovyc_options[:destdir] = File.expand_path(target)
+        groovyc_options
+      end
+
+      def javac_options
+        check_options options, OPTIONS
+        javac_options = options.only(*JAVAC_OPTIONS)
+        javac_options[:optimize] = (javac_options.delete(:optimise) || false)
+        javac_options[:nowarn] = (javac_options.delete(:warnings) || 
verbose).to_s !~ /^(true|yes|on)$/i
+        other = javac_options.delete(:javac) || {}
+        javac_options.merge!(other)
+        javac_options
+      end
+      
+    end
+  end
+end
+
+Buildr::Compiler.compilers.unshift Buildr::Compiler::Groovyc

Added: incubator/buildr/trunk/spec/groovy_compilers_spec.rb
URL: 
http://svn.apache.org/viewvc/incubator/buildr/trunk/spec/groovy_compilers_spec.rb?rev=627821&view=auto
==============================================================================
--- incubator/buildr/trunk/spec/groovy_compilers_spec.rb (added)
+++ incubator/buildr/trunk/spec/groovy_compilers_spec.rb Thu Feb 14 10:16:11 
2008
@@ -0,0 +1,223 @@
+require File.join(File.dirname(__FILE__), 'spec_helpers')
+
+describe 'groovyc compiler' do 
+  
+  it 'should identify itself from groovy source directories' do
+    write 'src/main/groovy/some/Hello.groovy', 'println "Hello Groovy"'
+    write 'src/test/groovy/some/Hello.groovy', 'println "Hello Groovy"'
+    define('foo') do 
+      compile.compiler.should eql(:groovyc)
+      test.compile.compiler.should eql(:groovyc)
+    end
+  end
+
+  it 'should identify if groovy sources are found on java directories' do
+    write 'src/main/java/some/Hello.groovy', 'println "Hello Groovy"'
+    write 'src/test/java/some/Hello.groovy', 'println "Hello Groovy"'
+    define('foo') do 
+      compile.compiler.should eql(:groovyc)
+      test.compile.compiler.should eql(:groovyc)
+    end
+  end
+
+  it 'should identify itself even if groovy and java sources are found' do
+    write 'src/main/java/some/Empty.java', 'package some; public interface 
Empty {}'
+    write 'src/main/groovy/some/Hello.groovy', 'println "Hello Groovy"'
+    write 'src/test/java/some/Empty.java', 'package some; public interface 
Empty {}'
+    write 'src/test/groovy/some/Hello.groovy', 'println "Hello Groovy"'
+    define('foo') do 
+      compile.compiler.should eql(:groovyc)
+      test.compile.compiler.should eql(:groovyc)
+    end
+  end
+
+  it 'should identify from custom layout' do 
+    write 'groovy/Hello.groovy', 'println "Hello world"'
+    write 'testing/Hello.groovy', 'println "Hello world"'
+    custom = Layout.new
+    custom[:source, :main, :groovy] = 'groovy'
+    custom[:source, :test, :groovy] = 'testing'
+    define 'foo', :layout=>custom do
+      compile.compiler.should eql(:groovyc)
+      test.compile.compiler.should eql(:groovyc)
+    end
+  end
+  
+  it 'should identify from compile source directories' do
+    write 'src/com/example/Code.groovy', 'println "monkey code"' 
+    write 'testing/com/example/Test.groovy', 'println "some test"' 
+    define 'foo' do
+      lambda { compile.from 'src' }.should change { compile.compiler 
}.to(:groovyc)
+      lambda { test.compile.from 'testing' }.should change { 
test.compile.compiler }.to(:groovyc)
+    end
+  end
+
+  it 'should report the multi-language as :groovy, :java' do
+    define('foo').compile.using(:groovyc).language.should == [:groovy, :java]
+  end
+
+  it 'should set the target directory to target/classes' do
+    define 'foo' do
+      lambda { compile.using(:groovyc) }.should change { compile.target.to_s 
}.to(File.expand_path('target/classes'))
+    end
+  end
+
+  it 'should not override existing target directory' do
+    define 'foo' do
+      compile.into('classes')
+      lambda { compile.using(:groovyc) }.should_not change { compile.target }
+    end
+  end
+
+  it 'should not change existing list of sources' do
+    define 'foo' do
+      compile.from('sources')
+      lambda { compile.using(:groovyc) }.should_not change { compile.sources }
+    end
+  end
+  
+  it 'should compile groovy sources' do
+    write 'src/main/groovy/some/Example.groovy', 'package some; class Example 
{ static main(args) { println "Hello" } }'
+    define('foo').compile.invoke
+    file('target/classes/some/Example.class').should exist
+  end
+
+  it 'should include as classpath dependency' do
+    write 'src/bar/groovy/some/Foo.groovy', 'package some; interface Foo {}'
+    write 'src/main/groovy/some/Example.groovy', 'package some; class Example 
implements Foo { }'
+    define('bar', :version => '1.0') do 
+      compile.from('src/bar/groovy').into('target/bar')
+      package(:jar)
+    end
+    lambda { define('foo').compile.with(project('bar').package(:jar)).invoke 
}.should run_task('foo:compile')
+    file('target/classes/some/Example.class').should exist
+  end
+     
+  it 'should cross compile java sources' do 
+    write 'src/main/java/some/Foo.java', 'package some; public interface Foo { 
public void hello(); }'
+    write 'src/main/java/some/Baz.java', 'package some; public class Baz 
extends Bar { }'
+    write 'src/main/groovy/some/Bar.groovy', 'package some; class Bar 
implements Foo { def void hello() { } }'
+    define('foo').compile.invoke
+    %w{Foo Bar Baz}.each { |f| file("target/classes/some/#{f}.class").should 
exist }
+  end
+
+  it 'should cross compile test java sources' do 
+    write 'src/test/java/some/Foo.java', 'package some; public interface Foo { 
public void hello(); }'
+    write 'src/test/java/some/Baz.java', 'package some; public class Baz 
extends Bar { }'
+    write 'src/test/groovy/some/Bar.groovy', 'package some; class Bar 
implements Foo { def void hello() { } }'
+    define('foo').test.compile.invoke
+    %w{Foo Bar Baz}.each { |f| 
file("target/test/classes/some/#{f}.class").should exist }
+  end
+
+  it 'should package classes into a jar file' do
+    write 'src/main/groovy/some/Example.groovy', 'package some; class Example 
{ }'
+    define('foo', :version => '1.0').package.invoke
+    file('target/foo-1.0.jar').should exist
+    Zip::ZipFile.open(project('foo').package(:jar).to_s) do |jar|
+      jar.file.exist?('some/Example.class').should be_true
+    end
+  end
+
+end
+
+describe 'groovyc compiler options' do
+  
+  def groovyc(&prc)
+    define('foo') do
+      compile.using(:groovyc)
+      @compiler = compile.instance_eval { @compiler }
+      class << @compiler
+        public :groovyc_options, :javac_options
+      end
+      if block_given?
+        instance_eval(&prc)
+      else
+        return compile
+      end
+    end
+  end
+  
+  it 'should set warning option to false by default' do 
+    groovyc do
+      compile.options.warnings.should be_false
+      @compiler.javac_options[:nowarn].should be_true
+    end
+  end
+
+  it 'should set warning option to true when running with --verbose option' do
+    verbose true
+    groovyc do
+      compile.options.warnings.should be_true
+      @compiler.javac_options[:nowarn].should be_false
+    end
+  end
+
+  it 'should not set verbose option by default' do
+    groovyc.options.verbose.should be_false
+  end
+
+  it 'should set verbose option when running with --trace option' do
+    trace true
+    groovyc.options.verbose.should be_true
+  end
+  
+  it 'should set debug option to false based on Buildr.options' do
+    Buildr.options.debug = false
+    groovyc.options.debug.should be_false
+  end
+
+  it 'should set debug option to false based on debug environment variable' do
+    ENV['debug'] = 'no'
+    groovyc.options.debug.should be_false
+  end
+
+  it 'should set debug option to false based on DEBUG environment variable' do
+    ENV['DEBUG'] = 'no'
+    groovyc.options.debug.should be_false
+  end
+
+  it 'should set deprecation option to false by default' do
+    groovyc.options.deprecation.should be_false
+  end
+
+  it 'should use deprecation argument when deprecation is true' do
+    groovyc do
+      compile.using(:deprecation=>true)
+      compile.options.deprecation.should be_true
+      @compiler.javac_options[:deprecation].should be_true
+    end
+  end
+
+  it 'should not use deprecation argument when deprecation is false' do
+    groovyc do
+      compile.using(:deprecation=>false)
+      compile.options.deprecation.should be_false
+      @compiler.javac_options[:deprecation].should_not be_true
+    end
+  end
+
+  it 'should set optimise option to false by default' do
+    groovyc.options.optimise.should be_false
+  end
+
+  it 'should use optimize argument when deprecation is true' do
+    groovyc do
+      compile.using(:optimise=>true)
+      @compiler.javac_options[:optimize].should be_true
+    end
+  end
+
+  it 'should not use optimize argument when deprecation is false' do
+    groovyc do
+      compile.using(:optimise=>false)
+      @compiler.javac_options[:optimize].should be_false
+    end
+  end
+
+  after do
+    Buildr.options.debug = nil
+    ENV.delete "debug"
+    ENV.delete "DEBUG"
+  end
+
+end

Modified: incubator/buildr/trunk/spec/spec_helpers.rb
URL: 
http://svn.apache.org/viewvc/incubator/buildr/trunk/spec/spec_helpers.rb?rev=627821&r1=627820&r2=627821&view=diff
==============================================================================
--- incubator/buildr/trunk/spec/spec_helpers.rb (original)
+++ incubator/buildr/trunk/spec/spec_helpers.rb Thu Feb 14 10:16:11 2008
@@ -5,6 +5,12 @@
   require 'rubygems'
   $LOAD_PATH.unshift File.expand_path('../lib', File.dirname(__FILE__))
   require 'buildr'
+
+  # Load additional files for optional specs
+  if rspec_options.argv.any? { |s| s =~ /groovy_compilers_spec/ }
+    require 'java/groovyc'
+  end
+
   require File.expand_path('sandbox', File.dirname(__FILE__))
 
   module SpecHelpers


Reply via email to