You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2019/11/15 17:33:42 UTC

[groovy] branch groovy25-groovyc updated (690b12d -> b8146f1)

This is an automated email from the ASF dual-hosted git repository.

emilles pushed a change to branch groovy25-groovyc
in repository https://gitbox.apache.org/repos/asf/groovy.git.


 discard 690b12d  GROOVY-8775, GROOVY-9197: Ant: separate JVM and compilation classpaths
     new b8146f1  GROOVY-8775, GROOVY-9197: Ant: separate JVM and compilation classpaths

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (690b12d)
            \
             N -- N -- N   refs/heads/groovy25-groovyc (b8146f1)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../src/main/java/org/codehaus/groovy/ant/Groovyc.java           | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)


[groovy] 01/01: GROOVY-8775, GROOVY-9197: Ant: separate JVM and compilation classpaths

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch groovy25-groovyc
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit b8146f10e6249a2d2bf3745227ac9202c06633cc
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Nov 15 10:23:46 2019 -0600

    GROOVY-8775, GROOVY-9197: Ant: separate JVM and compilation classpaths
---
 .../codehaus/groovy/tools/FileSystemCompiler.java  | 242 +++++++------
 src/spec/doc/tools-groovyc.adoc                    |  70 ++--
 .../main/java/org/codehaus/groovy/ant/Groovyc.java | 393 ++++++++++++---------
 3 files changed, 393 insertions(+), 312 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/tools/FileSystemCompiler.java b/src/main/java/org/codehaus/groovy/tools/FileSystemCompiler.java
index 9a0d042..8c80956 100644
--- a/src/main/java/org/codehaus/groovy/tools/FileSystemCompiler.java
+++ b/src/main/java/org/codehaus/groovy/tools/FileSystemCompiler.java
@@ -41,7 +41,6 @@ import java.io.File;
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -54,6 +53,8 @@ import static groovy.ui.GroovyMain.processConfigScripts;
  * Command-line compiler (aka. <tt>groovyc</tt>).
  */
 public class FileSystemCompiler {
+
+    private static boolean displayStackTraceOnError;
     private final CompilationUnit unit;
 
     public FileSystemCompiler(CompilerConfiguration configuration) throws ConfigurationException {
@@ -70,38 +71,40 @@ public class FileSystemCompiler {
         }
     }
 
-    public void compile(String[] paths) throws Exception {
-        unit.addSources(paths);
-        unit.compile();
-    }
-
-    public void compile(File[] files) throws Exception {
-        unit.addSources(files);
-        unit.compile();
-    }
-
-    /** Prints the usage help message for {@link CompilationOptions} to stderr.
+    /**
+     * Prints the usage help message for {@link CompilationOptions} to stderr.
+     *
      * @see #displayHelp(PrintWriter)
-     * @since 2.5 */
+     * @since 2.5
+     */
     public static void displayHelp() {
         displayHelp(new PrintWriter(System.err, true));
     }
 
-    /** Prints the usage help message for the {@link CompilationOptions} to the specified PrintWriter.
-     * @since 2.5 */
-    public static void displayHelp(final PrintWriter writer) {
+    /**
+     * Prints the usage help message for the {@link CompilationOptions} to the specified PrintWriter.
+     *
+     * @since 2.5
+     */
+    public static void displayHelp(PrintWriter writer) {
         configureParser(new CompilationOptions()).usage(writer);
     }
 
-    /** Prints version information to stderr.
-     * @see #displayVersion(PrintWriter) */
+    /**
+     * Prints version information to stderr.
+     *
+     * @see #displayVersion(PrintWriter)
+     */
     public static void displayVersion() {
         displayVersion(new PrintWriter(System.err, true));
     }
 
-    /** Prints version information to the specified PrintWriter.
-     * @since 2.5 */
-    public static void displayVersion(final PrintWriter writer) {
+    /**
+     * Prints version information to the specified PrintWriter.
+     *
+     * @since 2.5
+     */
+    public static void displayVersion(PrintWriter writer) {
         for (String line : new VersionProvider().getVersion()) {
             writer.println(line);
         }
@@ -114,10 +117,10 @@ public class FileSystemCompiler {
             File file = new File(filename);
             if (!file.exists()) {
                 System.err.println("error: file not found: " + file);
-                ++errors;
+                errors += 1;
             } else if (!file.canRead()) {
                 System.err.println("error: file not readable: " + file);
-                ++errors;
+                errors += 1;
             }
         }
 
@@ -128,8 +131,6 @@ public class FileSystemCompiler {
         return checkFiles(filenames) == 0;
     }
 
-    private static boolean displayStackTraceOnError = false;
-
     /**
      * Same as main(args) except that exceptions are thrown out instead of causing
      * the VM to exit.
@@ -152,18 +153,18 @@ public class FileSystemCompiler {
         displayStackTraceOnError = options.printStack;
         CompilerConfiguration configuration = options.toCompilerConfiguration();
 
-        // Load the file name list
-        String[] filenames = options.generateFileNames();
-        boolean fileNameErrors = filenames == null;
-        if (!fileNameErrors && (filenames.length == 0)) {
+        // load the file name list
+        String[] fileNames = options.generateFileNames();
+        boolean fileNameErrors = fileNames == null;
+        if (!fileNameErrors && (fileNames.length == 0)) {
             parser.usage(System.err);
             return;
         }
 
-        fileNameErrors = fileNameErrors && !validateFiles(filenames);
+        fileNameErrors = fileNameErrors && !validateFiles(fileNames);
 
         if (!fileNameErrors) {
-            doCompilation(configuration, null, filenames, lookupUnnamedFiles);
+            doCompilation(configuration, null, fileNames, lookupUnnamedFiles);
         }
     }
 
@@ -219,8 +220,7 @@ public class FileSystemCompiler {
         // if there are any joint compilation options set stubDir if not set
         try {
             if ((configuration.getJointCompilationOptions() != null)
-                && !configuration.getJointCompilationOptions().containsKey("stubDir"))
-            {
+                    && !configuration.getJointCompilationOptions().containsKey("stubDir")) {
                 tmpDir = DefaultGroovyStaticMethods.createTempDir(null, "groovy-generated-", "-java-source");
                 configuration.getJointCompilationOptions().put("stubDir", tmpDir);
             }
@@ -235,7 +235,8 @@ public class FileSystemCompiler {
                 }
             } else {
                 compiler.unit.getClassLoader().setResourceLoader(new GroovyResourceLoader() {
-                    public URL loadGroovySource(String filename) throws MalformedURLException {
+                    @Override
+                    public URL loadGroovySource(String filename) {
                         return null;
                     }
                 });
@@ -254,7 +255,7 @@ public class FileSystemCompiler {
         if (filenames == null) {
             return new String[0];
         }
-        List<String> fileList = new ArrayList<String>(filenames.size());
+        List<String> fileList = new ArrayList<>(filenames.size());
         boolean errors = false;
         for (String filename : filenames) {
             if (filename.startsWith("@")) {
@@ -289,12 +290,72 @@ public class FileSystemCompiler {
         }
     }
 
+    public static void deleteRecursive(File file) {
+        if (!file.exists()) {
+            return;
+        }
+        if (file.isDirectory()) {
+            for (File f : file.listFiles()) {
+                deleteRecursive(f);
+            }
+        }
+        file.delete();
+    }
+
+    public void compile(String[] paths) throws Exception {
+        unit.addSources(paths);
+        unit.compile();
+    }
+
+    public void compile(File[] files) throws Exception {
+        unit.addSources(files);
+        unit.compile();
+    }
+
     /**
-     * @since 2.5 */
+     * @deprecated use {@link #displayHelp(PrintWriter)} instead
+     */
+    @Deprecated
+    public static void displayHelp(Options options) {
+        final HelpFormatter formatter = new HelpFormatter();
+        formatter.printHelp(80, "groovyc [options] <source-files>", "options:", options, "");
+    }
+
+    // some methods to avoid binary incompatibility - don't gain us a lot but gives the user
+    // something slightly less cryptic than a NoSuchMethodError or an IncompatibleClassChangeError
+    @Deprecated
+    public static CompilerConfiguration generateCompilerConfigurationFromOptions(org.apache.commons.cli.CommandLine cli) {
+        throw new DeprecationException("This method is not supported for Groovy 2.5+. Consider instead using the FileSystemCompiler.CompilationOptions class.");
+    }
+
+    @Deprecated
+    public static String[] generateFileNamesFromOptions(org.apache.commons.cli.CommandLine cli) {
+        throw new DeprecationException("This method is not supported for Groovy 2.5+. Consider instead using the FileSystemCompiler.CompilationOptions class.");
+    }
+
+    @Deprecated
+    public static Options createCompilationOptions() {
+        throw new DeprecationException("This method is not supported for Groovy 2.5+. Consider instead using the FileSystemCompiler.CompilationOptions class.");
+    }
+
+    /**
+     * Creates a temporary directory in the default temporary directory (as specified by the system
+     * property <i>java.io.tmpdir</i>.
+     *
+     * @deprecated Use {@link DefaultGroovyStaticMethods#createTempDir(java.io.File, String, String)} instead.
+     */
+    @Deprecated
+    public static File createTempDir() throws IOException {
+        return DefaultGroovyStaticMethods.createTempDir(null);
+    }
+
+    /**
+     * @since 2.5
+     */
     static class VersionProvider implements IVersionProvider {
         @Override
         public String[] getVersion() {
-            return new String[] {
+            return new String[]{
                     "Groovy compiler version " + GroovySystem.getVersion(),
                     "Copyright 2003-2019 The Apache Software Foundation. http://groovy-lang.org/",
                     "",
@@ -303,11 +364,9 @@ public class FileSystemCompiler {
     }
 
     /**
-     * @since 2.5 */
-    @Command(name = "groovyc",
-            customSynopsis = "groovyc [options] <source-files>",
-            sortOptions = false,
-            versionProvider = VersionProvider.class)
+     * @since 2.5
+     */
+    @Command(name = "groovyc", customSynopsis = "groovyc [options] <source-files>", sortOptions = false, versionProvider = VersionProvider.class)
     public static class CompilationOptions {
         // IMPLEMENTATION NOTE:
         // classpath must be the first argument, so that the `startGroovy(.bat)` script
@@ -361,43 +420,41 @@ public class FileSystemCompiler {
         @Option(names = {"-v", "--version"}, versionHelp = true, description = "Print version information and exit")
         private boolean versionRequested;
 
-        @Parameters(description = "The groovy source files to compile, or @-files containing a list of source files to compile",
-                    paramLabel = "<source-files>")
+        @Parameters(description = "The groovy source files to compile, or @-files containing a list of source files to compile", paramLabel = "<source-files>")
         private List<String> files;
 
         public CompilerConfiguration toCompilerConfiguration() throws IOException {
-            // Setup the configuration data
             CompilerConfiguration configuration = new CompilerConfiguration();
 
             if (classpath != null) {
                 configuration.setClasspath(classpath);
             }
 
-            if (targetDir != null && targetDir.getName().length() > 0) {
+            if (targetDir != null && !targetDir.getName().isEmpty()) {
                 configuration.setTargetDirectory(targetDir);
             }
 
             configuration.setParameters(parameterMetadata);
             configuration.setPreviewFeatures(previewFeatures);
-            configuration.setSourceEncoding(encoding);
             configuration.setScriptBaseClass(scriptBaseClass);
+            configuration.setSourceEncoding(encoding);
 
             // joint compilation parameters
             if (jointCompilation) {
-                Map<String, Object> compilerOptions = new HashMap<String, Object>();
-                compilerOptions.put("namedValues", javacOptionsList());
-                compilerOptions.put("flags", flagsWithParameterMetaData());
+                Map<String, Object> compilerOptions = new HashMap<>();
+                compilerOptions.put("flags", javacFlags());
+                compilerOptions.put("namedValues", javacNamedValues());
                 configuration.setJointCompilationOptions(compilerOptions);
             }
 
             if (indy) {
-                configuration.getOptimizationOptions().put("int", false);
-                configuration.getOptimizationOptions().put("indy", true);
+                configuration.getOptimizationOptions().put("int", Boolean.FALSE);
+                configuration.getOptimizationOptions().put("indy", Boolean.TRUE);
             }
 
             String configScripts = System.getProperty("groovy.starter.configscripts", null);
             if (configScript != null || (configScripts != null && !configScripts.isEmpty())) {
-                List<String> scripts = new ArrayList<String>();
+                List<String> scripts = new ArrayList<>();
                 if (configScript != null) {
                     scripts.add(configScript);
                 }
@@ -414,76 +471,29 @@ public class FileSystemCompiler {
             return generateFileNamesFromOptions(files);
         }
 
-        String[] javacOptionsList() {
-            if (javacOptionsMap == null) {
-                return null;
-            }
-            List<String> result = new ArrayList<String>();
-            for (Map.Entry<String, String> entry : javacOptionsMap.entrySet()) {
-                result.add(entry.getKey());
-                result.add(entry.getValue());
+        private String[] javacNamedValues() {
+            List<String> result = new ArrayList<>();
+            if (javacOptionsMap != null) {
+                for (Map.Entry<String, String> entry : javacOptionsMap.entrySet()) {
+                    result.add(entry.getKey());
+                    result.add(entry.getValue());
+                }
             }
-            return result.toArray(new String[0]);
+            return result.isEmpty() ? null : result.toArray(new String[0]);
         }
 
-        String[] flagsWithParameterMetaData() {
-            if (flags == null) {
-                return null;
+        private String[] javacFlags() {
+            List<String> result = new ArrayList<>();
+            if (flags != null) {
+                result.addAll(flags);
             }
             if (parameterMetadata) {
-                flags.add("parameters");
+                result.add("parameters");
             }
-            return flags.toArray(new String[0]);
-        }
-    }
-
-    /** @deprecated use {@link #displayHelp(PrintWriter)} instead */
-    @Deprecated
-    public static void displayHelp(final Options options) {
-        final HelpFormatter formatter = new HelpFormatter();
-        formatter.printHelp(80, "groovyc [options] <source-files>", "options:", options, "");
-    }
-
-    // some methods to avoid binary incompatibility - don't gain us a lot but gives the user
-    // something slightly less cryptic than a NoSuchMethodError or an IncompatibleClassChangeError
-    @Deprecated
-    public static CompilerConfiguration generateCompilerConfigurationFromOptions(org.apache.commons.cli.CommandLine cli) throws IOException {
-        throw new DeprecationException("This method is not supported for Groovy 2.5+. Consider instead using the FileSystemCompiler.CompilationOptions class.");
-    }
-
-    @Deprecated
-    public static String[] generateFileNamesFromOptions(org.apache.commons.cli.CommandLine cli) {
-        throw new DeprecationException("This method is not supported for Groovy 2.5+. Consider instead using the FileSystemCompiler.CompilationOptions class.");
-    }
-
-    @Deprecated
-    public static Options createCompilationOptions() {
-        throw new DeprecationException("This method is not supported for Groovy 2.5+. Consider instead using the FileSystemCompiler.CompilationOptions class.");
-    }
-
-    /**
-     * Creates a temporary directory in the default temporary directory (as specified by the system
-     * property <i>java.io.tmpdir</i>.
-     *
-     * @deprecated Use {@link DefaultGroovyStaticMethods#createTempDir(java.io.File, String, String)} instead.
-     */
-    @Deprecated
-    public static File createTempDir() throws IOException {
-        return DefaultGroovyStaticMethods.createTempDir(null);
-    }
-
-    public static void deleteRecursive(File file) {
-        if (!file.exists()) {
-            return;
-        }
-        if (file.isFile()) {
-            file.delete();
-        } else if (file.isDirectory()) {
-            File[] files = file.listFiles();
-            for (int i = 0; i < files.length; i++) {
-                deleteRecursive(files[i]);
+            if (previewFeatures) {
+                result.add("-enable-preview");
             }
-            file.delete();
+            return result.isEmpty() ? null : result.toArray(new String[0]);
         }
     }
 }
diff --git a/src/spec/doc/tools-groovyc.adoc b/src/spec/doc/tools-groovyc.adoc
index 7871561..6d81049 100644
--- a/src/spec/doc/tools-groovyc.adoc
+++ b/src/spec/doc/tools-groovyc.adoc
@@ -75,16 +75,18 @@ Compiles Groovy source files and, if joint compilation option is used, Java sour
 Required taskdef
 ^^^^^^^^^^^^^^^^
 
-Assuming all the groovy jars you need are in _my.classpath_ (this will be `groovy-VERSION.jar`,
-`groovy-ant-VERSION.jar` plus any modules and transitive dependencies you might be using)
-you will need to declare this task at some point in the `build.xml` prior to the `groovyc` task being invoked.
+Assuming the groovy jars are in _groovy.libs_, you will need to declare this task
+at some point in the `build.xml` prior to the `groovyc` task being invoked.
 
 [source,xml]
-----------------------------------------------------
-<taskdef name="groovyc"
-         classname="org.codehaus.groovy.ant.Groovyc"
-         classpathref="my.classpath"/>
-----------------------------------------------------
+-----------------------------------------------------------------------
+<taskdef name="groovyc" classname="org.codehaus.groovy.ant.Groovyc">
+  <classpath>
+    <fileset file="${groovy.libs}/groovy-ant-VERSION.jar"/>
+    <fileset file="${groovy.libs}/groovy-VERSION.jar"/>
+  </classpath>
+</taskdef>
+-----------------------------------------------------------------------
 
 [[ThegroovycAntTask-groovycAttributes]]
 <groovyc> Attributes
@@ -166,6 +168,9 @@ you need to set this flag to true. Defaults to false. |No
 |parameters |Generates metadata for reflection on method parameter names on JDK 8 and above.
 Defaults to false. |No
 
+|previewFeatures |Enables the JEP preview features on JDK 12 and above.
+Defaults to false. |No
+
 |targetBytecode |Sets the bytecode compatibility level. |No
 
 |javahome |Sets the `java.home` value to use, default is the current JDK's home. |No
@@ -187,10 +192,14 @@ the compilation fails. |No
 *Example:*
 
 [source,xml]
-----
-<groovyc srcdir="src" destdir="target/classes">
-</groovyc>
-----
+-----------------------------------------------------------------------
+<path id="classpath.main">
+  <fileset dir="${groovy.libs}" includes="*.jar" excludes="groovy-ant-*.jar"/>
+  ...
+</path>
+<groovyc srcdir="${dir.sources}" destdir="${dir.classes}" classpathref="classpath.main"
+         fork="true" includeantruntime="false" configscript="config.groovy" targetBytecode="1.8"/>
+-----------------------------------------------------------------------
 
 
 [[ThegroovycAntTask-groovycNestedElements]]
@@ -201,48 +210,41 @@ the compilation fails. |No
 |==========================================================
 |element |kind |Required |Replaces Attribute
 |src |a path structure |Yes (unless srcdir is used) |srcdir
-|classpath |a path structure |No |classpath
-|javac |javac task |No |jointCompilationOptions
+|classpath |a path structure |No |classpath or classpathref
+|javac |javac task |No |N/A
 |==========================================================
 
 *Notes:*
 
 * For path structures see for example
 http://ant.apache.org/manual/using.html#path
-* For usages of the javac task see
+* For usages of the `javac` task see
 https://ant.apache.org/manual/Tasks/javac.html
-* The nested javac task behaves more or less as documented for the
-top-level `javac` task. `srcdir`, `destdir`, `classpath`, `encoding` for the
-nested `javac` task are taken from the enclosing `groovyc` 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 example `fork`,
-`memoryMaximumSize`, etc. may be used freely.
+* The nested `javac` task behaves more or less as documented for the top-level
+`javac` task. `srcdir`, `destdir`, `classpath`, `encoding` and `parameters`
+for the nested `javac` task are taken from the enclosing `groovyc` 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 example `fork`, `memoryMaximumSize`, etc. may be
+used freely.
 
 [[ThegroovycAntTask-JointCompilation]]
 Joint Compilation
 ^^^^^^^^^^^^^^^^^
 
-Joint compilation is enabled by using an embedded `javac` element, as shown in
-the following example:
+Joint compilation is enabled by using an embedded `javac` element, as shown in the following example:
 
 [source,xml]
-----
-<groovyc srcdir="${testSourceDirectory}" destdir="${testClassesDirectory}">
+-----------------------------------------------------------------------
+<groovyc srcdir="${testSourceDirectory}" destdir="${testClassesDirectory}" targetBytecode="1.8">
   <classpath>
     <pathelement path="${mainClassesDirectory}"/>
     <pathelement path="${testClassesDirectory}"/>
     <path refid="testPath"/>
   </classpath>
-  <javac source="1.7" target="1.7" debug="on" />
+  <javac debug="true" source="1.8" target="1.8" />
 </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 <<section-jointcompilation,joint compilation>> section.
 
diff --git a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovyc.java b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovyc.java
index 899536d..dd9b054 100644
--- a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovyc.java
+++ b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovyc.java
@@ -32,6 +32,7 @@ import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.types.Reference;
 import org.apache.tools.ant.util.GlobPatternMapper;
 import org.apache.tools.ant.util.SourceFileScanner;
+import org.codehaus.groovy.GroovyBugError;
 import org.codehaus.groovy.control.CompilationUnit;
 import org.codehaus.groovy.control.CompilerConfiguration;
 import org.codehaus.groovy.control.SourceExtensionHandler;
@@ -39,8 +40,8 @@ import org.codehaus.groovy.runtime.DefaultGroovyMethods;
 import org.codehaus.groovy.runtime.DefaultGroovyStaticMethods;
 import org.codehaus.groovy.tools.ErrorReporter;
 import org.codehaus.groovy.tools.FileSystemCompiler;
-import org.codehaus.groovy.tools.RootLoader;
 import org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit;
+import org.objectweb.asm.ClassVisitor;
 import picocli.CommandLine;
 
 import java.io.File;
@@ -48,13 +49,14 @@ import java.io.FileWriter;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.Writer;
-import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.net.URL;
 import java.nio.charset.Charset;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
-import java.util.Enumeration;
+import java.util.Collections;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
@@ -68,17 +70,22 @@ import java.util.StringTokenizer;
  * <pre>
  * &lt;?xml version="1.0"?&gt;
  * &lt;project name="MyGroovyBuild" default="compile"&gt;
- *   &lt;property name="groovy.home" value="/Path/To/Groovy"/&gt;
+ *   &lt;property name="groovy.home" location="/Path/To/Groovy"/&gt;
  *   &lt;property name="groovy.version" value="X.Y.Z"/&gt;
- *   &lt;path id="groovy.classpath"&gt;
- *     &lt;fileset dir="${groovy.home}/lib"&gt;
- *       &lt;include name="groovy-*${groovy.version}.jar" /&gt;
- *     &lt;/fileset&gt;
- *   &lt;/path&gt;
- *   &lt;taskdef name="groovyc" classname="org.codehaus.groovy.ant.Groovyc" classpathref="groovy.classpath"/&gt;
+ *
+ *   &lt;taskdef name="groovyc" classname="org.codehaus.groovy.ant.Groovyc"&gt;
+ *     &lt;classpath&gt;
+ *       &lt;fileset file="${groovy.home}/lib/groovy-${groovy.version}.jar"/&gt;
+ *       &lt;fileset file="${groovy.home}/lib/groovy-ant-${groovy.version}.jar"/&gt;
+ *     &lt;/classpath&gt;
+ *   &lt;/taskdef&gt;
  *
  *   &lt;target name="compile" description="compile groovy sources"&gt;
- *     &lt;groovyc srcdir="src" listfiles="true" classpathref="groovy.classpath"/&gt;
+ *     &lt;groovyc srcdir="src" destdir="bin" fork="true" listfiles="true" includeantruntime="false"/&gt;
+ *       &lt;classpath&gt;
+ *         &lt;fileset dir="${groovy.home}/lib" includes="groovy-*${groovy.version}.jar" excludes="groovy-ant-${groovy.version}.jar"/&gt;
+ *       &lt;/classpath&gt;
+ *     &lt;/groovyc&gt;
  *   &lt;/target&gt;
  * &lt;/project&gt;
  * </pre>
@@ -86,13 +93,13 @@ import java.util.StringTokenizer;
  * This task can take the following arguments:
  * <ul>
  * <li>srcdir</li>
- * <li>scriptExtension</li>
- * <li>targetBytecode</li>
  * <li>destdir</li>
  * <li>sourcepath</li>
  * <li>sourcepathRef</li>
  * <li>classpath</li>
  * <li>classpathRef</li>
+ * <li>scriptExtension</li>
+ * <li>targetBytecode</li>
  * <li>listfiles</li>
  * <li>failonerror</li>
  * <li>proceed</li>
@@ -124,39 +131,42 @@ import java.util.StringTokenizer;
  * </ul>
  * Of these arguments, the <b>srcdir</b> and <b>destdir</b> are required.
  * <p>
- * <p>When this task executes, it will recursively scan srcdir and destdir looking for Groovy source files
- * to compile. This task makes its compile decision based on timestamp.
+ * When this task executes, it will recursively scan srcdir and destdir looking
+ * for Groovy source files to compile. This task makes its compile decision based
+ * on timestamp.
  * <p>
  * A more elaborate build file showing joint compilation:
  * <pre>
  * &lt;?xml version="1.0"?&gt;
  * &lt;project name="MyJointBuild" default="compile"&gt;
- *   &lt;property name="groovy.home" value="/Path/To/Groovy"/&gt;
+ *   &lt;property name="groovy.home" location="/Path/To/Groovy"/&gt;
  *   &lt;property name="groovy.version" value="X.Y.Z"/&gt;
  *
- *   &lt;path id="groovy.classpath"&gt;
+ *   &lt;path id="classpath.main"&gt;
  *     &lt;fileset dir="${groovy.home}/lib"&gt;
- *       &lt;include name="groovy-*${groovy.version}.jar" /&gt;
+ *       &lt;include name="groovy-*${groovy.version}.jar"/&gt;
+ *       &lt;exclude name="groovy-ant-${groovy.version}.jar"/&gt;
  *     &lt;/fileset&gt;
  *   &lt;/path&gt;
  *
- *   &lt;target name="clean" description="remove all built files"&gt;
- *     &lt;delete dir="classes" /&gt;
- *   &lt;/target&gt;
+ *   &lt;taskdef name="groovyc" classname="org.codehaus.groovy.ant.Groovyc"&gt;
+ *     &lt;classpath&gt;
+ *       &lt;fileset file="${groovy.home}/lib/groovy-${groovy.version}.jar"/&gt;
+ *       &lt;fileset file="${groovy.home}/lib/groovy-ant-${groovy.version}.jar"/&gt;
+ *     &lt;/classpath&gt;
+ *   &lt;/taskdef&gt;
  *
- *   &lt;target name="compile" depends="init" description="compile java and groovy sources"&gt;
- *     &lt;mkdir dir="classes" /&gt;
- *     &lt;groovyc destdir="classes" srcdir="src" listfiles="true" keepStubs="true" stubdir="stubs"&gt;
- *       &lt;javac debug="on" deprecation="true"/&gt;
- *       &lt;classpath&gt;
- *         &lt;fileset dir="classes"/&gt;
- *         &lt;path refid="groovy.classpath"/&gt;
- *       &lt;/classpath&gt;
- *     &lt;/groovyc&gt;
+ *   &lt;target name="clean"&gt;
+ *     &lt;delete dir="bin" failonerror="false"/&gt;
  *   &lt;/target&gt;
  *
- *   &lt;target name="init"&gt;
- *     &lt;taskdef name="groovyc" classname="org.codehaus.groovy.ant.Groovyc" classpathref="groovy.classpath"/&gt;
+ *   &lt;target name="compile" depends="clean" description="compile java and groovy sources"&gt;
+ *     &lt;mkdir dir="bin"/&gt;
+ *
+ *     &lt;groovyc srcdir="src" destdir="bin" stubdir="stubs" keepStubs="true"
+ *      fork="true" includeantruntime="false" classpathref="classpath.main"&gt;
+ *       &lt;javac debug="true" source="1.8" target="1.8"/&gt;
+ *     &lt;/groovyc&gt;
  *   &lt;/target&gt;
  * &lt;/project&gt;
  * </pre>
@@ -166,9 +176,10 @@ import java.util.StringTokenizer;
  * Can also be used from {@link groovy.util.AntBuilder} to allow the build file to be scripted in Groovy.
  */
 public class Groovyc extends MatchingTask {
-    private static final URL[] EMPTY_URL_ARRAY = new URL[0];
+
     private static final File[] EMPTY_FILE_ARRAY = new File[0];
     private static final String[] EMPTY_STRING_ARRAY = new String[0];
+
     private final LoggingHelper log = new LoggingHelper(this);
 
     private Path src;
@@ -176,20 +187,20 @@ public class Groovyc extends MatchingTask {
     private Path compileClasspath;
     private Path compileSourcepath;
     private String encoding;
-    private boolean stacktrace = false;
-    private boolean verbose = false;
+    private boolean stacktrace;
+    private boolean verbose;
     private boolean includeAntRuntime = true;
-    private boolean includeJavaRuntime = false;
-    private boolean fork = false;
+    private boolean includeJavaRuntime;
+    private boolean fork;
     private File forkJavaHome;
-    private String forkedExecutable = null;
+    private String forkedExecutable;
     private String memoryInitialSize;
     private String memoryMaximumSize;
     private String scriptExtension = "*.groovy";
-    private String targetBytecode = null;
+    private String targetBytecode;
 
     protected boolean failOnError = true;
-    protected boolean listFiles = false;
+    protected boolean listFiles;
     protected File[] compileList = EMPTY_FILE_ARRAY;
 
     private String updatedProperty;
@@ -201,7 +212,7 @@ public class Groovyc extends MatchingTask {
     private Javac javac;
     private boolean jointCompilation;
 
-    private final List<File> temporaryFiles = new ArrayList<File>(2);
+    private final List<File> temporaryFiles = new ArrayList<>(2);
     private File stubDir;
     private boolean keepStubs;
     private boolean forceLookupUnnamedFiles;
@@ -209,17 +220,17 @@ public class Groovyc extends MatchingTask {
     private String scriptBaseClass;
     private String configscript;
 
-    private Set<String> scriptExtensions = new LinkedHashSet<String>();
+    private Set<String> scriptExtensions = new LinkedHashSet<>();
 
     /**
      * If true, generates metadata for reflection on method parameter names (jdk8+ only).  Defaults to false.
      */
-    private boolean parameters = false;
+    private boolean parameters;
 
     /**
      * If true, enable preview Java features (JEP 12) (jdk12+ only). Defaults to false.
      */
-    private boolean previewFeatures = false;
+    private boolean previewFeatures;
 
     /**
      * Adds a path for source compilation.
@@ -297,7 +308,6 @@ public class Groovyc extends MatchingTask {
      * @param version the bytecode compatibility level
      */
     public void setTargetBytecode(String version) {
-
         for (String allowedJdk : CompilerConfiguration.ALLOWED_JDKS) {
             if (allowedJdk.equals(version)) {
                 this.targetBytecode = version;
@@ -884,7 +894,7 @@ public class Groovyc extends MatchingTask {
      */
     protected void resetFileLists() {
         compileList = EMPTY_FILE_ARRAY;
-        scriptExtensions = new LinkedHashSet<String>();
+        scriptExtensions = new LinkedHashSet<>();
     }
 
     /**
@@ -960,64 +970,109 @@ public class Groovyc extends MatchingTask {
         }
     }
 
+    /**
+     * If {@code groovyc} task includes a nested {@code javac} task, check for
+     * shareable configuration.  {@code FileSystemCompiler} supports several
+     * command-line arguments for configuring joint compilation:
+     * <ul>
+     * <li><tt>-j</tt> enables joint compile
+     * <li><tt>-F</tt> is used to pass flags
+     * <li><tt>-J</tt> is used to pass name=value pairs
+     * </ul>
+     * Joint compilation options are transferred from {@link FileSystemCompiler}
+     * to {@link CompilerConfiguration}'s jointCompileOptions property.  Flags
+     * are saved to key "flags" (with the inclusion of "parameters" if enabled
+     * on groovyc), pairs are saved to key "namedValues" and the key "memStub"
+     * may also be set to {@link Boolean#TRUE} to influence joint compilation.
+     *
+     * @see org.codehaus.groovy.tools.javac.JavacJavaCompiler
+     * @see javax.tools.JavaCompiler
+     */
     private List<String> extractJointOptions(Path classpath) {
-        List<String> jointOptions = new ArrayList<String>();
+        List<String> jointOptions = new ArrayList<>();
         if (!jointCompilation) return jointOptions;
 
-        // extract joint options, some get pushed up...
+        // map "debug" and "debuglevel" to "-Fg"
+        if (javac.getDebug()) {
+            String level = javac.getDebugLevel();
+            jointOptions.add("-Fg" + (level == null ? "" : ":" + level));
+        } else {
+            jointOptions.add("-Fg:none");
+        }
+
+        // map "deprecation" to "-Fdeprecation"
+        if (javac.getDeprecation()) {
+            jointOptions.add("-Fdeprecation");
+        }
+
+        // map "nowarn" to "-Fnowarn"
+        if (javac.getNowarn()) {
+            jointOptions.add("-Fnowarn");
+        }
+
+        // map "verbose" to "-Fverbose"
+        if (javac.getVerbose()) {
+            jointOptions.add("-Fverbose");
+        }
+
         RuntimeConfigurable rc = javac.getRuntimeConfigurableWrapper();
-        for (Object o1 : rc.getAttributeMap().entrySet()) {
-            final Map.Entry e = (Map.Entry) o1;
-            final String key = e.getKey().toString();
-            final String value = getProject().replaceProperties(e.getValue().toString());
-            if (key.contains("debug")) {
-                String level = "";
-                if (javac.getDebugLevel() != null) {
-                    level = ":" + javac.getDebugLevel();
+
+        for (Map.Entry<String, Object> e : rc.getAttributeMap().entrySet()) {
+            String key = e.getKey();
+            if (key.equals("depend")
+                    || key.equals("encoding")
+                    || key.equals("extdirs")
+                    || key.equals("nativeheaderdir")
+                    || key.equals("release")
+                    || key.equals("source")
+                    || key.equals("target")) {
+                switch (key) {
+                case "nativeheaderdir":
+                    key = "h"; break;
+                case "release":
+                    key = "-" + key; // to get "--" when passed to javac
                 }
-                jointOptions.add("-Fg" + level);
-            } else if (key.contains("debugLevel")) {
-                // ignore, taken care of in debug
-            } else if ((key.contains("nowarn"))
-                    || (key.contains("verbose"))
-                    || (key.contains("deprecation"))) {
-                // false is default, so something to do only in true case
-                if ("on".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value) || "yes".equalsIgnoreCase(value))
-                    jointOptions.add("-F" + key);
+                // map "depend", "encoding", etc. to "-Jkey=val"
+                jointOptions.add("-J" + key + "=" + getProject().replaceProperties(e.getValue().toString()));
+
             } else if (key.contains("classpath")) {
-                classpath.add(javac.getClasspath());
-            } else if ((key.contains("depend"))
-                    || (key.contains("extdirs"))
-                    || (key.contains("encoding"))
-                    || (key.contains("source"))
-                    || (key.contains("target"))
-                    || (key.contains("verbose"))) { // already handling verbose but pass on too
-                jointOptions.add("-J" + key + "=" + value);
-            } else {
-                log.warn("The option " + key + " cannot be set on the contained <javac> element. The option will be ignored");
+                if (key.startsWith("boot")) {
+                    // map "bootclasspath" or "bootclasspathref" to "-Jbootclasspath="
+                    jointOptions.add("-Jbootclasspath=" + javac.getBootclasspath());
+                } else {
+                    // map "classpath" or "classpathref" to "--classpath"
+                    classpath.add(javac.getClasspath());
+                }
+            } else if (key.contains("module") && key.contains("path")) {
+                if (key.startsWith("upgrade")) {
+                    // map "upgrademodulepath" or "upgrademodulepathref" to "-J-upgrade-module-path="
+                    jointOptions.add("-J-upgrade-module-path=" + javac.getUpgrademodulepath());
+                } else if (key.contains("source")) {
+                    // map "modulesourcepath" or "modulesourcepathref" to "-J-module-source-path="
+                    jointOptions.add("-J-module-source-path=" + javac.getModulesourcepath());
+                } else {
+                    // map "modulepath" or "modulepathref" to "-J-module-path="
+                    jointOptions.add("-J-module-path=" + javac.getModulepath());
+                }
+            } else if (!key.contains("debug") && !key.equals("deprecation") && !key.equals("nowarn") && !key.equals("verbose")) {
+                log.warn("The option " + key + " cannot be set on the contained <javac> element. The option will be ignored.");
             }
-            // TODO includes? excludes?
+            // TODO: defaultexcludes, excludes(file)?, includes(file)?, includeDestClasses, tempdir
         }
 
-        // ant's <javac> supports nested <compilerarg value=""> elements (there can be multiple of them)
-        // for additional options to be passed to javac.
-        Enumeration children = rc.getChildren();
-        while (children.hasMoreElements()) {
-            RuntimeConfigurable childrc = (RuntimeConfigurable) children.nextElement();
+        // Ant's <javac> supports nested <compilerarg value=""> elements (there
+        // can be multiple of them) for additional options to be passed to javac.
+        for (RuntimeConfigurable childrc : Collections.list(rc.getChildren())) {
             if (childrc.getElementTag().equals("compilerarg")) {
-                for (Object o : childrc.getAttributeMap().entrySet()) {
-                    final Map.Entry e = (Map.Entry) o;
-                    final String key = e.getKey().toString();
+                for (Map.Entry<String, Object> e : childrc.getAttributeMap().entrySet()) {
+                    String key = e.getKey();
                     if (key.equals("value")) {
-                        final String value = getProject().replaceProperties(e.getValue().toString());
+                        String value = getProject().replaceProperties(e.getValue().toString());
                         StringTokenizer st = new StringTokenizer(value, " ");
                         while (st.hasMoreTokens()) {
-                            String optionStr = st.nextToken();
-                            String replaced = optionStr.replace("-X", "-FX");
-                            if (optionStr.equals(replaced)) {
-                                replaced = optionStr.replace("-W", "-FW"); // GROOVY-5063
-                            }
-                            jointOptions.add(replaced);
+                            String option = st.nextToken();
+                            // GROOVY-5063: map "-Werror", etc. to "-FWerror"
+                            jointOptions.add(option.replaceFirst("^-(W|X|proc:)", "-F$1"));
                         }
                     }
                 }
@@ -1028,16 +1083,7 @@ public class Groovyc extends MatchingTask {
     }
 
     private void doForkCommandLineList(List<String> commandLineList, Path classpath, String separator) {
-        if (!fork) return;
-
-        if (includeAntRuntime) {
-            classpath.addExisting((new Path(getProject())).concatSystemClasspath("last"));
-        }
-        if (includeJavaRuntime) {
-            classpath.addJavaRuntime();
-        }
-
-        if (forkedExecutable != null && !forkedExecutable.equals("")) {
+        if (forkedExecutable != null && !forkedExecutable.isEmpty()) {
             commandLineList.add(forkedExecutable);
         } else {
             String javaHome;
@@ -1048,39 +1094,64 @@ public class Groovyc extends MatchingTask {
             }
             commandLineList.add(javaHome + separator + "bin" + separator + "java");
         }
-        commandLineList.add("-classpath");
-        commandLineList.add(getClasspathRelative(classpath));
 
-        final String fileEncodingProp = System.getProperty("file.encoding");
-        if ((fileEncodingProp != null) && !fileEncodingProp.equals("")) {
-            commandLineList.add("-Dfile.encoding=" + fileEncodingProp);
+        String[] bootstrapClasspath;
+        ClassLoader loader = getClass().getClassLoader();
+        if (loader instanceof AntClassLoader) {
+            bootstrapClasspath = ((AntClassLoader) loader).getClasspath().split(File.pathSeparator);
+        } else {
+            Class<?>[] bootstrapClasses = {
+                FileSystemCompilerFacade.class,
+                FileSystemCompiler.class,
+                antlr.Parser.class,
+                ClassVisitor.class,
+                CommandLine.class,
+            };
+            Set<String> locations = new LinkedHashSet<>();
+            for (Class<?> clazz : bootstrapClasses) {
+                locations.add(new File(getLocation(clazz)).getAbsolutePath());
+            }
+            bootstrapClasspath = locations.toArray(new String[locations.size()]);
         }
-        if (targetBytecode != null) {
-            commandLineList.add("-Dgroovy.target.bytecode=" + targetBytecode);
+        if (bootstrapClasspath.length > 0) {
+            commandLineList.add("-classpath");
+            commandLineList.add(getClasspathRelative(bootstrapClasspath));
         }
 
-        if ((memoryInitialSize != null) && !memoryInitialSize.equals("")) {
+        if (memoryInitialSize != null && !memoryInitialSize.isEmpty()) {
             commandLineList.add("-Xms" + memoryInitialSize);
         }
-        if ((memoryMaximumSize != null) && !memoryMaximumSize.equals("")) {
+        if (memoryMaximumSize != null && !memoryMaximumSize.isEmpty()) {
             commandLineList.add("-Xmx" + memoryMaximumSize);
         }
+        if (targetBytecode != null) {
+            commandLineList.add("-Dgroovy.target.bytecode=" + targetBytecode);
+        }
         if (!"*.groovy".equals(getScriptExtension())) {
             String tmpExtension = getScriptExtension();
             if (tmpExtension.startsWith("*."))
                 tmpExtension = tmpExtension.substring(1);
             commandLineList.add("-Dgroovy.default.scriptExtension=" + tmpExtension);
         }
+
         commandLineList.add(FileSystemCompilerFacade.class.getName());
+        commandLineList.add("--classpath");
+        if (includeAntRuntime) {
+            classpath.addExisting(new Path(getProject()).concatSystemClasspath("last"));
+        }
+        if (includeJavaRuntime) {
+            classpath.addJavaRuntime();
+        }
+        commandLineList.add(getClasspathRelative(classpath.list()));
         if (forceLookupUnnamedFiles) {
             commandLineList.add("--forceLookupUnnamedFiles");
         }
     }
 
-    private String getClasspathRelative(Path classpath) {
+    private String getClasspathRelative(String[] classpath) {
         String baseDir = getProject().getBaseDir().getAbsolutePath();
         StringBuilder sb = new StringBuilder();
-        for (String next : classpath.list()) {
+        for (String next : classpath) {
             if (sb.length() > 0) {
                 sb.append(File.pathSeparatorChar);
             }
@@ -1093,6 +1164,14 @@ public class Groovyc extends MatchingTask {
         return sb.toString();
     }
 
+    private static URI getLocation(Class<?> clazz) {
+        try {
+            return clazz.getProtectionDomain().getCodeSource().getLocation().toURI();
+        } catch (URISyntaxException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
     /**
      * Add "groovyc" parameters to the commandLineList, based on the ant configuration.
      *
@@ -1174,12 +1253,12 @@ public class Groovyc extends MatchingTask {
     }
 
     private String[] makeCommandLine(List<String> commandLineList) {
-        log.verbose("Compilation arguments:\n" + DefaultGroovyMethods.join((Iterable)commandLineList, "\n"));
+        log.verbose("Compilation arguments:\n" + DefaultGroovyMethods.join((Iterable<String>) commandLineList, "\n"));
         return commandLineList.toArray(EMPTY_STRING_ARRAY);
     }
 
     private void runForked(String[] commandLine) {
-        final Execute executor = new Execute();
+        Execute executor = new Execute();
         executor.setAntRun(getProject());
         executor.setWorkingDirectory(getProject().getBaseDir());
         executor.setCommandline(commandLine);
@@ -1188,7 +1267,7 @@ public class Groovyc extends MatchingTask {
         } catch (final IOException ioe) {
             throw new BuildException("Error running forked groovyc.", ioe);
         }
-        final int returnCode = executor.getExitValue();
+        int returnCode = executor.getExitValue();
         if (returnCode != 0) {
             taskSuccess = false;
             if (errorProperty != null) {
@@ -1214,28 +1293,23 @@ public class Groovyc extends MatchingTask {
             if (tmpExtension.startsWith("*."))
                 tmpExtension = tmpExtension.substring(1);
             configuration.setDefaultScriptExtension(tmpExtension);
-
-            // Load the file name list
-            String[] filenames = options.generateFileNames();
-            boolean fileNameErrors = filenames == null;
-
-            fileNameErrors = fileNameErrors || !FileSystemCompiler.validateFiles(filenames);
-
             if (targetBytecode != null) {
                 configuration.setTargetBytecode(targetBytecode);
             }
 
+            // Load the file name list
+            String[] fileNames = options.generateFileNames();
+            boolean fileNameErrors = (fileNames == null || !FileSystemCompiler.validateFiles(fileNames));
             if (!fileNameErrors) {
                 try (GroovyClassLoader loader = buildClassLoaderFor()) {
-                    FileSystemCompiler.doCompilation(configuration, makeCompileUnit(loader), filenames, forceLookupUnnamedFiles);
+                    FileSystemCompiler.doCompilation(configuration, makeCompileUnit(loader), fileNames, forceLookupUnnamedFiles);
                 }
             }
-
-        } catch (Exception re) {
-            Throwable t = re;
-            if ((re.getClass() == RuntimeException.class) && (re.getCause() != null)) {
+        } catch (Exception e) {
+            Throwable t = e;
+            if (e.getClass() == RuntimeException.class && e.getCause() != null) {
                 // unwrap to the real exception
-                t = re.getCause();
+                t = e.getCause();
             }
             Writer writer = new StringBuilderWriter();
             new ErrorReporter(t, false).write(new PrintWriter(writer));
@@ -1264,13 +1338,14 @@ public class Groovyc extends MatchingTask {
                     + (destDir != null ? " to " + destDir : ""));
 
             listFiles();
-            Path classpath = getClasspath() != null ? getClasspath() : new Path(getProject());
-            List<String> jointOptions = extractJointOptions(classpath);
 
-            String separator = System.getProperty("file.separator");
-            List<String> commandLineList = new ArrayList<String>();
+            Path classpath = getClasspath();
+            if (classpath == null)
+                classpath = new Path(getProject());
+            List<String> jointOptions = extractJointOptions(classpath);
+            List<String> commandLineList = new ArrayList<>();
 
-            doForkCommandLineList(commandLineList, classpath, separator);
+            if (fork) doForkCommandLineList(commandLineList, classpath, File.separator);
             doNormalCommandLineList(commandLineList, jointOptions, classpath);
             addSourceFiles(commandLineList);
 
@@ -1324,22 +1399,17 @@ public class Groovyc extends MatchingTask {
     }
 
     protected GroovyClassLoader buildClassLoaderFor() {
+        if (fork) {
+            throw new GroovyBugError("Cannot use Groovyc#buildClassLoaderFor() for forked compilation");
+        }
         // GROOVY-5044
-        if (!fork && !getIncludeantruntime()) {
+        if (!getIncludeantruntime()) {
             throw new IllegalArgumentException("The includeAntRuntime=false option is not compatible with fork=false");
         }
-        final ClassLoader parent =
-                AccessController.doPrivileged(
-                        new PrivilegedAction<ClassLoader>() {
-                            @Override
-                            public ClassLoader run() {
-                                return getIncludeantruntime()
-                                        ? getClass().getClassLoader()
-                                        : new AntClassLoader(new RootLoader(EMPTY_URL_ARRAY, null), getProject(), getClasspath());
-                            }
-                        });
-        if (parent instanceof AntClassLoader) {
-            AntClassLoader antLoader = (AntClassLoader) parent;
+
+        final ClassLoader loader = getClass().getClassLoader();
+        if (loader instanceof AntClassLoader) {
+            AntClassLoader antLoader = (AntClassLoader) loader;
             String[] pathElm = antLoader.getClasspath().split(File.pathSeparator);
             List<String> classpath = configuration.getClasspath();
             /*
@@ -1370,23 +1440,22 @@ public class Groovyc extends MatchingTask {
             }
         }
 
-        GroovyClassLoader loader =
-                AccessController.doPrivileged(
-                        new PrivilegedAction<GroovyClassLoader>() {
-                            @Override
-                            public GroovyClassLoader run() {
-                                return new GroovyClassLoader(parent, configuration);
-                            }
-                        });
+        GroovyClassLoader groovyLoader = AccessController.doPrivileged(new PrivilegedAction<GroovyClassLoader>() {
+            @Override
+            public GroovyClassLoader run() {
+                return new GroovyClassLoader(loader, configuration);
+            }
+        });
         if (!forceLookupUnnamedFiles) {
             // in normal case we don't need to do script lookups
-            loader.setResourceLoader(new GroovyResourceLoader() {
-                public URL loadGroovySource(String filename) throws MalformedURLException {
+            groovyLoader.setResourceLoader(new GroovyResourceLoader() {
+                @Override
+                public URL loadGroovySource(String filename) {
                     return null;
                 }
             });
         }
-        return loader;
+        return groovyLoader;
     }
 
     private Set<String> getScriptExtensions() {
@@ -1395,14 +1464,14 @@ public class Groovyc extends MatchingTask {
 
     private void loadRegisteredScriptExtensions() {
         if (scriptExtensions.isEmpty()) {
-
             scriptExtensions.add(getScriptExtension().substring(2)); // first extension will be the one set explicitly on <groovyc>
 
-            Path classpath = getClasspath() != null ? getClasspath() : new Path(getProject());
-            final String[] pe = classpath.list();
+            Path classpath = getClasspath();
+            if (classpath == null)
+                classpath = new Path(getProject());
             try (GroovyClassLoader loader = new GroovyClassLoader(getClass().getClassLoader())) {
-                for (String file : pe) {
-                    loader.addClasspath(file);
+                for (String element : classpath.list()) {
+                    loader.addClasspath(element);
                 }
                 scriptExtensions.addAll(SourceExtensionHandler.getRegisteredExtensions(loader));
             } catch (IOException e) {