A blog about software development and other software related matters

Blog Archive

Tuesday, December 18, 2007

Buildr and groovyc

Buildr is a build tool that iv mentioned in previous posts, its really flexible and easy to mold custom functionality into it due to its Ruby heritage and its AntWrap utilization.
In this post im going to demonstrate how to use the groovyc ant task in order to intruduce groovy compilation into your build (which is a bit tricky).
Lets dive head first into the code:


SP=File::SEPARATOR

desc "Dummy project"
define "Dummy" do
#..
def
hashToPath(hash)hash[:group].gsub('.',SP)+SP+hash[:id]+SP+hash[:version]+SP+hash[:id]+'-'+hash[:version]+'.jar'
end

def reslove_artifacts_paths(array)
array.flatten.inject([]){|result,arti| result << repositories.local+'/'+hashToPath(artifact(arti).to_hash)}.join(File::PATH_SEPARATOR)
end

desc 'compiling'
compile.enhance([:groovyc])# this actully replaces the standart compile with the groovyc ant task

desc 'groovyc task'
task :groovyc do
classpath=reslove_artifacts_paths(RUNTIME)
ant('groovy') do |ant|
ant.taskdef :name=>'groovyc',:classname=>'org.codehaus.groovy.ant.Groovyc',:classpath=>reslove_artifacts_paths(GROOVY)
ant.groovyc(:srcdir=>path_to('src', 'main', 'java') , :destdir=>path_to('target','classes') , :classpath=>classpath){
ant.javac(:source=>"1.5" ,:target=>"1.5")
}
end
end
#..
end


The code above (if you havent guessed it until now) is the buildfile, lets disassemble it:

  • The groovyc task uses AntWrap in order to define and use the groovyc ant task, notice that we are using joint compilation which in essence suppresses the default compilation (since there wont be anything left to compile when its turn arrives) and makes our life easier (no need to mess with the ordering of the compilation steps).

  • The reslove_artifacts_paths method does what its name suggests and is required in order to make ant happy (i haven't found a nicer way of doing this) or else it wont find the required classes.

  • the GROOVY constant points to the groovy-all jar the RUNTIME points to all that is needed during compilation.



That all about there is to it.

2 comments:

Assaf said...

Ronen,

Cool. For Buildr 1.3 we added an API for plugging new compilers. The main benefit is that tasks like packaging, or creating Eclipse projects will recognize the source files and support the compiler.

Meanwhile, couple of tricks you can use. To convert dependencies into a classpath:

Buildr.artifacts(GROOVY).map(&:name).join(File::PATH_SEPARATOR)

artifacts is just the array->array version of artifact, and each artifact's name is its file path.

That won't download/build any of them, so you can add those as dependencies, or invoke explicity:

Buildr.artifacts(GROOVY).each(&:invoke).map(&:to_s).join(File::PATH_SEPARATOR)

ronen said...

Cool, id be sure checking this out!
Iv been using Buildr also with an OSS JRuby project that iv been working on, more on this to come :)