2. Tools
2.1. Compiling Groovy
2.1.1. groovyc, the Groovy compiler
groovyc
is the Groovy compiler command line tool. It allows you to compile Groovy sources into bytecode. It plays
the same role as javac
in the Java world. The easiest way to compile a Groovy script or class is to run the following command:
groovyc MyClass.groovy
This will produce a MyClass.class
file (as well as other .class files depending on the contents of the source). groovyc
supports
a number of command line switches:
Short version | Long version | Description | Example |
---|---|---|---|
-b |
--basescript |
Base class name for scripts (must derive from Script) |
|
-cp |
-classpath, --classpath |
Specify the compilation classpath. Must be the first argument. |
groovyc -cp lib/dep.jar MyClass.groovy |
--sourcepath* |
Directory where to find source files |
groovyc -sourcepath src script.groovy |
|
--temp |
Temporary directory for the compiler |
||
--encoding |
Encoding of the source files |
groovyc -encoding utf-8 script.groovy |
|
--help |
Displays help for the command line groovyc tool |
groovyc --help |
|
-v |
--version |
Displays the compiler version |
groovyc -v |
-e |
--exception |
Displays the stack trace in case of compilation error |
groovyc -e script.groovy |
-j |
--jointCompilation* |
Enables joint compilation |
groovyc -j A.groovy B.java |
Notes:
-
sourcepath
is not used anymore. Specifying this parameter will have no effect on compilation. -
for a full description of joint compilation, see the joint compilation section.
2.1.2. Ant task
<groovyc>
Description
Compiles Groovy source files and, if joint compilation option is used, Java source files.
Required taskdef
Assuming groovy-all-VERSION.jar
is in my.classpath you will need to
declare this task at some point in the build.xml
prior to the groovyc
task being invoked.
<taskdef name="groovyc"
classname="org.codehaus.groovy.ant.Groovyc"
classpathref="my.classpath"/>
<groovyc> Attributes
Attribute | Description | Required |
---|---|---|
configscript |
Set the configuration file used to customize the compilation configuration. |
No |
srcdir |
Location of the Groovy (and possibly Java) source files. |
Yes |
destdir |
Location to store the class files. |
Yes |
classpath |
The classpath to use. |
No |
classpathref |
The classpath to use given as a path references. |
No |
sourcepath |
The sourcepath to use. |
No |
sourcepathref |
The sourcepath to use given as a path reference. |
No |
encoding |
Encoding of source files. |
No |
verbose |
Asks the compiler for verbose output; defaults to no. |
No |
includeAntRuntime |
Whether to include the Ant run-time libraries in the classpath; defaults to yes. |
No |
includeJavaRuntime |
Whether to include the default run-time libraries from the executing VM in the classpath; defaults to no. |
No |
fork |
Whether to execute groovyc using a spawned instance of the JVM; defaults to no. |
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) |
No |
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) |
No |
failonerror |
Indicates whether compilation errors will fail the build; defaults to true. |
No |
listfiles |
Indicates whether the source files to be compiled will be listed; defaults to no. |
No |
stacktrace |
if true each compile error message will contain a stacktrace |
No |
indy |
Enable compilation with the “invoke dynamic” support when using Groovy 2.0 and beyond and running on JDK 7 |
No |
scriptBaseClass |
Sets the base class for Groovy scripts |
No |
stubdir |
Set the stub directory into which the Java source stub files should be generated. The directory need not exist and will not be deleted automatically - though its contents will be cleared unless keepStubs is true. Ignored when forked. |
No |
keepStubs |
Set the keepStubs flag. Defaults to false. Set to true for debugging. Ignored when forked. |
No |
forceLookupUnnamedFiles |
The Groovyc Ant task is frequently used in the context of a build system that knows the complete list of source files to be compiled. In such a context, it is wasteful for the Groovy compiler to go searching the classpath when looking for source files and hence by default the Groovyc Ant task calls the compiler in a special mode with such searching turned off. If you wish the compiler to search for source files then you need to set this flag to true. Defaults to false. |
No |
Example:
<groovyc srcdir="src" destdir="target/classes">
</groovyc>
<groovyc> Nested Elements
element | kind | Required | Replaces Attribute |
---|---|---|---|
javac |
javac task |
No |
jointCompilationOptions |
src |
a path structure |
Yes (unless srcdir is used) |
srcdir |
classpath |
a path structure |
No |
classpath |
Notes:
-
For path structures see for example http://ant.apache.org/manual/using.html#path
-
For usages of the javac task see http://ant.apache.org/manual/CoreTasks/javac.html
-
The nested javac task behaves more or less as documented for the top-level
javac
task.srcdir
,destdir
,classpath
,encoding
for the nestedjavac
task are taken from the enclosinggroovyc
task. If these attributes are specified then they are added, they do not replace. In fact, you should not attempt to overwrite the destination. Other attributes and nested elements are unaffected, for examplefork
,memoryMaximumSize
, etc. may be used freely.
Joint Compilation
Joint compilation is enabled by using an embedded javac
element, as shown in
the following example:
<groovyc srcdir="${testSourceDirectory}" destdir="${testClassesDirectory}">
<classpath>
<pathelement path="${mainClassesDirectory}"/>
<pathelement path="${testClassesDirectory}"/>
<path refid="testPath"/>
</classpath>
<javac source="1.7" target="1.7" debug="on" />
</groovyc>
It is rare to specify srcdir
and destdir
, the nested javac
task is provided with the srcdir
and destdir
values from the enclosing groovyc
task, and it is invariable
the right thing to do just to leave this as is.
To restate: the javac
task gets the srcdir
, destdir
and classpath
from
the enclosing groovyc
task.
More details about joint compilation can be found in the joint compilation section.
2.1.3. Maven integration
There are several approaches to compiling Groovy code in your Maven projects. GMaven is the most flexible and feature rich, but it has some difficulties with joint Java-Groovy projects and it is no longer under active development. The Groovy-Eclipse compiler plugin for Maven sidesteps the joint compilation issues. Read this for a deeper discussion of the benefits and disadvantages of the two approaches.
A third approach is to use Maven’s Ant plugin to compile a groovy project. Note that the Ant plugin is bound to the compile and test-compile phases of the build in the example below. It will be invoked during these phases and the contained tasks will be carried out which runs the Groovy compiler over the source and test directories. The resulting Java classes will coexist with and be treated like any standard Java classes compiled from Java source and will appear no different to the JRE, or the JUnit runtime.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycomp.MyGroovy</groupId>
<artifactId>MyGroovy</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>Maven Example building a Groovy project</name>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.1.6</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<configuration>
<tasks>
<mkdir dir="${basedir}/src/main/groovy"/>
<taskdef name="groovyc"
classname="org.codehaus.groovy.ant.Groovyc">
<classpath refid="maven.compile.classpath"/>
</taskdef>
<mkdir dir="${project.build.outputDirectory}"/>
<groovyc destdir="${project.build.outputDirectory}"
srcdir="${basedir}/src/main/groovy/" listfiles="true">
<classpath refid="maven.compile.classpath"/>
</groovyc>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<configuration>
<tasks>
<mkdir dir="${basedir}/src/test/groovy"/>
<taskdef name="groovyc"
classname="org.codehaus.groovy.ant.Groovyc">
<classpath refid="maven.test.classpath"/>
</taskdef>
<mkdir dir="${project.build.testOutputDirectory}"/>
<groovyc destdir="${project.build.testOutputDirectory}"
srcdir="${basedir}/src/test/groovy/" listfiles="true">
<classpath refid="maven.test.classpath"/>
</groovyc>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
This assumes you have a Maven project setup with groovy
subfolders
as peers to the java src and test subfolders. You can use the java
/jar
archetype to set this up then rename the java folders to groovy or keep
the java folders and just create groovy peer folders. There exists, also
a groovy plugin which has not been tested or used in production. After
defining the build section as in the above example, you can invoke the
typical Maven build phases normally. For example, mvn test
will
execute the test phase, compiling Groovy source and Groovy test source
and finally executing the unit tests. If you run mvn jar
it will
execute the jar phase bundling up all of your compiled production
classes into a jar after all of the unit tests pass. For more detail on
Maven build phases consult the Maven2 documentation.
2.1.4. GMaven and GMavenPlus
GMaven
Example:
<dependencies>
<dependency>
<groupId>org.codehaus.gmaven.runtime</groupId>
<artifactId>gmaven-runtime-default</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>generateStubs</goal>
<goal>compile</goal>
<goal>generateTestStubs</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Important:
You should be aware that GMaven is not supported anymore and has problems with joint compilation. Should you need joint compilation, we advise that you use the Groovy Eclipse maven plugin.
GMavenPlus
GMavenPlus is a rewrite of GMaven which is in active development. It does not support all the features of GMaven but supports newer versions of Groovy, invokedynamic, as well as joint compilation, through stubs (which means it has the same potential issues as GMaven). The main advantage over its predecessor is that it compiles with recent versions of the compiler and supports choosing what version of Groovy is used.
GMaven2
See GMaven 2
Unlike the name seems to indicate, GMaven 2 is not aimed at replacing GMaven. In fact, it’s a rewrite of the scripting features of the GMaven plugin. Interestingly, it supports the missing features of GMavenPlus, that is to say:
-
Script execution
-
Command-line shell access
-
GUI console access
So it may be used as a complement to the Groovy Eclipse plugin or GMavenPlus.
2.1.5. The Groovy Eclipse Maven plugin
Groovy-Eclipse provides a compiler plugin for Maven. Using the compiler plugin, it is possible to compile your maven projects using the Groovy-Eclipse compiler.
The most recent version of the Groovy-Eclipse-Compiler plugin for maven is 2.8.0-01.2.9.0-01-SNAPSHOT is now available from http://nexus.codehaus.org/snapshots/ .The most recent version of the groovy-eclipse-batch artifact is 2.1.5-03 (for Groovy 2.1) and 2.0.7-03 (for Groovy 2.0). They are both available from maven central.
How to use the compiler plugin—Setting up the POM
In your plugin section, you must change the compiler used by the
maven-compiler-plugin.
Like the javac ant task,
the maven-compiler-plugin does not actually compile, but rather
delegates the compilation to a different artifact (in our case, the
groovy-eclipse-batch
artifact):
<build>
...
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<!-- 2.8.0-01 and later require maven-compiler-plugin 3.0 or higher -->
<version>3.0</version>
<configuration>
<compilerId>groovy-eclipse-compiler</compilerId>
<!-- set verbose to be true if you want lots of uninteresting messages -->
<!-- <verbose>true</verbose> -->
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-eclipse-compiler</artifactId>
<version>2.8.0-01</version>
</dependency>
<!-- for 2.8.0-01 and later you must have an explicit dependency on groovy-eclipse-batch -->
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-eclipse-batch</artifactId>
<version>2.1.5-03</version>
<!-- or choose a different compiler version -->
<!-- <version>1.8.6-01</version> -->
<!-- <version>1.7.10-06</version> -->
</dependency>
</dependencies>
</plugin>
...
</plugins>
</build>
This will allow Groovy files to be compiled. The groovy-eclipse-compiler recognizes all settings supported by the maven-compiler-plugin.
Remember that you still need to specify a groovy artifact as a build
dependency in addition to the maven-compiler-plugin
dependency. The
groovy dependency version should match the compiler version. Something
like this:
<dependencies>
...
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>1.8.6</version>
</dependency>
...
</dependencies>
Note that the groovy-eclipse-compiler and groovy-eclipse-batch artifacts are available in Maven-central, so there is no need to explicitly declare any extra repositories.
Setting up the source folders
There are several ways to set up your maven project to recognize Groovy source files
Do nothing
The simplest way to set up your source folders is to do nothing at all:
add all of your Groovy files to src/main/java
and src/test/java
.
This requires absolutely no extra configuration and is easy to
implement. However, this is not a standard maven approach to setting up
your project. If you require a more standard maven approach, then it is
possible to put your Groovy files in src/main/groovy
and
src/test/groovy
and you Java files in src/main/java
and
src/test/java
. There are several ways of doing this.
Do almost nothing
If there is at least one file (Java or not) in src/main/java
, then
all files in src/main/groovy
will be found. If, however,
src/main/java
is empty, then src/main/groovy
will be ignored. You
can get around this by placing an empty file in src/main/java
just so
that src/main/groovy
will be recognized. The same is true for
src/test/java
and src/test/groovy
. This is actually a workaround for
GRECLIPSE-1221.
Use the groovy-eclipse-compiler
mojo for configuring source folders
(You only need this approach if your project has an empty
src/main/java
or src/test/java
.)
If your project has no Java files and you don’t want to add an empty
file in src/main/java
, then you can configure source files by
referencing the groovy-eclipse-compiler mojo. Just add this to the
plugins
section of your pom:
<build>
...
<plugin>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-eclipse-compiler</artifactId>
<version>2.8.0-01</version>
<extensions>true</extensions>
</plugin>
...
</build>
The <extensions>true</extensions>
section is important because this
redefines the default lifecycle of your project so that an extra phase
is added. This phase has an extra goal attached to it that adds the two
Groovy source folders.
Use the build-helper-maven-plugin
(You only need this approach if your project has an empty
src/main/java
or src/test/java
.)
The build-helper-maven-plugin
allows you to do things like adding
extra source folders to your project without needing to redefine the
default lifecycle. You need to add this configuration to your build
plugin section:
<build>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/main/groovy</source>
</sources>
</configuration>
</execution>
<execution>
<id>add-test-source</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/test/groovy</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
...
</build>
The benefit of using this approach is that you do not need to make any changes to the default lifecycle. The downside is, of course, that you need 31 lines of configuration to do this!
Sample project and source code
There is an archetype available for this project. You can use it through a command like this:
mvn archetype:generate \
-DarchetypeGroupId=org.codehaus.groovy \
-DarchetypeArtifactId=groovy-eclipse-quickstart \
-DarchetypeVersion=2.5.2-01 \
-DgroupId=foo \
-DartifactId=bar \
-Dversion=1 \
-DinteractiveMode=false \
-DarchetypeRepository=https://nexus.codehaus.org/content/repositories/snapshots/
(This archetype is not actively maintained.)
A sample project using the compiler plugin as well as the source code for the plugin itself are available from the github repository:
The full URL to the maven projects is:https://github.com/groovy/groovy-eclipse/tree/master/extrasThere are several projects in the repository:groovy-eclipse-compiler : the compiler plugin itself (an m2eclipse project).groovy-eclipse-batch-builder : a set of ant scripts and configuration files used to build the groovy-eclipse-batch artifact. This artifact is an amalgamation of all jars required for compiling Groovy and Java code in Eclipse, including ecj (the Eclipse compiler for Java), the non-UI components of Groovy-Eclipse, the Groovy jars, and various required Eclipse bundles.groovy-eclipse-maven-tests : a sample project that uses the compiler plugin (an m2eclipse project).org.codehaus.groovy.m2eclipse : an Eclipse plugin that provides integration between Groovy-Eclipse and m2eclipse (the Maven tooling for Eclipse).Feature org.codehaus.groovy.m2eclipse : an Eclipse feature that is required for building and releasing the org.codehaus.groovy.m2eclipse plugin.
The sample project and archetype is not maintained as well as we would like. Some community help with this would be greatly appreciated. Please see GRECLIPSE-1285.
Why another Groovy compiler for Maven? What about GMaven?
GMaven 2.0 and later no longer supports compilation. You can read more about this on the GMaven 2 project page. GMaven 1.x is now deprecated.
GMaven 1.x had limitations over the groovy-eclipse-compiler and for the following reasons GMaven 2.0 compilation is no longer supported:
-
The compiler plugin does not require the creation of Java stubs so that your Groovy files can compile against Java files. This will prevent some arcane compile errors from appearing.
-
The Groovy-Eclipse compiler is the same inside Eclipse and inside Maven, and so configuration across the two platforms can be simplified.
-
The compiler plugin is a standard compiler plugin for Maven. It therefore follows all allows all the same standard configuration that the Javac compiler plugin uses. This makes it simpler to introduce Groovy into an existing Maven project. All you need to do is change the compiler plugin that the pom references.
There are still some reasons to use GMaven:
-
GroovyDoc tool is not supported because the compiler plugin does not produce stubs.
-
Groovy Mojos are not supported.
-
Groovy scripts cannot be executed in your poms.
Whether or not the Groovy-Eclipse compiler plugin for Maven is appropriate for your project will depend on your requirements.
Project Lombok
Project Lombok is compatible with the groovy-eclipse-compiler. There is some extra configuration that you need to do. The lombok jar needs to be added to both the build and compile dependencies sections:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>0.10.4</version>
</dependency>
Also, the following configuration needs to be added to the maven-compiler-plugin configuration:
<configuration>
<compilerId>groovy-eclipse-compiler</compilerId>
<verbose>true</verbose>
<compilerArguments>
<javaAgentClass>lombok.core.Agent</javaAgentClass>
</compilerArguments>
<fork>true</fork>
</configuration>
Groovy-Eclipse configurator for m2Eclipse
If you are going to be working with your maven project inside of Eclipse, it is strongly recommended that you use m2eclipse. And to use your Groovy projects with m2eclipse, you will need to install the Groovy-Eclipse configurator for m2eclipse. This feature is available any of the Groovy-Eclipse update sites (e.g., nightly, milestone, or release). Just go to your Eclipse update manager and add the Groovy-Eclipse update sites (if you haven’t done so already). Select the Groovy-Eclipse M2E integration.
Release Builds
Eclipse level |
Release update site |
4.2 (Juno) |
|
3.7 (Indigo) |
Development Builds
Eclipse level |
Development update site |
4.2 (Juno) |
|
3.7 (Indigo) |
The Groovy-Eclipse configurator for m2eclipse is not compatible with AspectJ or Scala. So you cannot use a joint AspectJ/Scala/Groovy project in Eclipse. These languages must be separated into separate sub-projects.
Where to find more information and ask questions
Please ask all questions on the Groovy-Eclipse mailing list. Any bugs or feature enhancements should go on Groovy-Eclipse’s jira.
2.1.6. Joint compilation
Joint compilation means that the Groovy compiler will parse the Groovy source files, create stubs for all of them, invoke the Java compiler to compile the stubs along with Java sources, and then continue compilation in the normal Groovy compiler way. This allows mixing of Java and Groovy files without constraint.
Joint compilation can be enabled using the -j
flag with the command-line compiler,
or using using a nested tag and all the attributes and further nested tags as required
for the Ant task.
It is important to know that if you don’t enable joint compilation and try to compile Java source files with the Groovy compiler, the Java source files will be compiled as if they were Groovy sources. In some situations, this might work since most of the Java syntax is compatible with Groovy, but semantics would be different.