You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@ant.apache.org by bo...@apache.org on 2016/03/21 12:21:14 UTC
[3/5] ant git commit: Added modulepath,
modulesourcepath and upgrademodulepath into Javac task.
Added modulepath, modulesourcepath and upgrademodulepath into Javac task.
Project: http://git-wip-us.apache.org/repos/asf/ant/repo
Commit: http://git-wip-us.apache.org/repos/asf/ant/commit/83eaf480
Tree: http://git-wip-us.apache.org/repos/asf/ant/tree/83eaf480
Diff: http://git-wip-us.apache.org/repos/asf/ant/diff/83eaf480
Branch: refs/heads/master
Commit: 83eaf4804522c3aaac033f224ec2c5b9f6a25e30
Parents: 038e194
Author: Tomas Zezula <to...@gmail.com>
Authored: Fri Mar 11 14:00:22 2016 +0100
Committer: Stefan Bodewig <bo...@apache.org>
Committed: Mon Mar 21 12:02:59 2016 +0100
----------------------------------------------------------------------
manual/Tasks/javac.html | 88 +++-
.../org/apache/tools/ant/taskdefs/Javac.java | 432 ++++++++++++++++++-
.../compilers/DefaultCompilerAdapter.java | 64 +++
.../apache/tools/ant/taskdefs/JavacTest.java | 85 ++++
.../compilers/DefaultCompilerAdapterTest.java | 163 +++++++
5 files changed, 809 insertions(+), 23 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ant/blob/83eaf480/manual/Tasks/javac.html
----------------------------------------------------------------------
diff --git a/manual/Tasks/javac.html b/manual/Tasks/javac.html
index ce54246..cfddb58 100644
--- a/manual/Tasks/javac.html
+++ b/manual/Tasks/javac.html
@@ -135,7 +135,7 @@ invoking the compiler.</p>
<td valign="top">srcdir</td>
<td valign="top">Location of the java files. (See the
<a href="#srcdirnote">note</a> below.)</td>
- <td align="center" valign="top">Yes, unless nested <code><src></code> elements are present.</td>
+ <td align="center" valign="top">Yes, unless nested <code><src></code> elements or <code>modulesourcepath</code> attribute or elements are present.</td>
</tr>
<tr>
<td valign="top">destdir</td>
@@ -459,6 +459,51 @@ invoking the compiler.</p>
</td>
<td align="center" valign="top">No - default is "true"</td>
</tr>
+ <tr>
+ <td valign="top">modulepath</td>
+ <td valign="top">
+ Specify where to find application modules. A list of directories of modules, module files or exploded modules.
+ <em>since Ant 1.9.7</em>
+ </td>
+ <td align="center" valign="top">No</td>
+ </tr>
+ <tr>
+ <td valign="top">modulepathref</td>
+ <td valign="top">
+ The modulepath to use, given as <a href="../using.html#references">reference</a> to a PATH defined elsewhere.
+ <em>since Ant 1.9.7</em></td>
+ <td align="center" valign="top">No</td>
+ </tr>
+ <tr>
+ <td valign="top">modulesourcepath</td>
+ <td valign="top">
+ Specify where to find input source files for multiple module compilation.
+ <em>since Ant 1.9.7</em>
+ </td>
+ <td align="center" valign="top">Yes, unless <code>srcdir</code> attribute or nested <code><src></code> elements are present</td>
+ </tr>
+ <tr>
+ <td valign="top">modulesourcepathref</td>
+ <td valign="top">
+ The modulesourcepath to use, given as <a href="../using.html#references">reference</a> to a PATH defined elsewhere.
+ <em>since Ant 1.9.7</em></td>
+ <td align="center" valign="top">No</td>
+ </tr>
+ <tr>
+ <td valign="top">upgrademodulepath</td>
+ <td valign="top">
+ Specify the location of modules that replace upgradeable modules in the runtime image.
+ <em>since Ant 1.9.7</em>
+ </td>
+ <td align="center" valign="top">No</td>
+ </tr>
+ <tr>
+ <td valign="top">upgrademodulepathref</td>
+ <td valign="top">
+ The upgrademodulepath to use, given as <a href="../using.html#references">reference</a> to a PATH defined elsewhere.
+ <em>since Ant 1.9.7</em></td>
+ <td align="center" valign="top">No</td>
+ </tr>
</table>
<h3>Parameters specified as nested elements</h3>
@@ -468,17 +513,23 @@ supports most attributes of <code><fileset></code>
<code><include></code>, <code><exclude></code> and
<code><patternset></code> elements.</p>
<h4><code>srcdir</code>, <code>classpath</code>, <code>sourcepath</code>,
-<code>bootclasspath</code> and <code>extdirs</code></h4>
+<code>bootclasspath</code>, <code>modulepath</code>, <code>modulesourcepath</code>,
+<code>upgrademodulepath</code> and <code>extdirs</code></h4>
<p><code><javac></code>'s <code>srcdir</code>, <code>classpath</code>,
-<code>sourcepath</code>, <code>bootclasspath</code>, and
-<code>extdirs</code> attributes are
+<code>sourcepath</code>, <code>bootclasspath</code>,
+<code>extdirs</code>, <code>modulepath</code>, <code>modulesourcepath</code>,
+and <code>upgrademodulepath</code> attributes are
<a href="../using.html#path">path-like structures</a>
and can also be set via nested
<code><src></code> (note the different name!),
<code><classpath></code>,
<code><sourcepath></code>,
-<code><bootclasspath></code> and
-<code><extdirs></code> elements, respectively.</p>
+<code><bootclasspath></code>,
+<code><extdirs></code>,
+<code><modulepath></code>,
+<code><modulesourcepath></code> and
+<code><upgrademodulepath></code>
+elements, respectively.</p>
<h4>compilerarg</h4>
@@ -710,6 +761,31 @@ the <tt><compilerarg></tt> element:
<p>in which case your compiler adapter can support attributes and
nested elements of its own.</p>
+<pre> <javac srcdir="${src}"
+ destdir="${build}"
+ includeantruntime="false"
+ modulepath="modules"
+ source="9"
+ /></pre>
+<p>compiles all <code>.java</code> files in a single module under the <code>${src}</code> directory,
+ and stores the <code>.class</code> files in the <code>${build}</code> directory. The compilation uses
+ application modules located in <code>modules</code> folder.The source level is <code>9</code> to enable modules.</p>
+
+<pre> <javac modulesourcepath="${src}/*/{gen,lin{32,64}}/classes"
+ destdir="${build}"
+ includeantruntime="false"
+ modulepath="modules"
+ source="9"
+ /></pre>
+<p>compiles all <code>.java</code> files in <code>gen/classes</code>, <code>lin32/classes</code> and
+ <code>lin64/classes</code> in all source modules under the <code>${src}</code> directory.
+ Generates module directories in the <code>${build}</code> directory. Each generated module directory under
+ the <code>${build}</code> directory contains <code>.class</code> files from corresponding source module.
+ The <code>*</code> is a token representing the name of any of the modules in the compilation module set.
+ The <code>{ ... , ... }</code> express alternates for expansion.
+ The compilation uses application modules located in <code>modules</code> folder.The source level is
+ <code>9</code> to enable modules.</p>
+
<h3>Jikes Notes</h3>
<p>You need Jikes 1.15 or later.</p>
http://git-wip-us.apache.org/repos/asf/ant/blob/83eaf480/src/main/org/apache/tools/ant/taskdefs/Javac.java
----------------------------------------------------------------------
diff --git a/src/main/org/apache/tools/ant/taskdefs/Javac.java b/src/main/org/apache/tools/ant/taskdefs/Javac.java
index 3d77f7c..e5c96d6 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Javac.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Javac.java
@@ -19,12 +19,17 @@
package org.apache.tools.ant.taskdefs;
import java.io.File;
+import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.TreeMap;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
@@ -93,12 +98,20 @@ public class Javac extends MatchingTask {
private static final String CLASSIC = "classic";
private static final String EXTJAVAC = "extJavac";
+ private static final char GROUP_START_MARK = '{'; //modulesourcepath group start character
+ private static final char GROUP_END_MARK = '}'; //modulesourcepath group end character
+ private static final char GROUP_SEP_MARK = ','; //modulesourcepath group element separator character
+ private static final String MODULE_MARKER = "*"; //modulesourcepath module name marker
+
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
private Path src;
private File destDir;
private Path compileClasspath;
+ private Path modulepath;
+ private Path upgrademodulepath;
private Path compileSourcepath;
+ private Path moduleSourcepath;
private String encoding;
private boolean debug = false;
private boolean optimize = false;
@@ -311,6 +324,49 @@ public class Javac extends MatchingTask {
}
/**
+ * Set the modulesourcepath to be used for this compilation.
+ * @param msp the modulesourcepath
+ * @since 1.9.7
+ */
+ public void setModulesourcepath(final Path msp) {
+ if (moduleSourcepath == null) {
+ moduleSourcepath = msp;
+ } else {
+ moduleSourcepath.append(msp);
+ }
+ }
+
+ /**
+ * Gets the modulesourcepath to be used for this compilation.
+ * @return the modulesourcepath
+ * @since 1.9.7
+ */
+ public Path getModulesourcepath() {
+ return moduleSourcepath;
+ }
+
+ /**
+ * Adds a path to modulesourcepath.
+ * @return a modulesourcepath to be configured
+ * @since 1.9.7
+ */
+ public Path createModulesourcepath() {
+ if (moduleSourcepath == null) {
+ moduleSourcepath = new Path(getProject());
+ }
+ return moduleSourcepath.createPath();
+ }
+
+ /**
+ * Adds a reference to a modulesourcepath defined elsewhere.
+ * @param r a reference to a modulesourcepath
+ * @since 1.9.7
+ */
+ public void setModulesourcepathRef(final Reference r) {
+ createModulesourcepath().setRefid(r);
+ }
+
+ /**
* Set the classpath to be used for this compilation.
*
* @param classpath an Ant Path object containing the compilation classpath.
@@ -351,6 +407,92 @@ public class Javac extends MatchingTask {
}
/**
+ * Set the modulepath to be used for this compilation.
+ * @param mp an Ant Path object containing the modulepath.
+ * @since 1.9.7
+ */
+ public void setModulepath(final Path mp) {
+ if (modulepath == null) {
+ modulepath = mp;
+ } else {
+ modulepath.append(mp);
+ }
+ }
+
+ /**
+ * Gets the modulepath to be used for this compilation.
+ * @return the modulepath
+ * @since 1.9.7
+ */
+ public Path getModulepath() {
+ return modulepath;
+ }
+
+ /**
+ * Adds a path to the modulepath.
+ * @return a modulepath to be configured
+ * @since 1.9.7
+ */
+ public Path createModulepath() {
+ if (modulepath == null) {
+ modulepath = new Path(getProject());
+ }
+ return modulepath.createPath();
+ }
+
+ /**
+ * Adds a reference to a modulepath defined elsewhere.
+ * @param r a reference to a modulepath
+ * @since 1.9.7
+ */
+ public void setModulepathRef(final Reference r) {
+ createModulepath().setRefid(r);
+ }
+
+ /**
+ * Set the upgrademodulepath to be used for this compilation.
+ * @param ump an Ant Path object containing the upgrademodulepath.
+ * @since 1.9.7
+ */
+ public void setUpgrademodulepath(final Path ump) {
+ if (upgrademodulepath == null) {
+ upgrademodulepath = ump;
+ } else {
+ upgrademodulepath.append(ump);
+ }
+ }
+
+ /**
+ * Gets the upgrademodulepath to be used for this compilation.
+ * @return the upgrademodulepath
+ * @since 1.9.7
+ */
+ public Path getUpgrademodulepath() {
+ return upgrademodulepath;
+ }
+
+ /**
+ * Adds a path to the upgrademodulepath.
+ * @return an upgrademodulepath to be configured
+ * @since 1.9.7
+ */
+ public Path createUpgrademodulepath() {
+ if (upgrademodulepath == null) {
+ upgrademodulepath = new Path(getProject());
+ }
+ return upgrademodulepath.createPath();
+ }
+
+ /**
+ * Adds a reference to the upgrademodulepath defined elsewhere.
+ * @param r a reference to an upgrademodulepath
+ * @since 1.9.7
+ */
+ public void setUpgrademodulepathRef(final Reference r) {
+ createUpgrademodulepath().setRefid(r);
+ }
+
+ /**
* Sets the bootclasspath that will be used to compile the classes
* against.
* @param bootclasspath a path to use as a boot class path (may be more
@@ -918,19 +1060,45 @@ public class Javac extends MatchingTask {
// scan source directories and dest directory to build up
// compile lists
- final String[] list = src.list();
- for (int i = 0; i < list.length; i++) {
- final File srcDir = getProject().resolveFile(list[i]);
- if (!srcDir.exists()) {
- throw new BuildException("srcdir \""
- + srcDir.getPath()
- + "\" does not exist!", getLocation());
- }
+ // Both src and modulesourcepath can be passed to javac, in this case
+ // the src becomes a part of the unnamed module.
+ if (hasPath(src)) {
+ final String[] list = src.list();
+ for (int i = 0; i < list.length; i++) {
+ final File srcDir = getProject().resolveFile(list[i]);
+ if (!srcDir.exists()) {
+ throw new BuildException("srcdir \""
+ + srcDir.getPath()
+ + "\" does not exist!", getLocation());
+ }
- final DirectoryScanner ds = this.getDirectoryScanner(srcDir);
- final String[] files = ds.getIncludedFiles();
+ final DirectoryScanner ds = this.getDirectoryScanner(srcDir);
+ final String[] files = ds.getIncludedFiles();
- scanDir(srcDir, destDir != null ? destDir : srcDir, files);
+ scanDir(srcDir, destDir != null ? destDir : srcDir, files);
+ }
+ } else {
+ assert hasPath(moduleSourcepath) : "Either srcDir or moduleSourcepath must be given";
+ final FileUtils fu = FileUtils.getFileUtils();
+ for (String pathElement : moduleSourcepath.list()) {
+ boolean valid = false;
+ for (Map.Entry<String,Collection<File>> modules : resolveModuleSourcePathElement(getProject().getBaseDir(), pathElement).entrySet()) {
+ final String moduleName = modules.getKey();
+ for (File srcDir : modules.getValue()) {
+ if (srcDir.exists()) {
+ valid = true;
+ final DirectoryScanner ds = getDirectoryScanner(srcDir);
+ final String[] files = ds.getIncludedFiles();
+ scanDir(srcDir, fu.resolveFile(destDir, moduleName), files);
+ }
+ }
+ }
+ if (!valid) {
+ throw new BuildException("modulesourcepath \""
+ + pathElement
+ + "\" does not exist!", getLocation());
+ }
+ }
}
compile();
@@ -1106,13 +1274,23 @@ public class Javac extends MatchingTask {
* @exception BuildException if an error occurs
*/
protected void checkParameters() throws BuildException {
- if (src == null) {
- throw new BuildException("srcdir attribute must be set!",
- getLocation());
- }
- if (src.size() == 0) {
- throw new BuildException("srcdir attribute must be set!",
+ if (hasPath(src)) {
+ if (hasPath(moduleSourcepath)) {
+ throw new BuildException("modulesourcepath cannot be combined with srcdir attribute!",
+ getLocation());
+ }
+ } else if (hasPath(moduleSourcepath)) {
+ if (hasPath(src) || hasPath(compileSourcepath)) {
+ throw new BuildException("modulesourcepath cannot be combined with srcdir or sourcepath !",
+ getLocation());
+ }
+ if (destDir == null) {
+ throw new BuildException("modulesourcepath requires destdir attribute to be set!",
getLocation());
+ }
+ } else {
+ throw new BuildException("either srcdir or modulesourcepath attribute must be set!",
+ getLocation());
}
if (destDir != null && !destDir.isDirectory()) {
@@ -1251,6 +1429,226 @@ public class Javac extends MatchingTask {
}
}
+ /**
+ * Checks if a path exists and is non empty.
+ * @param path to be checked
+ * @return true if the path is non <code>null</code> and non empty.
+ * @since 1.9.7
+ */
+ private static boolean hasPath(final Path path) {
+ return path != null && path.size() > 0;
+ }
+
+ /**
+ * Resolves the modulesourcepath element possibly containing groups
+ * and module marks to module names and source roots.
+ * @param projectDir the project directory
+ * @param element the modulesourcepath elemement
+ * @return a mapping from module name to module source roots
+ * @since 1.9.7
+ */
+ private static Map<String,Collection<File>> resolveModuleSourcePathElement(
+ final File projectDir,
+ final String element) {
+ final Map<String,Collection<File>> result = new TreeMap<String, Collection<File>>();
+ for (CharSequence resolvedElement : expandGroups(element)) {
+ findModules(projectDir, resolvedElement.toString(), result);
+ }
+ return result;
+ }
+
+ /**
+ * Expands the groups in the modulesourcepath entry to alternatives.
+ * <p>
+ * The <code>'*'</code> is a token representing the name of any of the modules in the compilation module set.
+ * The <code>'{' ... ',' ... '}'</code> express alternates for expansion.
+ * An example of the modulesourcepath entry is <code>src/*/{linux,share}/classes</code>
+ * </p>
+ * @param element the entry to expand groups in
+ * @return the possible alternatives
+ * @since 1.9.7
+ */
+ private static Collection<? extends CharSequence> expandGroups(
+ final CharSequence element) {
+ List<StringBuilder> result = new ArrayList<StringBuilder>();
+ result.add(new StringBuilder());
+ StringBuilder resolved = new StringBuilder();
+ for (int i = 0; i < element.length(); i++) {
+ final char c = element.charAt(i);
+ switch (c) {
+ case GROUP_START_MARK:
+ final int end = getGroupEndIndex(element, i);
+ if (end < 0) {
+ throw new BuildException(String.format(
+ "Unclosed group %s, starting at: %d",
+ element,
+ i));
+ }
+ final Collection<? extends CharSequence> parts = resolveGroup(element.subSequence(i+1, end));
+ switch (parts.size()) {
+ case 0:
+ break;
+ case 1:
+ resolved.append(parts.iterator().next());
+ break;
+ default:
+ final List<StringBuilder> oldRes = result;
+ result = new ArrayList<StringBuilder>(oldRes.size() * parts.size());
+ for (CharSequence part : parts) {
+ for (CharSequence prefix : oldRes) {
+ result.add(new StringBuilder(prefix).append(resolved).append(part));
+ }
+ }
+ resolved = new StringBuilder();
+ }
+ i = end;
+ break;
+ default:
+ resolved.append(c);
+ }
+ }
+ for (StringBuilder prefix : result) {
+ prefix.append(resolved);
+ }
+ return result;
+ }
+
+ /**
+ * Resolves the group to alternatives.
+ * @param group the group to resolve
+ * @return the possible alternatives
+ * @since 1.9.7
+ */
+ private static Collection<? extends CharSequence> resolveGroup(final CharSequence group) {
+ final Collection<CharSequence> result = new ArrayList<CharSequence>();
+ int start = 0;
+ int depth = 0;
+ for (int i = 0; i < group.length(); i++) {
+ final char c = group.charAt(i);
+ switch (c) {
+ case GROUP_START_MARK:
+ depth++;
+ break;
+ case GROUP_END_MARK:
+ depth--;
+ break;
+ case GROUP_SEP_MARK:
+ if (depth == 0) {
+ result.addAll(expandGroups(group.subSequence(start, i)));
+ start = i + 1;
+ }
+ break;
+ }
+ }
+ result.addAll(expandGroups(group.subSequence(start, group.length())));
+ return result;
+ }
+
+ /**
+ * Finds the index of an enclosing brace of the group.
+ * @param element the element to find the enclosing brace in
+ * @param start the index of the opening brace.
+ * @return return the index of an enclosing brace of the group or -1 if not found
+ * @since 1.9.7
+ */
+ private static int getGroupEndIndex(
+ final CharSequence element,
+ final int start) {
+ int depth = 0;
+ for (int i = start; i < element.length(); i++) {
+ final char c = element.charAt(i);
+ switch (c) {
+ case GROUP_START_MARK:
+ depth++;
+ break;
+ case GROUP_END_MARK:
+ depth--;
+ if (depth == 0) {
+ return i;
+ }
+ break;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Finds modules in the expanded modulesourcepath entry.
+ * @param root the project root
+ * @param pattern the expanded modulesourcepath entry
+ * @param collector the map to put modules into
+ * @since 1.9.7
+ */
+ private static void findModules(
+ final File root,
+ String pattern,
+ final Map<String,Collection<File>> collector) {
+ pattern = pattern
+ .replace('/', File.separatorChar)
+ .replace('\\', File.separatorChar);
+ final int startIndex = pattern.indexOf(MODULE_MARKER);
+ if (startIndex == -1) {
+ findModules(root, pattern, null, collector);
+ } else {
+ if (startIndex == 0) {
+ throw new BuildException("The modulesourcepath entry must be a folder.");
+ }
+ final int endIndex = startIndex + MODULE_MARKER.length();
+ if (pattern.charAt(startIndex - 1) != File.separatorChar) {
+ throw new BuildException("The module mark must be preceded by separator");
+ }
+ if (endIndex < pattern.length() && pattern.charAt(endIndex) != File.separatorChar) {
+ throw new BuildException("The module mark must be followed by separator");
+ }
+ if (pattern.indexOf(MODULE_MARKER, endIndex) != -1) {
+ throw new BuildException("The modulesourcepath entry must contain at most one module mark");
+ }
+ final String pathToModule = pattern.substring(0,startIndex);
+ final String pathInModule = endIndex == pattern.length() ?
+ null :
+ pattern.substring(endIndex+1); //+1 the separator
+ findModules(root, pathToModule, pathInModule, collector);
+ }
+ }
+
+ /**
+ * Finds modules in the expanded modulesourcepath entry.
+ * @param root the project root
+ * @param pathToModule the path to modules folder
+ * @param pathInModule the path in module to source folder
+ * @param collector the map to put modules into
+ * @since 1.9.7
+ */
+ private static void findModules(
+ final File root,
+ final String pathToModule,
+ final String pathInModule,
+ final Map<String,Collection<File>> collector) {
+ final FileUtils fu = FileUtils.getFileUtils();
+ final File f = fu.resolveFile(root, pathToModule);
+ if (!f.isDirectory()) {
+ return;
+ }
+ final File[] modules = f.listFiles(new FileFilter() {
+ @Override
+ public boolean accept(File pathname) {
+ return pathname.isDirectory();
+ }
+ });
+ for (File module : modules) {
+ final String moduleName = module.getName();
+ final File moduleSourceRoot = pathInModule == null ?
+ module :
+ new File(module, pathInModule);
+ Collection<File> moduleRoots = collector.get(moduleName);
+ if (moduleRoots == null) {
+ moduleRoots = new ArrayList<File>();
+ collector.put(moduleName, moduleRoots);
+ }
+ moduleRoots.add(moduleSourceRoot);
+ }
+ }
+
private static final byte[] PACKAGE_INFO_CLASS_HEADER = {
(byte) 0xca, (byte) 0xfe, (byte) 0xba, (byte) 0xbe, 0x00, 0x00, 0x00,
0x31, 0x00, 0x07, 0x07, 0x00, 0x05, 0x07, 0x00, 0x06, 0x01, 0x00, 0x0a,
http://git-wip-us.apache.org/repos/asf/ant/blob/83eaf480/src/main/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapter.java
----------------------------------------------------------------------
diff --git a/src/main/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapter.java b/src/main/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapter.java
index 519163c..d1a9cb3 100644
--- a/src/main/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapter.java
+++ b/src/main/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapter.java
@@ -73,7 +73,10 @@ public abstract class DefaultCompilerAdapter
protected Path bootclasspath;
protected Path extdirs;
protected Path compileClasspath;
+ protected Path modulepath;
+ protected Path upgrademodulepath;
protected Path compileSourcepath;
+ protected Path moduleSourcepath;
protected Project project;
protected Location location;
protected boolean includeAntRuntime;
@@ -112,13 +115,20 @@ public abstract class DefaultCompilerAdapter
extdirs = attributes.getExtdirs();
compileList = attributes.getFileList();
compileClasspath = attributes.getClasspath();
+ modulepath = attributes.getModulepath();
+ upgrademodulepath = attributes.getUpgrademodulepath();
compileSourcepath = attributes.getSourcepath();
+ moduleSourcepath = attributes.getModulesourcepath();
project = attributes.getProject();
location = attributes.getLocation();
includeAntRuntime = attributes.getIncludeantruntime();
includeJavaRuntime = attributes.getIncludejavaruntime();
memoryInitialSize = attributes.getMemoryInitialSize();
memoryMaximumSize = attributes.getMemoryMaximumSize();
+ if (moduleSourcepath != null && src == null && compileSourcepath == null) {
+ //Compatibility to prevent NPE from Jikes, Jvc, Kjc
+ compileSourcepath = new Path(getProject());
+ }
}
/**
@@ -183,6 +193,45 @@ public abstract class DefaultCompilerAdapter
}
/**
+ * Builds the modulepath.
+ * @return the modulepath
+ * @since 1.9.7
+ */
+ protected Path getModulepath() {
+ final Path mp = new Path(getProject());
+ if (modulepath != null) {
+ mp.addExisting(modulepath);
+ }
+ return mp;
+ }
+
+ /**
+ * Builds the upgrademodulepath.
+ * @return the upgrademodulepath
+ * @since 1.9.7
+ */
+ protected Path getUpgrademodulepath() {
+ final Path ump = new Path(getProject());
+ if (upgrademodulepath != null) {
+ ump.addExisting(upgrademodulepath);
+ }
+ return ump;
+ }
+
+ /**
+ * Builds the modulesourcepath for multi module compilation.
+ * @return the modulesourcepath
+ * @since 1.9.7
+ */
+ protected Path getModulesourcepath() {
+ final Path msp = new Path(getProject());
+ if (moduleSourcepath != null) {
+ msp.add(moduleSourcepath);
+ }
+ return msp;
+ }
+
+ /**
* Get the command line arguments for the switches.
* @param cmd the command line
* @return the command line
@@ -350,6 +399,21 @@ public abstract class DefaultCompilerAdapter
setImplicitSourceSwitch(cmd, t, adjustSourceValue(t));
}
}
+ final Path msp = getModulesourcepath();
+ if (msp.size() > 0) {
+ cmd.createArgument().setValue("-modulesourcepath");
+ cmd.createArgument().setPath(msp);
+ }
+ final Path mp = getModulepath();
+ if (mp.size() > 0) {
+ cmd.createArgument().setValue("-modulepath");
+ cmd.createArgument().setPath(mp);
+ }
+ final Path ump = getUpgrademodulepath();
+ if (ump.size() > 0) {
+ cmd.createArgument().setValue("-upgrademodulepath");
+ cmd.createArgument().setPath(ump);
+ }
return cmd;
}
http://git-wip-us.apache.org/repos/asf/ant/blob/83eaf480/src/tests/junit/org/apache/tools/ant/taskdefs/JavacTest.java
----------------------------------------------------------------------
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/JavacTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/JavacTest.java
index 12ceea2..67e31e9 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/JavacTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/JavacTest.java
@@ -18,6 +18,7 @@
package org.apache.tools.ant.taskdefs;
+import java.io.File;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.compilers.CompilerAdapter;
import org.apache.tools.ant.taskdefs.compilers.CompilerAdapterFactory;
@@ -28,10 +29,13 @@ import org.junit.Before;
import org.junit.Test;
import static org.apache.tools.ant.AntAssert.assertContains;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.types.Path;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
/**
* Testcase for <javac>.
@@ -244,4 +248,85 @@ public class JavacTest {
javac.setTarget("1.5");
assertEquals("1.5", javac.getTarget());
}
+
+ @Test
+ public void testModulesourcepathOrSrcDirRequired() {
+ try {
+ javac.checkParameters();
+ fail("Build exception should have been thrown - neither srcDir nor modulesourcepath");
+ } catch (BuildException e) {
+ //pass
+ }
+ }
+
+ @Test
+ public void testModulesourcepathAndSrcDirForbidden() {
+ try {
+ javac.checkParameters();
+ final Path p = new Path(project);
+ p.setPath("src");
+ javac.setSrcdir(p);
+ final Path mp = new Path(project);
+ p.setPath("modsrc");
+ javac.setModulesourcepath(mp);
+ fail("Build exception should have been thrown - neither srcDir nor modulesourcepath");
+ } catch (BuildException e) {
+ //pass
+ }
+ }
+
+ @Test
+ public void testModulesourcepathAndSourcepathForbidden() {
+ try {
+ javac.checkParameters();
+ final Path p = new Path(project);
+ p.setPath("src");
+ javac.setSourcepath(p);
+ final Path mp = new Path(project);
+ p.setPath("modsrc");
+ javac.setModulesourcepath(mp);
+ fail("Build exception should have been thrown - neither srcDir nor modulesourcepath");
+ } catch (BuildException e) {
+ //pass
+ }
+ }
+
+ @Test
+ public void testSrcDir() {
+ final Path p = new Path(project);
+ p.setPath("src");
+ javac.setSrcdir(p);
+ javac.checkParameters();
+ }
+
+ @Test
+ public void testModulesourcepath() {
+ final File tmp = new File(System.getProperty("java.io.tmpdir")); //NOI18N
+ final File destDir = new File(tmp, String.format("%stestMP%d",
+ getClass().getName(),
+ System.currentTimeMillis()/1000));
+ destDir.mkdirs();
+ try {
+ final Path p = new Path(project);
+ p.setPath("src");
+ javac.setModulesourcepath(p);
+ javac.setDestdir(destDir);
+ javac.checkParameters();
+ } finally {
+ destDir.delete();
+ }
+ }
+
+ @Test
+ public void testModulesourcepathRequiresDestdir() {
+ try {
+ final Path p = new Path(project);
+ p.setPath("src");
+ javac.setModulesourcepath(p);
+ javac.checkParameters();
+ fail("Build exception should have been thrown - modulesourcepath requires destdir");
+ } catch (BuildException e) {
+ //pass
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/ant/blob/83eaf480/src/tests/junit/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapterTest.java
----------------------------------------------------------------------
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapterTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapterTest.java
index 750098f..2972cdb 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapterTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapterTest.java
@@ -18,12 +18,23 @@
package org.apache.tools.ant.taskdefs.compilers;
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Javac;
import org.apache.tools.ant.types.Commandline;
import org.junit.Test;
import static org.apache.tools.ant.AntAssert.assertContains;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.util.FileUtils;
+import org.junit.Assert;
import static org.junit.Assert.assertEquals;
public class DefaultCompilerAdapterTest {
@@ -174,6 +185,127 @@ public class DefaultCompilerAdapterTest {
testSource(null, "javac1.9", "", "9");
}
+ @Test
+ public void testSingleModuleCompilation() throws IOException {
+ final File workDir = createWorkDir("testSMC");
+ try {
+ final File src = new File(workDir, "src");
+ src.mkdir();
+ final File java1 = createFile(src,"org/apache/ant/tests/J1.java");
+ final File java2 = createFile(src,"org/apache/ant/tests/J2.java");
+ final File modules = new File(workDir, "modules");
+ modules.mkdir();
+ final Project prj = new Project();
+ prj.setBaseDir(workDir);
+ final LogCapturingJavac javac = new LogCapturingJavac();
+ javac.setProject(prj);
+ final Commandline[] cmd = new Commandline[1];
+ final DefaultCompilerAdapter impl = new DefaultCompilerAdapter() {
+ @Override
+ public boolean execute() throws BuildException {
+ cmd[0] = setupModernJavacCommand();
+ return true;
+ }
+ };
+ final Path srcPath = new Path(prj);
+ srcPath.setLocation(src);
+ javac.setSrcdir(srcPath);
+ javac.createModulepath().setLocation(modules);
+ javac.setSource("9");
+ javac.setTarget("9");
+ javac.setIncludeantruntime(false);
+ javac.add(impl);
+ javac.execute();
+ Assert.assertNotNull(cmd[0]);
+ final List<String> cmdLine = Arrays.asList(cmd[0].getCommandline());
+ //No modulesourcepath
+ assertEquals(-1, cmdLine.indexOf("-modulesourcepath"));
+ //The -sourcepath has to be followed by src
+ int index = cmdLine.indexOf("-sourcepath");
+ Assert.assertTrue(index != -1 && index < cmdLine.size() - 1);
+ assertEquals(src.getAbsolutePath(), cmdLine.get(index + 1));
+ //The -modulepath has to be followed by modules
+ index = cmdLine.indexOf("-modulepath");
+ Assert.assertTrue(index != -1 && index < cmdLine.size() - 1);
+ assertEquals(modules.getAbsolutePath(), cmdLine.get(index + 1));
+ //J1.java & J2.java has to be in files list
+ final Set<String> expected = new TreeSet<String>();
+ Collections.addAll(expected, java1.getAbsolutePath(), java2.getAbsolutePath());
+ final Set<String> actual = new TreeSet<String>();
+ actual.addAll(cmdLine.subList(cmdLine.size() - 2, cmdLine.size()));
+ assertEquals(expected, actual);
+ } finally {
+ delete(workDir);
+ }
+ }
+
+ @Test
+ public void testMultiModuleCompilation() throws IOException {
+ final File workDir = createWorkDir("testMMC");
+ try {
+ final File src = new File(workDir, "src");
+ src.mkdir();
+ final File java1 = createFile(src,"main/m1/lin64/classes/org/apache/ant/tests/J1.java");
+ final File java2 = createFile(src,"main/m2/lin32/classes/org/apache/ant/tests/J2.java");
+ final File java3 = createFile(src,"main/m3/sol/classes/org/apache/ant/tests/J3.java");
+ final File modules = new File(workDir, "modules");
+ modules.mkdir();
+ final File build = new File(workDir, "build");
+ build.mkdirs();
+ final Project prj = new Project();
+ prj.setBaseDir(workDir);
+ final LogCapturingJavac javac = new LogCapturingJavac();
+ javac.setProject(prj);
+ final Commandline[] cmd = new Commandline[1];
+ final DefaultCompilerAdapter impl = new DefaultCompilerAdapter() {
+ @Override
+ public boolean execute() throws BuildException {
+ cmd[0] = setupModernJavacCommand();
+ return true;
+ }
+ };
+ final String moduleSrcPathStr = "src/main/*/{lin{32,64},sol}/classes";
+ final Path moduleSourcePath = new Path(prj);
+ moduleSourcePath.setPath(moduleSrcPathStr);
+ javac.setModulesourcepath(moduleSourcePath);
+ javac.createModulepath().setLocation(modules);
+ javac.setSource("9");
+ javac.setTarget("9");
+ javac.setDestdir(build);
+ javac.setIncludeantruntime(false);
+ javac.add(impl);
+ javac.execute();
+ Assert.assertNotNull(cmd[0]);
+ final List<String> cmdLine = Arrays.asList(cmd[0].getCommandline());
+ //No sourcepath
+ assertEquals(-1, cmdLine.indexOf("-sourcepath"));
+ //The -modulesourcepath has to be followed by the pattern
+ int index = cmdLine.indexOf("-modulesourcepath");
+ Assert.assertTrue(index != -1 && index < cmdLine.size() - 1);
+ String expectedModSrcPath = String.format("%s/%s",
+ workDir.getAbsolutePath(),
+ moduleSrcPathStr)
+ .replace('/', File.separatorChar)
+ .replace('\\', File.separatorChar);
+ assertEquals(expectedModSrcPath, cmdLine.get(index + 1));
+ //The -modulepath has to be followed by modules
+ index = cmdLine.indexOf("-modulepath");
+ Assert.assertTrue(index != -1 && index < cmdLine.size() - 1);
+ assertEquals(modules.getAbsolutePath(), cmdLine.get(index + 1));
+ //J1.java, J2.java & J3.java has to be in files list
+ final Set<String> expectedFiles = new TreeSet<String>();
+ Collections.addAll(expectedFiles,
+ java1.getAbsolutePath(),
+ java2.getAbsolutePath(),
+ java3.getAbsolutePath());
+ final Set<String> actualFiles = new TreeSet<String>();
+ actualFiles.addAll(cmdLine.subList(cmdLine.size() - 3, cmdLine.size()));
+ assertEquals(expectedFiles, actualFiles);
+ } finally {
+ delete(workDir);
+ }
+ }
+
private void commonSourceDowngrades(String javaVersion) {
testSource("1.3", javaVersion,
"If you specify -target 1.1 you now must also specify"
@@ -220,4 +352,35 @@ public class DefaultCompilerAdapterTest {
assertEquals(expectedSource, args[1]);
}
}
+
+ private File createWorkDir(String testName) {
+ final File tmp = new File(System.getProperty("java.io.tmpdir")); //NOI18N
+ final File destDir = new File(tmp, String.format("%s%s%d",
+ getClass().getName(),
+ testName,
+ System.currentTimeMillis()/1000));
+ destDir.mkdirs();
+ return destDir;
+ }
+
+ private File createFile(File folder, String relativePath) throws IOException {
+ final File file = new File(
+ folder,
+ relativePath.replace('/', File.separatorChar).replace('\\', File.separatorChar));
+ FileUtils.getFileUtils().createNewFile(file, true);
+ return file;
+ }
+
+ private void delete(File f) {
+ if (f.isDirectory()) {
+ final File[] clds = f.listFiles();
+ if (clds != null) {
+ for (File cld : clds) {
+ delete(cld);
+ }
+ }
+ }
+ f.delete();
+ }
+
}