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