You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2019/11/15 11:00:16 UTC
[groovy] branch master updated: GROOVY-8775,
GROOVY-9197: Ant: separate JVM and compilation classpaths
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/master by this push:
new c6e50ba GROOVY-8775, GROOVY-9197: Ant: separate JVM and compilation classpaths
c6e50ba is described below
commit c6e50bab27dc705116b93daccd62d53160c99938
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Nov 11 15:02:53 2019 -0600
GROOVY-8775, GROOVY-9197: Ant: separate JVM and compilation classpaths
---
src/test/groovy/bugs/Groovy9197.groovy | 61 +++++++
.../main/java/org/codehaus/groovy/ant/Groovyc.java | 190 ++++++++++++---------
.../org/codehaus/groovy/ant/GroovycTest.xml | 20 +++
.../groovy/ant/MakesExternalReference.java | 39 +++++
.../org/codehaus/groovy/ant/commons-lang3-3.4.jar | Bin 0 -> 434678 bytes
.../org/codehaus/groovy/ant/GroovycTest.java | 7 +
6 files changed, 236 insertions(+), 81 deletions(-)
diff --git a/src/test/groovy/bugs/Groovy9197.groovy b/src/test/groovy/bugs/Groovy9197.groovy
new file mode 100644
index 0000000..f752f35
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy9197.groovy
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package groovy.bugs
+
+import org.codehaus.groovy.control.CompilerConfiguration
+import org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit
+import org.junit.Test
+
+import static groovy.grape.Grape.resolve
+
+final class Groovy9197 {
+
+ @Test
+ void testJointCompilationClasspathPropagation() {
+ def uris = resolve(autoDownload:true, classLoader:new GroovyClassLoader(null),
+ [groupId:'org.apache.commons', artifactId:'commons-lang3', version:'3.9'])
+
+ def config = new CompilerConfiguration(
+ classpath: new File(uris[0]).path,
+ targetDirectory: File.createTempDir(),
+ jointCompilationOptions: [memStub: true]
+ )
+
+ def parentDir = File.createTempDir()
+ try {
+ def pojo = new File(parentDir, 'Pojo.java')
+ pojo.write '''
+ import static org.apache.commons.lang3.StringUtils.isEmpty;
+ public class Pojo {
+ public static void main(String[] args) {
+ assert !isEmpty(" ");
+ assert isEmpty("");
+ }
+ }
+ '''
+
+ def unit = new JavaAwareCompilationUnit(config)
+ unit.addSources(pojo)
+ unit.compile()
+ } finally {
+ parentDir.deleteDir()
+ config.targetDirectory.deleteDir()
+ }
+ }
+}
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 a72af08..ccc6efe 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
@@ -19,6 +19,7 @@
package org.codehaus.groovy.ant;
import groovy.lang.GroovyClassLoader;
+import org.antlr.v4.runtime.tree.ParseTreeVisitor;
import org.apache.groovy.io.StringBuilderWriter;
import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.BuildException;
@@ -31,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;
@@ -38,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;
@@ -47,11 +49,13 @@ import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
-import java.net.URL;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
@@ -67,17 +71,22 @@ import java.util.StringTokenizer;
* <pre>
* <?xml version="1.0"?>
* <project name="MyGroovyBuild" default="compile">
- * <property name="groovy.home" value="/Path/To/Groovy"/>
+ * <property name="groovy.home" location="/Path/To/Groovy"/>
* <property name="groovy.version" value="X.Y.Z"/>
- * <path id="groovy.classpath">
- * <fileset dir="${groovy.home}/lib">
- * <include name="groovy-*${groovy.version}.jar" />
- * </fileset>
- * </path>
- * <taskdef name="groovyc" classname="org.codehaus.groovy.ant.Groovyc" classpathref="groovy.classpath"/>
+ *
+ * <taskdef name="groovyc" classname="org.codehaus.groovy.ant.Groovyc">
+ * <classpath>
+ * <fileset file="${groovy.home}/lib/groovy-${groovy.version}.jar"/>
+ * <fileset file="${groovy.home}/lib/groovy-ant-${groovy.version}.jar"/>
+ * </classpath>
+ * </taskdef>
*
* <target name="compile" description="compile groovy sources">
- * <groovyc srcdir="src" listfiles="true" classpathref="groovy.classpath"/>
+ * <groovyc srcdir="src" destdir="bin" fork="true" listfiles="true" includeantruntime="false"/>
+ * <classpath>
+ * <fileset dir="${groovy.home}/lib" includes="groovy-*${groovy.version}.jar" excludes="groovy-ant-${groovy.version}.jar"/>
+ * </classpath>
+ * </groovyc>
* </target>
* </project>
* </pre>
@@ -85,13 +94,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>
@@ -123,39 +132,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>
* <?xml version="1.0"?>
* <project name="MyJointBuild" default="compile">
- * <property name="groovy.home" value="/Path/To/Groovy"/>
+ * <property name="groovy.home" location="/Path/To/Groovy"/>
* <property name="groovy.version" value="X.Y.Z"/>
*
- * <path id="groovy.classpath">
+ * <path id="classpath.main">
* <fileset dir="${groovy.home}/lib">
- * <include name="groovy-*${groovy.version}.jar" />
+ * <include name="groovy-*${groovy.version}.jar"/>
+ * <exclude name="groovy-ant-${groovy.version}.jar"/>
* </fileset>
* </path>
*
- * <target name="clean" description="remove all built files">
- * <delete dir="classes" />
- * </target>
+ * <taskdef name="groovyc" classname="org.codehaus.groovy.ant.Groovyc">
+ * <classpath>
+ * <fileset file="${groovy.home}/lib/groovy-${groovy.version}.jar"/>
+ * <fileset file="${groovy.home}/lib/groovy-ant-${groovy.version}.jar"/>
+ * </classpath>
+ * </taskdef>
*
- * <target name="compile" depends="init" description="compile java and groovy sources">
- * <mkdir dir="classes" />
- * <groovyc destdir="classes" srcdir="src" listfiles="true" keepStubs="true" stubdir="stubs">
- * <javac debug="on" deprecation="true"/>
- * <classpath>
- * <fileset dir="classes"/>
- * <path refid="groovy.classpath"/>
- * </classpath>
- * </groovyc>
+ * <target name="clean">
+ * <delete dir="bin" failonerror="false"/>
* </target>
*
- * <target name="init">
- * <taskdef name="groovyc" classname="org.codehaus.groovy.ant.Groovyc" classpathref="groovy.classpath"/>
+ * <target name="compile" depends="clean" description="compile java and groovy sources">
+ * <mkdir dir="bin"/>
+ *
+ * <groovyc srcdir="src" destdir="bin" stubdir="stubs" keepStubs="true"
+ * fork="true" includeantruntime="false" classpathref="classpath.main">
+ * <javac debug="true" source="1.8" target="1.8"/>
+ * </groovyc>
* </target>
* </project>
* </pre>
@@ -165,7 +177,7 @@ import java.util.StringTokenizer;
* Can also be used from {@link groovy.ant.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];
@@ -176,20 +188,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;
@@ -214,12 +226,12 @@ public class Groovyc extends MatchingTask {
/**
* 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.
@@ -1071,13 +1083,6 @@ public class Groovyc extends MatchingTask {
}
private void doForkCommandLineList(List<String> commandLineList, Path classpath, String separator) {
- if (includeAntRuntime) {
- classpath.addExisting(new Path(getProject()).concatSystemClasspath("last"));
- }
- if (includeJavaRuntime) {
- classpath.addJavaRuntime();
- }
-
if (forkedExecutable != null && !forkedExecutable.isEmpty()) {
commandLineList.add(forkedExecutable);
} else {
@@ -1089,38 +1094,61 @@ public class Groovyc extends MatchingTask {
}
commandLineList.add(javaHome + separator + "bin" + separator + "java");
}
- commandLineList.add("-classpath");
- commandLineList.add(getClasspathRelative(classpath));
- String fileEncoding = System.getProperty("file.encoding");
- if (fileEncoding != null && !fileEncoding.isEmpty()) {
- commandLineList.add("-Dfile.encoding=" + fileEncoding);
+ String[] bootstrapClasspath;
+ ClassLoader loader = getClass().getClassLoader();
+ if (loader instanceof AntClassLoader) {
+ bootstrapClasspath = ((AntClassLoader) loader).getClasspath().split(File.pathSeparator);
+ } else {
+ Class<?>[] bootstrapClasses = {
+ FileSystemCompilerFacade.class,
+ FileSystemCompiler.class,
+ ParseTreeVisitor.class,
+ ClassVisitor.class,
+ CommandLine.class,
+ };
+ bootstrapClasspath = Arrays.stream(bootstrapClasses).map(Groovyc::getLocation)
+ .map(uri -> new File(uri).getAbsolutePath()).distinct().toArray(String[]::new);
}
- if (targetBytecode != null) {
- commandLineList.add("-Dgroovy.target.bytecode=" + targetBytecode);
+ if (bootstrapClasspath.length > 0) {
+ commandLineList.add("-classpath");
+ commandLineList.add(getClasspathRelative(bootstrapClasspath));
}
+
if (memoryInitialSize != null && !memoryInitialSize.isEmpty()) {
commandLineList.add("-Xms" + memoryInitialSize);
}
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);
}
@@ -1133,6 +1161,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.
*
@@ -1214,7 +1250,7 @@ public class Groovyc extends MatchingTask {
}
private String[] makeCommandLine(List<String> commandLineList) {
- log.verbose("Compilation arguments:\n" + DefaultGroovyMethods.join((Iterable<String>) commandLineList, "\n"));
+ log.info("Compilation arguments:\n" + DefaultGroovyMethods.join((Iterable<String>) commandLineList, "\n"));
return commandLineList.toArray(EMPTY_STRING_ARRAY);
}
@@ -1302,10 +1338,9 @@ public class Groovyc extends MatchingTask {
Path classpath = Optional.ofNullable(getClasspath()).orElse(new Path(getProject()));
List<String> jointOptions = extractJointOptions(classpath);
- String separator = System.getProperty("file.separator");
List<String> commandLineList = new ArrayList<>();
- if (fork) doForkCommandLineList(commandLineList, classpath, separator);
+ if (fork) doForkCommandLineList(commandLineList, classpath, File.separator);
doNormalCommandLineList(commandLineList, jointOptions, classpath);
addSourceFiles(commandLineList);
@@ -1359,23 +1394,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");
}
- 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;
+ ClassLoader loader = getClass().getClassLoader();
+ if (loader instanceof AntClassLoader) {
+ AntClassLoader antLoader = (AntClassLoader) loader;
String[] pathElm = antLoader.getClasspath().split(File.pathSeparator);
List<String> classpath = configuration.getClasspath();
/*
@@ -1406,13 +1435,13 @@ public class Groovyc extends MatchingTask {
}
}
- GroovyClassLoader loader = AccessController.doPrivileged(
- (PrivilegedAction<GroovyClassLoader>) () -> new GroovyClassLoader(parent, configuration));
+ GroovyClassLoader groovyLoader = AccessController.doPrivileged(
+ (PrivilegedAction<GroovyClassLoader>) () -> new GroovyClassLoader(loader, configuration));
if (!forceLookupUnnamedFiles) {
// in normal case we don't need to do script lookups
- loader.setResourceLoader(filename -> null);
+ groovyLoader.setResourceLoader(filename -> null);
}
- return loader;
+ return groovyLoader;
}
private Set<String> getScriptExtensions() {
@@ -1423,11 +1452,10 @@ public class Groovyc extends MatchingTask {
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 = Optional.ofNullable(getClasspath()).orElse(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) {
diff --git a/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/GroovycTest.xml b/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/GroovycTest.xml
index d4fb8d2..73bb824 100644
--- a/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/GroovycTest.xml
+++ b/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/GroovycTest.xml
@@ -187,6 +187,26 @@
<groovyc srcdir="${srcPath}" destdir="${destPath}" includes="GroovycTest1.groovy" fork="false" includeAntRuntime="false"/>
</target>
+ <!-- GROOVY-9197 -->
+ <target name="jointForkedCompilation_ExternalJarOnClasspath">
+ <presetdef name="compile">
+ <groovyc fork="true" includeantruntime="false">
+ <javac debug="true" source="${javaVersion}" target="${javaVersion}"/>
+ </groovyc>
+ </presetdef>
+
+ <path id="the.classpath">
+ <path refid="groovyMaterials"/>
+ <fileset file="commons-lang3-3.4.jar"/>
+ </path>
+
+ <compile srcdir="${srcPath}" destdir="${destPath}" includes="MakesExternalReference.java">
+ <classpath refid="the.classpath"/>
+ </compile>
+
+ <java classname="org.codehaus.groovy.ant.MakesExternalReference" classpathref="the.classpath"/>
+ </target>
+
<target name="clean">
<delete quiet="true">
<fileset dir="${destPath}/org/codehaus/groovy/ant">
diff --git a/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/MakesExternalReference.java b/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/MakesExternalReference.java
new file mode 100644
index 0000000..e5d2c73
--- /dev/null
+++ b/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/MakesExternalReference.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.codehaus.groovy.ant;
+
+import java.io.*;
+
+import static org.apache.commons.lang3.StringUtils.isEmpty;
+
+public class MakesExternalReference {
+ public static void main(String[] args) throws IOException {
+ FileOutputStream fout = new FileOutputStream(
+ new File("target/classes/groovy/test/org/codehaus/groovy/ant/MakesExternalReference_Result.txt"));
+ try {
+ assert !isEmpty(" ");
+ fout.write("OK.".getBytes());
+ } finally {
+ try {
+ fout.close();
+ } catch (IOException ignore) {
+ }
+ }
+ }
+}
diff --git a/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/commons-lang3-3.4.jar b/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/commons-lang3-3.4.jar
new file mode 100644
index 0000000..8ec91d4
Binary files /dev/null and b/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/commons-lang3-3.4.jar differ
diff --git a/subprojects/groovy-ant/src/test/groovy/org/codehaus/groovy/ant/GroovycTest.java b/subprojects/groovy-ant/src/test/groovy/org/codehaus/groovy/ant/GroovycTest.java
index cb60c5d..cec5dd6 100644
--- a/subprojects/groovy-ant/src/test/groovy/org/codehaus/groovy/ant/GroovycTest.java
+++ b/subprojects/groovy-ant/src/test/groovy/org/codehaus/groovy/ant/GroovycTest.java
@@ -252,6 +252,13 @@ public class GroovycTest extends GroovyTestCase {
ensureFails("noForkNoAntRuntime");
}
+ // GROOVY-9197
+ public void testJointCompilationPropagatesClasspath() {
+ ensureNotPresent("MakesExternalReference");
+ project.executeTarget("jointForkedCompilation_ExternalJarOnClasspath");
+ ensureResultOK("MakesExternalReference");
+ }
+
private void ensureExecutes(String target) {
ensureNotPresent("GroovycTest1");
project.executeTarget(target);