From 4ca5683c2a54ff4a141ed562a0f3b431b153b2c2 Mon Sep 17 00:00:00 2001 From: Stefan Bodewig Date: Fri, 12 Jan 2001 14:08:51 +0000 Subject: [PATCH] rewritten to use a factory. Submitted by: Jay Glanville git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@268444 13f79535-47bb-0310-9956-ffa450edef68 --- WHATSNEW | 4 + docs/index.html | 19 +- .../apache/tools/ant/taskdefs/Execute.java | 2 +- .../org/apache/tools/ant/taskdefs/Javac.java | 697 ++++-------------- .../taskdefs/compilers/CompilerAdapter.java | 86 +++ .../compilers/CompilerAdapterFactory.java | 151 ++++ .../compilers/DefaultCompilerAdapter.java | 373 ++++++++++ .../tools/ant/taskdefs/compilers/Javac12.java | 108 +++ .../tools/ant/taskdefs/compilers/Javac13.java | 113 +++ .../tools/ant/taskdefs/compilers/Jikes.java | 205 ++++++ .../tools/ant/taskdefs/compilers/Jvc.java | 134 ++++ src/main/org/apache/tools/ant/types/Path.java | 16 +- 12 files changed, 1349 insertions(+), 559 deletions(-) create mode 100644 src/main/org/apache/tools/ant/taskdefs/compilers/CompilerAdapter.java create mode 100644 src/main/org/apache/tools/ant/taskdefs/compilers/CompilerAdapterFactory.java create mode 100644 src/main/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapter.java create mode 100644 src/main/org/apache/tools/ant/taskdefs/compilers/Javac12.java create mode 100644 src/main/org/apache/tools/ant/taskdefs/compilers/Javac13.java create mode 100644 src/main/org/apache/tools/ant/taskdefs/compilers/Jikes.java create mode 100644 src/main/org/apache/tools/ant/taskdefs/compilers/Jvc.java diff --git a/WHATSNEW b/WHATSNEW index 56f19ae58..c1fb6fa7b 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -9,6 +9,10 @@ Changes that could break older environments: * has been replaced by a number of new tasks. +* is now implemented using a factory. This makes extending + javac to use a new compiler a lot easier but may break custom + versions of this task that rely on the old implementation. + Other changes: -------------- diff --git a/docs/index.html b/docs/index.html index 1bb86b430..6bff27131 100644 --- a/docs/index.html +++ b/docs/index.html @@ -3170,7 +3170,12 @@ inclusion/exclusion of files works, and how to write patterns.

  • jvc (the Command-Line Compiler from Microsoft's SDK for Java / Visual J++)
  • -

    For JDK 1.1/1.2 is classic the default. For JDK 1.3 is modern the default.

    +

    For JDK 1.1/1.2 is classic the default. For JDK 1.3 is modern the default. +If you whish to use a different compiler interface then one of the four +supplied, then write a class that implements the CompilerAdapter interface +(package org.apache.tools.ant.taskdefs.compilers). Supply the full +classname in the "build.compiler" property. +

    Parameters

    @@ -3284,6 +3289,18 @@ inclusion/exclusion of files works, and how to write patterns.

    tracking for compilers that support this (jikes and classic) + + + + + + + + + +
    No
    includeAntRuntimewhether or not to include the ant runtime libraries. + Default is no.No
    includeJavaRuntimwhether or not to include the default runtime + libraries from the executing virtual machine. Default is no.No
    failonerror If set to false, the build will continue even if there are compilation errors. diff --git a/src/main/org/apache/tools/ant/taskdefs/Execute.java b/src/main/org/apache/tools/ant/taskdefs/Execute.java index a9a5e9a4a..be2a73b0f 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Execute.java +++ b/src/main/org/apache/tools/ant/taskdefs/Execute.java @@ -355,7 +355,7 @@ public class Execute { exitValue = value; } - protected int getExitValue() { + public int getExitValue() { return exitValue; } diff --git a/src/main/org/apache/tools/ant/taskdefs/Javac.java b/src/main/org/apache/tools/ant/taskdefs/Javac.java index 186ddc3d7..7917f84bd 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Javac.java +++ b/src/main/org/apache/tools/ant/taskdefs/Javac.java @@ -59,11 +59,9 @@ import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.Project; import org.apache.tools.ant.types.*; import org.apache.tools.ant.util.*; +import org.apache.tools.ant.taskdefs.compilers.*; -import java.lang.reflect.Method; -import java.lang.reflect.Constructor; -import java.io.*; -import java.util.*; +import java.io.File; /** * Task to compile Java source files. This task can take the following @@ -81,6 +79,9 @@ import java.util.*; *
  • target *
  • depend *
  • vebose + *
  • failonerror + *
  • includeantruntime + *
  • includejavaruntime * * Of these arguments, the sourcedir and destdir are required. *

    @@ -91,16 +92,13 @@ import java.util.*; * @author James Davidson duncan@x180.com * @author Robin Green greenrd@hotmail.com * @author Stefan Bodewig + * @author J D Glanville */ public class Javac extends MatchingTask { - /** - * Integer returned by the "Modern" jdk1.3 compiler to indicate success. - */ - private static final int - MODERN_COMPILER_SUCCESS = 0; - private static final String FAIL_MSG = "Compile failed, messages should have been provided."; + private static final String FAIL_MSG + = "Compile failed, messages should have been provided."; private Path src; private File destDir; @@ -114,7 +112,8 @@ public class Javac extends MatchingTask { private String target; private Path bootclasspath; private Path extdirs; - private static String lSep = System.getProperty("line.separator"); + private boolean includeAntRuntime = true; + private boolean includeJavaRuntime = false; protected boolean failOnError = true; protected File[] compileList = new File[0]; @@ -143,6 +142,11 @@ public class Javac extends MatchingTask { } } + /** Gets the source dirs to find the source java files. */ + public Path getSrcdir() { + return src; + } + /** * Set the destination directory into which the Java source * files should be compiled. @@ -151,6 +155,14 @@ public class Javac extends MatchingTask { this.destDir = destDir; } + /** + * Gets the destination directory into which the java source files + * should be compiled. + */ + public File getDestdir() { + return destDir; + } + /** * Set the classpath to be used for this compilation. */ @@ -162,6 +174,11 @@ public class Javac extends MatchingTask { } } + /** Gets the classpath to be used for this compilation. */ + public Path getClasspath() { + return compileClasspath; + } + /** * Maybe creates a nested classpath element. */ @@ -191,6 +208,14 @@ public class Javac extends MatchingTask { } } + /** + * Gets the bootclasspath that will be used to compile the classes + * against. + */ + public Path getBootclasspath() { + return bootclasspath; + } + /** * Maybe creates a nested classpath element. */ @@ -220,6 +245,14 @@ public class Javac extends MatchingTask { } } + /** + * Gets the extension directories that will be used during the + * compilation. + */ + public Path getExtdirs() { + return extdirs; + } + /** * Maybe creates a nested classpath element. */ @@ -244,6 +277,13 @@ public class Javac extends MatchingTask { failOnError = !proceed; } + /** + * Gets the failonerror flag. + */ + public boolean getFailonerror() { + return failOnError; + } + /** * Set the deprecation flag. */ @@ -251,6 +291,11 @@ public class Javac extends MatchingTask { this.deprecation = deprecation; } + /** Gets the deprecation flag. */ + public boolean getDeprecation() { + return deprecation; + } + /** * Set the Java source file encoding name. */ @@ -258,6 +303,11 @@ public class Javac extends MatchingTask { this.encoding = encoding; } + /** Gets the java source file encoding name. */ + public String getEncoding() { + return encoding; + } + /** * Set the debug flag. */ @@ -265,26 +315,46 @@ public class Javac extends MatchingTask { this.debug = debug; } + /** Gets the debug flag. */ + public boolean getDebug() { + return debug; + } + /** * Set the optimize flag. */ - public void setOptimize(boolean optimize) { - this.optimize = optimize; - } + public void setOptimize(boolean optimize) { + this.optimize = optimize; + } + + /** Gets the optimize flag. */ + public boolean getOptimize() { + return optimize; + } /** * Set the depend flag. */ - public void setDepend(boolean depend) { - this.depend = depend; - } + public void setDepend(boolean depend) { + this.depend = depend; + } + + /** Gets the depend flag. */ + public boolean getDepend() { + return depend; + } /** * Set the verbose flag. */ - public void setVerbose(boolean verbose) { - this.verbose = verbose; - } + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } + + /** Gets the verbose flag. */ + public boolean getVerbose() { + return verbose; + } /** * Sets the target VM that the classes will be compiled for. Valid @@ -294,6 +364,42 @@ public class Javac extends MatchingTask { this.target = target; } + /** Gets the target VM that the classes will be compiled for. */ + public String getTarget() { + return target; + } + + /** + * Include ant's own classpath in this task's classpath? + */ + public void setIncludeantruntime( boolean include ) { + includeAntRuntime = include; + } + + /** + * Gets whether or not the ant classpath is to be included in the + * task's classpath. + */ + public boolean getIncludeantruntime() { + return includeAntRuntime; + } + + /** + * Sets whether or not to include the java runtime libraries to this + * task's classpath. + */ + public void setIncludejavaruntime( boolean include ) { + includeJavaRuntime = include; + } + + /** + * Gets whether or not the java runtime should be included in this + * task's classpath. + */ + public boolean getIncludejavaruntime() { + return includeJavaRuntime; + } + /** * Executes the task. */ @@ -312,7 +418,7 @@ public class Javac extends MatchingTask { throw new BuildException("destination directory \"" + destDir + "\" does not exist or is not a directory", location); } - // scan source directories and dest directory to build up both copy lists and + // scan source directories and dest directory to build up // compile lists resetFileLists(); for (int i=0; i 0) { + + CompilerAdapter adapter = CompilerAdapterFactory.getCompiler( + compiler, this ); log("Compiling " + compileList.length + " source file" + (compileList.length == 1 ? "" : "s") + (destDir != null ? " to " + destDir : "")); - boolean compileSucceeded = false; - - if (compiler.equalsIgnoreCase("classic")) { - compileSucceeded = doClassicCompile(); - } else if (compiler.equalsIgnoreCase("modern")) { - compileSucceeded = doModernCompile(); - } else if (compiler.equalsIgnoreCase("jikes")) { - compileSucceeded = doJikesCompile(); - } else if (compiler.equalsIgnoreCase("jvc")) { - compileSucceeded = doJvcCompile(); - } else { - String msg = "Don't know how to use compiler " + compiler; - throw new BuildException(msg, location); - } + // now we need to populate the compiler adapter + adapter.setJavac( this ); - if (!compileSucceeded) { + // finally, lets execute the compiler!! + if (!adapter.execute()) { if (failOnError) { throw new BuildException(FAIL_MSG, location); } @@ -382,7 +480,6 @@ public class Javac extends MatchingTask { * Scans the directory looking for source files to be compiled. * The results are returned in the class variable compileList */ - protected void scanDir(File srcDir, File destDir, String files[]) { GlobPatternMapper m = new GlobPatternMapper(); m.setFrom("*.java"); @@ -391,527 +488,19 @@ public class Javac extends MatchingTask { File[] newFiles = sfs.restrictAsFiles(files, srcDir, destDir, m); if (newFiles.length > 0) { - File[] newCompileList = new File[compileList.length + newFiles.length]; - System.arraycopy(compileList, 0, newCompileList, 0, compileList.length); - System.arraycopy(newFiles, 0, newCompileList, compileList.length, newFiles.length); + File[] newCompileList = new File[compileList.length + + newFiles.length]; + System.arraycopy(compileList, 0, newCompileList, 0, + compileList.length); + System.arraycopy(newFiles, 0, newCompileList, + compileList.length, newFiles.length); compileList = newCompileList; } } - /** - * Builds the compilation classpath. - * - * @param addRuntime Shall rt.jar or - * classes.zip be added to the classpath. - */ - protected Path getCompileClasspath(boolean addRuntime) { - Path classpath = new Path(project); - - // add dest dir to classpath so that previously compiled and - // untouched classes are on classpath - - if (destDir != null) { - classpath.setLocation(destDir); - } - - // Combine the build classpath with the system classpath, in an - // order determined by the value of build.classpath - - if (compileClasspath == null) { - classpath.addExisting(Path.systemClasspath); - } else { - classpath.addExisting(compileClasspath.concatSystemClasspath()); - } - - // optionally add the runtime classes - - if (addRuntime) { - if (System.getProperty("java.vendor").toLowerCase().indexOf("microsoft") >= 0) { - // Pull in *.zip from packages directory - FileSet msZipFiles = new FileSet(); - msZipFiles.setDir(new File(System.getProperty("java.home") + File.separator + "Packages")); - msZipFiles.setIncludes("*.ZIP"); - classpath.addFileset(msZipFiles); - } - else if (Project.getJavaVersion() == Project.JAVA_1_1) { - classpath.addExisting(new Path(null, - System.getProperty("java.home") - + File.separator + "lib" - + File.separator - + "classes.zip")); - } else { - // JDK > 1.1 seems to set java.home to the JRE directory. - classpath.addExisting(new Path(null, - System.getProperty("java.home") - + File.separator + "lib" - + File.separator + "rt.jar")); - // Just keep the old version as well and let addExistingToPath - // sort it out. - classpath.addExisting(new Path(null, - System.getProperty("java.home") - + File.separator +"jre" - + File.separator + "lib" - + File.separator + "rt.jar")); - } - } - - return classpath; - } - - /** - * Peforms a compile using the classic compiler that shipped with - * JDK 1.1 and 1.2. - * - * @return true if the compile succeeded - */ - private boolean doClassicCompile() throws BuildException { - log("Using classic compiler", Project.MSG_VERBOSE); - Commandline cmd = setupJavacCommand(); - - // Use reflection to be able to build on all JDKs - /* - // provide the compiler a different message sink - namely our own - sun.tools.javac.Main compiler = - new sun.tools.javac.Main(new LogOutputStream(this, Project.MSG_WARN), "javac"); - - if (!compiler.compile(cmd.getArguments())) { - throw new BuildException("Compile failed"); - } - */ - try { - // Create an instance of the compiler, redirecting output to - // the project log - OutputStream logstr = new LogOutputStream(this, Project.MSG_WARN); - Class c = Class.forName("sun.tools.javac.Main"); - Constructor cons = c.getConstructor(new Class[] { OutputStream.class, String.class }); - Object compiler = cons.newInstance(new Object[] { logstr, "javac" }); - - // Call the compile() method - Method compile = c.getMethod("compile", new Class [] { String[].class }); - Boolean ok = (Boolean)compile.invoke(compiler, new Object[] {cmd.getArguments()}); - return ok.booleanValue(); - } - catch (ClassNotFoundException ex) { - throw new BuildException("Cannot use classic compiler, as it is not available"+ - " A common solution is to set the environment variable"+ - " JAVA_HOME to your jdk directory.", location); - } - catch (Exception ex) { - if (ex instanceof BuildException) { - throw (BuildException) ex; - } else { - throw new BuildException("Error starting classic compiler: ", ex, location); - } - } - } - - /** - * Performs a compile using the newer compiler that ships with JDK 1.3 - * - * @return true if the compile succeeded - */ - private boolean doModernCompile() throws BuildException { - try { - Class.forName("com.sun.tools.javac.Main"); - } catch (ClassNotFoundException cnfe) { - log("Modern compiler is not available - using classic compiler", Project.MSG_WARN); - return doClassicCompile(); - } - - log("Using modern compiler", Project.MSG_VERBOSE); - Commandline cmd = setupJavacCommand(); - - PrintStream err = System.err; - PrintStream out = System.out; - - // Use reflection to be able to build on all JDKs >= 1.1: - try { - PrintStream logstr = - new PrintStream(new LogOutputStream(this, Project.MSG_WARN)); - System.setOut(logstr); - System.setErr(logstr); - Class c = Class.forName ("com.sun.tools.javac.Main"); - Object compiler = c.newInstance (); - Method compile = c.getMethod ("compile", - new Class [] {(new String [] {}).getClass ()}); - int result = ((Integer) compile.invoke - (compiler, new Object[] {cmd.getArguments()})) .intValue (); - return (result == MODERN_COMPILER_SUCCESS); - } catch (Exception ex) { - if (ex instanceof BuildException) { - throw (BuildException) ex; - } else { - throw new BuildException("Error starting modern compiler", ex, location); - } - } finally { - System.setErr(err); - System.setOut(out); - } + /** Gets the list of files to be compiled. */ + public File[] getFileList() { + return compileList; } - /** - * Does the command line argument processing common to classic and - * modern. - */ - private Commandline setupJavacCommand() { - Commandline cmd = new Commandline(); - Path classpath = getCompileClasspath(false); - - if (deprecation == true) { - cmd.createArgument().setValue("-deprecation"); - } - - if (destDir != null) { - cmd.createArgument().setValue("-d"); - cmd.createArgument().setFile(destDir); - } - - cmd.createArgument().setValue("-classpath"); - // Just add "sourcepath" to classpath ( for JDK1.1 ) - if (Project.getJavaVersion().startsWith("1.1")) { - cmd.createArgument().setValue(classpath.toString() - + File.pathSeparator - + src.toString()); - } else { - cmd.createArgument().setPath(classpath); - cmd.createArgument().setValue("-sourcepath"); - cmd.createArgument().setPath(src); - if (target != null) { - cmd.createArgument().setValue("-target"); - cmd.createArgument().setValue(target); - } - } - if (encoding != null) { - cmd.createArgument().setValue("-encoding"); - cmd.createArgument().setValue(encoding); - } - if (debug) { - cmd.createArgument().setValue("-g"); - } - if (optimize) { - cmd.createArgument().setValue("-O"); - } - if (bootclasspath != null) { - cmd.createArgument().setValue("-bootclasspath"); - cmd.createArgument().setPath(bootclasspath); - } - if (extdirs != null) { - cmd.createArgument().setValue("-extdirs"); - cmd.createArgument().setPath(extdirs); - } - - if (depend) { - if (Project.getJavaVersion().startsWith("1.1")) { - cmd.createArgument().setValue("-depend"); - } else if (Project.getJavaVersion().startsWith("1.2")) { - cmd.createArgument().setValue("-Xdepend"); - } else { - log("depend attribute is not supported by the modern compiler", - Project.MSG_WARN); - } - } - - if (verbose) { - cmd.createArgument().setValue("-verbose"); - } - - logAndAddFilesToCompile(cmd); - return cmd; - } - - /** - * Logs the compilation parameters, adds the files to compile and logs the - * &qout;niceSourceList" - */ - protected void logAndAddFilesToCompile(Commandline cmd) { - log("Compilation args: " + cmd.toString(), - Project.MSG_VERBOSE); - - StringBuffer niceSourceList = new StringBuffer("File"); - if (compileList.length != 1) { - niceSourceList.append("s"); - } - niceSourceList.append(" to be compiled:"); - - niceSourceList.append(lSep); - - for (int i=0; i < compileList.length; i++) { - String arg = compileList[i].getAbsolutePath(); - cmd.createArgument().setValue(arg); - niceSourceList.append(" " + arg + lSep); - } - - log(niceSourceList.toString(), Project.MSG_VERBOSE); - } - - /** - * Performs a compile using the Jikes compiler from IBM.. - * Mostly of this code is identical to doClassicCompile() - * However, it does not support all options like - * bootclasspath, extdirs, deprecation and so on, because - * there is no option in jikes and I don't understand - * what they should do. - * - * It has been successfully tested with jikes >1.10 - * - * @author skanthak@muehlheim.de - * - * @return true if the compile succeeded - */ - private boolean doJikesCompile() throws BuildException { - log("Using jikes compiler", Project.MSG_VERBOSE); - - Path classpath = new Path(project); - - // Jikes doesn't support bootclasspath dir (-bootclasspath) - // so we'll emulate it for compatibility and convenience. - if (bootclasspath != null) { - classpath.append(bootclasspath); - } - - // Jikes doesn't support an extension dir (-extdir) - // so we'll emulate it for compatibility and convenience. - addExtdirsToClasspath(classpath); - - classpath.append(getCompileClasspath(true)); - - // Jikes has no option for source-path so we - // will add it to classpath. - classpath.append(src); - - // if the user has set JIKESPATH we should add the contents as well - String jikesPath = System.getProperty("jikes.class.path"); - if (jikesPath != null) { - classpath.append(new Path(project, jikesPath)); - } - - Commandline cmd = new Commandline(); - cmd.setExecutable("jikes"); - - if (deprecation == true) - cmd.createArgument().setValue("-deprecation"); - - if (destDir != null) { - cmd.createArgument().setValue("-d"); - cmd.createArgument().setFile(destDir); - } - - cmd.createArgument().setValue("-classpath"); - cmd.createArgument().setPath(classpath); - - if (encoding != null) { - cmd.createArgument().setValue("-encoding"); - cmd.createArgument().setValue(encoding); - } - if (debug) { - cmd.createArgument().setValue("-g"); - } - if (optimize) { - cmd.createArgument().setValue("-O"); - } - if (verbose) { - cmd.createArgument().setValue("-verbose"); - } - if (depend) { - cmd.createArgument().setValue("-depend"); - } - /** - * XXX - * Perhaps we shouldn't use properties for these - * three options (emacs mode, warnings and pedantic), - * but include it in the javac directive? - */ - - /** - * Jikes has the nice feature to print error - * messages in a form readable by emacs, so - * that emacs can directly set the cursor - * to the place, where the error occured. - */ - String emacsProperty = project.getProperty("build.compiler.emacs"); - if (emacsProperty != null && Project.toBoolean(emacsProperty)) { - cmd.createArgument().setValue("+E"); - } - - /** - * Jikes issues more warnings that javac, for - * example, when you have files in your classpath - * that don't exist. As this is often the case, these - * warning can be pretty annoying. - */ - String warningsProperty = project.getProperty("build.compiler.warnings"); - if (warningsProperty != null && !Project.toBoolean(warningsProperty)) { - cmd.createArgument().setValue("-nowarn"); - } - - /** - * Jikes can issue pedantic warnings. - */ - String pedanticProperty = project.getProperty("build.compiler.pedantic"); - if (pedanticProperty != null && Project.toBoolean(pedanticProperty)) { - cmd.createArgument().setValue("+P"); - } - - /** - * Jikes supports something it calls "full dependency - * checking", see the jikes documentation for differences - * between -depend and +F. - */ - String fullDependProperty = project.getProperty("build.compiler.fulldepend"); - if (fullDependProperty != null && Project.toBoolean(fullDependProperty)) { - cmd.createArgument().setValue("+F"); - } - - int firstFileName = cmd.size(); - logAndAddFilesToCompile(cmd); - - return executeExternalCompile(cmd.getCommandline(), firstFileName) == 0; - } - - /** - * Do the compile with the specified arguments. - * @param args - arguments to pass to process on command line - * @param firstFileName - index of the first source file in args - */ - protected int executeExternalCompile(String[] args, int firstFileName) { - String[] commandArray = null; - File tmpFile = null; - - try { - /* - * Many system have been reported to get into trouble with - * long command lines - no, not only Windows ;-). - * - * POSIX seems to define a lower limit of 4k, so use a temporary - * file if the total length of the command line exceeds this limit. - */ - if (Commandline.toString(args).length() > 4096) { - PrintWriter out = null; - try { - tmpFile = new File("jikes"+(new Random(System.currentTimeMillis())).nextLong()); - out = new PrintWriter(new FileWriter(tmpFile)); - for (int i = firstFileName; i < args.length; i++) { - out.println(args[i]); - } - out.flush(); - commandArray = new String[firstFileName+1]; - System.arraycopy(args, 0, commandArray, 0, firstFileName); - commandArray[firstFileName] = "@" + tmpFile.getAbsolutePath(); - } catch (IOException e) { - throw new BuildException("Error creating temporary file", e, location); - } finally { - if (out != null) { - try {out.close();} catch (Throwable t) {} - } - } - } else { - commandArray = args; - } - - try { - Execute exe = new Execute(new LogStreamHandler(this, - Project.MSG_INFO, - Project.MSG_WARN)); - exe.setAntRun(project); - exe.setWorkingDirectory(project.getBaseDir()); - exe.setCommandline(commandArray); - exe.execute(); - return exe.getExitValue(); - } catch (IOException e) { - throw new BuildException("Error running Jikes compiler", e, location); - } - } finally { - if (tmpFile != null) { - tmpFile.delete(); - } - } - } - - /** - * Emulation of extdirs feature in java >= 1.2. - * This method adds all files in the given - * directories (but not in sub-directories!) to the classpath, - * so that you don't have to specify them all one by one. - * @param classpath - Path to append files to - */ - protected void addExtdirsToClasspath(Path classpath) { - if (extdirs == null) { - String extProp = System.getProperty("java.ext.dirs"); - if (extProp != null) { - extdirs = new Path(project, extProp); - } else { - return; - } - } - - String[] dirs = extdirs.list(); - for (int i=0; i. + */ + +package org.apache.tools.ant.taskdefs.compilers; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.taskdefs.Javac; + +/** + * The interface that all compiler adapters must adher to. + * + *

    A compiler adapter is an adapter that interprets the javac's + * parameters in preperation to be passed off to the compier this + * adapter represents. As all the necessary values are stored in the + * Javac task itself, the only thing all adapters need is the javac + * task, the execute command and a parameterless constructor (for + * reflection).

    + * + * @author Jay Dickon Glanville jayglanville@home.com + */ + +public interface CompilerAdapter { + + /** + * Sets the compiler attributes, which are stored in the Javac task. + */ + public void setJavac( Javac attributes ); + + /** + * Executes the task. + * + * @return has the compilation been successful + */ + public boolean execute() throws BuildException; +} diff --git a/src/main/org/apache/tools/ant/taskdefs/compilers/CompilerAdapterFactory.java b/src/main/org/apache/tools/ant/taskdefs/compilers/CompilerAdapterFactory.java new file mode 100644 index 000000000..ed3dcfbe5 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/compilers/CompilerAdapterFactory.java @@ -0,0 +1,151 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.tools.ant.taskdefs.compilers; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.Project; + +/** + * Creates the necessary compiler adapter, given basic criteria. + * + * @author J D Glanville + */ +public class CompilerAdapterFactory { + + /** This is a singlton -- can't create instances!! */ + private CompilerAdapterFactory() { + } + + /** + * Based on the parameter passed in, this method creates the necessary + * factory desired. + * + * The current mapping for compiler names are as follows: + *
    • jikes = jikes compiler + *
    • classic, javac1.1, javac1.2 = the standard compiler from JDK + * 1.1/1.2 + *
    • modern, javac1.3 = the new compiler of JDK 1.3 + *
    • jvc, microsoft = the command line compiler from Microsoft's SDK + * for Java / Visual J++ + *
    • a fully quallified classname = the name of a compiler + * adapter + *
    + * + * @param compilerType either the name of the desired compiler, or the + * full classname of the compiler's adapter. + * @param task a task to log through. + * @throws BuildException if the compiler type could not be resolved into + * a compiler adapter. + */ + public static CompilerAdapter getCompiler( String compilerType, Task task ) + throws BuildException { + /* If I've done things right, this should be the extent of the + * conditional statements required. + */ + if ( compilerType.equalsIgnoreCase("jikes") ) { + return new Jikes(); + } + if ( compilerType.equalsIgnoreCase("classic") || + compilerType.equalsIgnoreCase("javac1.1") || + compilerType.equalsIgnoreCase("javac1.2")) { + return new Javac12(); + } + if ( compilerType.equalsIgnoreCase("modern") || + compilerType.equalsIgnoreCase("javac1.3")) { + // does the modern compiler exist? + try { + Class.forName("com.sun.tools.javac.Main"); + } catch (ClassNotFoundException cnfe) { + task.log("Modern compiler is not available - using " + + "classic compiler", Project.MSG_WARN); + return new Javac12(); + } + return new Javac13(); + } + if ( compilerType.equalsIgnoreCase("jvc") || + compilerType.equalsIgnoreCase("microsoft")) { + return new Jvc(); + } + return resolveClassName( compilerType ); + } + + /** + * Tries to resolve the given classname into a compiler adapter. + * Throws a fit if it can't. + * + * @param className The fully qualified classname to be created. + * @throws BuildException This is the fit that is thrown if className + * isn't an instance of CompilerAdapter. + */ + private static CompilerAdapter resolveClassName( String className ) + throws BuildException { + try { + Class c = Class.forName( className ); + Object o = c.newInstance(); + return (CompilerAdapter) o; + } catch ( ClassNotFoundException cnfe ) { + throw new BuildException( className + " can\'t be found.", cnfe ); + } catch ( ClassCastException cce ) { + throw new BuildException(className + " isn\'t the classname of " + + "a compiler adapter.", cce); + } catch ( Throwable t ) { + // for all other possibilities + throw new BuildException(className + " caused an interesting " + + "exception.", t); + } + } + +} diff --git a/src/main/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapter.java b/src/main/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapter.java new file mode 100644 index 000000000..867cb3a78 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapter.java @@ -0,0 +1,373 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.tools.ant.taskdefs.compilers; + +import org.apache.tools.ant.*; +import org.apache.tools.ant.taskdefs.*; +import org.apache.tools.ant.types.*; + +import java.io.*; +import java.util.Random; + +/** + * This is the default implementation for the CompilerAdapter interface. + * Currently, this is a cut-and-paste of the original javac task. + * + * @author James Davidson duncan@x180.com + * @author Robin Green greenrd@hotmail.com + * @author Stefan Bodewig + * @author J D Glanville + */ +public abstract class DefaultCompilerAdapter implements CompilerAdapter { + + /* jdg - TODO - all these attributes are currently protected, but they + * should probably be private in the near future. + */ + + protected Path src; + protected File destDir; + protected String encoding; + protected boolean debug = false; + protected boolean optimize = false; + protected boolean deprecation = false; + protected boolean depend = false; + protected boolean verbose = false; + protected String target; + protected Path bootclasspath; + protected Path extdirs; + protected Path compileClasspath; + protected Project project; + protected Location location; + protected boolean includeAntRuntime; + protected boolean includeJavaRuntime; + + protected File[] compileList; + protected static String lSep = System.getProperty("line.separator"); + protected Javac attributes; + + public void setJavac( Javac attributes ) { + this.attributes = attributes; + src = attributes.getSrcdir(); + destDir = attributes.getDestdir(); + encoding = attributes.getEncoding(); + debug = attributes.getDebug(); + optimize = attributes.getOptimize(); + deprecation = attributes.getDeprecation(); + depend = attributes.getDepend(); + verbose = attributes.getVerbose(); + target = attributes.getTarget(); + bootclasspath = attributes.getBootclasspath(); + extdirs = attributes.getExtdirs(); + compileList = attributes.getFileList(); + compileClasspath = attributes.getClasspath(); + project = attributes.getProject(); + location = attributes.getLocation(); + includeAntRuntime = attributes.getIncludeantruntime(); + includeJavaRuntime = attributes.getIncludejavaruntime(); + } + + public Javac getJavac() { + return attributes; + } + + /** + * Builds the compilation classpath. + * + */ + protected Path getCompileClasspath() { + Path classpath = new Path(project); + + // add dest dir to classpath so that previously compiled and + // untouched classes are on classpath + + if (destDir != null) { + classpath.setLocation(destDir); + } + + // Combine the build classpath with the system classpath, in an + // order determined by the value of build.classpath + + if (compileClasspath == null) { + if ( includeAntRuntime ) { + classpath.addExisting(Path.systemClasspath); + } + } else { + if ( includeAntRuntime ) { + classpath.addExisting(compileClasspath.concatSystemClasspath("last")); + } else { + classpath.addExisting(compileClasspath.concatSystemClasspath("ignore")); + } + } + + if (includeJavaRuntime) { + if (System.getProperty("java.vendor").toLowerCase().indexOf("microsoft") >= 0) { + // Pull in *.zip from packages directory + FileSet msZipFiles = new FileSet(); + msZipFiles.setDir(new File(System.getProperty("java.home") + File.separator + "Packages")); + msZipFiles.setIncludes("*.ZIP"); + classpath.addFileset(msZipFiles); + } + else if (Project.getJavaVersion() == Project.JAVA_1_1) { + classpath.addExisting(new Path(null, + System.getProperty("java.home") + + File.separator + "lib" + + File.separator + + "classes.zip")); + } else { + // JDK > 1.1 seems to set java.home to the JRE directory. + classpath.addExisting(new Path(null, + System.getProperty("java.home") + + File.separator + "lib" + + File.separator + "rt.jar")); + // Just keep the old version as well and let addExistingToPath + // sort it out. + classpath.addExisting(new Path(null, + System.getProperty("java.home") + + File.separator +"jre" + + File.separator + "lib" + + File.separator + "rt.jar")); + } + } + + return classpath; + } + + /** + * Does the command line argument processing common to classic and + * modern. + */ + protected Commandline setupJavacCommand() { + Commandline cmd = new Commandline(); + Path classpath = getCompileClasspath(); + + if (deprecation == true) { + cmd.createArgument().setValue("-deprecation"); + } + + if (destDir != null) { + cmd.createArgument().setValue("-d"); + cmd.createArgument().setFile(destDir); + } + + cmd.createArgument().setValue("-classpath"); + // Just add "sourcepath" to classpath ( for JDK1.1 ) + if (Project.getJavaVersion().startsWith("1.1")) { + cmd.createArgument().setValue(classpath.toString() + + File.pathSeparator + + src.toString()); + } else { + cmd.createArgument().setPath(classpath); + cmd.createArgument().setValue("-sourcepath"); + cmd.createArgument().setPath(src); + if (target != null) { + cmd.createArgument().setValue("-target"); + cmd.createArgument().setValue(target); + } + } + if (encoding != null) { + cmd.createArgument().setValue("-encoding"); + cmd.createArgument().setValue(encoding); + } + if (debug) { + cmd.createArgument().setValue("-g"); + } + if (optimize) { + cmd.createArgument().setValue("-O"); + } + if (bootclasspath != null) { + cmd.createArgument().setValue("-bootclasspath"); + cmd.createArgument().setPath(bootclasspath); + } + if (extdirs != null) { + cmd.createArgument().setValue("-extdirs"); + cmd.createArgument().setPath(extdirs); + } + + if (depend) { + if (Project.getJavaVersion().startsWith("1.1")) { + cmd.createArgument().setValue("-depend"); + } else if (Project.getJavaVersion().startsWith("1.2")) { + cmd.createArgument().setValue("-Xdepend"); + } else { + attributes.log("depend attribute is not supported by the modern compiler", + Project.MSG_WARN); + } + } + + if (verbose) { + cmd.createArgument().setValue("-verbose"); + } + + logAndAddFilesToCompile(cmd); + return cmd; + } + + /** + * Logs the compilation parameters, adds the files to compile and logs the + * &qout;niceSourceList" + */ + protected void logAndAddFilesToCompile(Commandline cmd) { + attributes.log("Compilation args: " + cmd.toString(), + Project.MSG_VERBOSE); + + StringBuffer niceSourceList = new StringBuffer("File"); + if (compileList.length != 1) { + niceSourceList.append("s"); + } + niceSourceList.append(" to be compiled:"); + + niceSourceList.append(lSep); + + for (int i=0; i < compileList.length; i++) { + String arg = compileList[i].getAbsolutePath(); + cmd.createArgument().setValue(arg); + niceSourceList.append(" " + arg + lSep); + } + + attributes.log(niceSourceList.toString(), Project.MSG_VERBOSE); + } + + /** + * Do the compile with the specified arguments. + * @param args - arguments to pass to process on command line + * @param firstFileName - index of the first source file in args + */ + protected int executeExternalCompile(String[] args, int firstFileName) { + String[] commandArray = null; + File tmpFile = null; + + try { + /* + * Many system have been reported to get into trouble with + * long command lines - no, not only Windows ;-). + * + * POSIX seems to define a lower limit of 4k, so use a temporary + * file if the total length of the command line exceeds this limit. + */ + if (Commandline.toString(args).length() > 4096) { + PrintWriter out = null; + try { + tmpFile = new File("jikes"+(new Random(System.currentTimeMillis())).nextLong()); + out = new PrintWriter(new FileWriter(tmpFile)); + for (int i = firstFileName; i < args.length; i++) { + out.println(args[i]); + } + out.flush(); + commandArray = new String[firstFileName+1]; + System.arraycopy(args, 0, commandArray, 0, firstFileName); + commandArray[firstFileName] = "@" + tmpFile.getAbsolutePath(); + } catch (IOException e) { + throw new BuildException("Error creating temporary file", e, location); + } finally { + if (out != null) { + try {out.close();} catch (Throwable t) {} + } + } + } else { + commandArray = args; + } + + try { + Execute exe = new Execute(new LogStreamHandler(attributes, + Project.MSG_INFO, + Project.MSG_WARN)); + exe.setAntRun(project); + exe.setWorkingDirectory(project.getBaseDir()); + exe.setCommandline(commandArray); + exe.execute(); + return exe.getExitValue(); + } catch (IOException e) { + throw new BuildException("Error running " + args[0] + + " compiler", e, location); + } + } finally { + if (tmpFile != null) { + tmpFile.delete(); + } + } + } + + /** + * Emulation of extdirs feature in java >= 1.2. + * This method adds all files in the given + * directories (but not in sub-directories!) to the classpath, + * so that you don't have to specify them all one by one. + * @param classpath - Path to append files to + */ + protected void addExtdirsToClasspath(Path classpath) { + if (extdirs == null) { + String extProp = System.getProperty("java.ext.dirs"); + if (extProp != null) { + extdirs = new Path(project, extProp); + } else { + return; + } + } + + String[] dirs = extdirs.list(); + for (int i=0; i. + */ + +package org.apache.tools.ant.taskdefs.compilers; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.taskdefs.LogOutputStream; +import org.apache.tools.ant.types.Commandline; + +import java.io.*; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +/** + * The implementation of the javac compiler for JDK 1.2 + * This is primarily a cut-and-paste from the original javac task before it + * was refactored. + * + * @author James Davidson duncan@x180.com + * @author Robin Green greenrd@hotmail.com + * @author Stefan Bodewig + * @author J D Glanville + */ +public class Javac12 extends DefaultCompilerAdapter { + + public boolean execute() throws BuildException { + attributes.log("Using classic compiler", Project.MSG_VERBOSE); + Commandline cmd = setupJavacCommand(); + + try { + // Create an instance of the compiler, redirecting output to + // the project log + OutputStream logstr = new LogOutputStream(attributes, Project.MSG_WARN); + Class c = Class.forName("sun.tools.javac.Main"); + Constructor cons = c.getConstructor(new Class[] { OutputStream.class, String.class }); + Object compiler = cons.newInstance(new Object[] { logstr, "javac" }); + + // Call the compile() method + Method compile = c.getMethod("compile", new Class [] { String[].class }); + Boolean ok = (Boolean)compile.invoke(compiler, new Object[] {cmd.getArguments()}); + return ok.booleanValue(); + } + catch (ClassNotFoundException ex) { + throw new BuildException("Cannot use classic compiler, as it is not available"+ + " A common solution is to set the environment variable"+ + " JAVA_HOME to your jdk directory.", location); + } + catch (Exception ex) { + if (ex instanceof BuildException) { + throw (BuildException) ex; + } else { + throw new BuildException("Error starting classic compiler: ", ex, location); + } + } + } +} diff --git a/src/main/org/apache/tools/ant/taskdefs/compilers/Javac13.java b/src/main/org/apache/tools/ant/taskdefs/compilers/Javac13.java new file mode 100644 index 000000000..a50713f95 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/compilers/Javac13.java @@ -0,0 +1,113 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.tools.ant.taskdefs.compilers; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.taskdefs.LogOutputStream; +import org.apache.tools.ant.types.Commandline; + +import java.lang.reflect.Method; +import java.io.*; + +/** + * The implementation of the javac compiler for JDK 1.3 + * This is primarily a cut-and-paste from the original javac task before it + * was refactored. + * + * @author James Davidson duncan@x180.com + * @author Robin Green greenrd@hotmail.com + * @author Stefan Bodewig + * @author J D Glanville + */ +public class Javac13 extends DefaultCompilerAdapter { + + /** + * Integer returned by the "Modern" jdk1.3 compiler to indicate success. + */ + private static final int MODERN_COMPILER_SUCCESS = 0; + + public boolean execute() throws BuildException { + attributes.log("Using modern compiler", Project.MSG_VERBOSE); + Commandline cmd = setupJavacCommand(); + + PrintStream err = System.err; + PrintStream out = System.out; + + // Use reflection to be able to build on all JDKs >= 1.1: + try { + PrintStream logstr = + new PrintStream(new LogOutputStream(attributes, Project.MSG_WARN)); + System.setOut(logstr); + System.setErr(logstr); + Class c = Class.forName ("com.sun.tools.javac.Main"); + Object compiler = c.newInstance (); + Method compile = c.getMethod ("compile", + new Class [] {(new String [] {}).getClass ()}); + int result = ((Integer) compile.invoke + (compiler, new Object[] {cmd.getArguments()})) .intValue (); + return (result == MODERN_COMPILER_SUCCESS); + } catch (Exception ex) { + if (ex instanceof BuildException) { + throw (BuildException) ex; + } else { + throw new BuildException("Error starting modern compiler", ex, location); + } + } finally { + System.setErr(err); + System.setOut(out); + } + } +} diff --git a/src/main/org/apache/tools/ant/taskdefs/compilers/Jikes.java b/src/main/org/apache/tools/ant/taskdefs/compilers/Jikes.java new file mode 100644 index 000000000..fbc4e1266 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/compilers/Jikes.java @@ -0,0 +1,205 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.tools.ant.taskdefs.compilers; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.*; + +/** + * The implementation of the jikes compiler. + * This is primarily a cut-and-paste from the original javac task before it + * was refactored. + * + * @author James Davidson duncan@x180.com + * @author Robin Green greenrd@hotmail.com + * @author Stefan Bodewig + * @author J D Glanville + */ +public class Jikes extends DefaultCompilerAdapter { + + /** + * Performs a compile using the Jikes compiler from IBM.. + * Mostly of this code is identical to doClassicCompile() + * However, it does not support all options like + * bootclasspath, extdirs, deprecation and so on, because + * there is no option in jikes and I don't understand + * what they should do. + * + * It has been successfully tested with jikes >1.10 + * + * @author skanthak@muehlheim.de + */ + public boolean execute() throws BuildException { + attributes.log("Using jikes compiler", Project.MSG_VERBOSE); + + Path classpath = new Path(project); + + // Jikes doesn't support bootclasspath dir (-bootclasspath) + // so we'll emulate it for compatibility and convenience. + if (bootclasspath != null) { + classpath.append(bootclasspath); + } + + // Jikes doesn't support an extension dir (-extdir) + // so we'll emulate it for compatibility and convenience. + addExtdirsToClasspath(classpath); + + if ( (bootclasspath == null) || (bootclasspath.size() == 0) ) { + // no bootclasspath, therefore, get one from the java runtime + includeJavaRuntime = true; + } else { + // there is a bootclasspath stated. By default, the + // includeJavaRuntime is false. If the user has stated a + // bootclasspath and said to include the java runtime, it's on + // their head! + } + classpath.append(getCompileClasspath()); + + // Jikes has no option for source-path so we + // will add it to classpath. + classpath.append(src); + + // if the user has set JIKESPATH we should add the contents as well + String jikesPath = System.getProperty("jikes.class.path"); + if (jikesPath != null) { + classpath.append(new Path(project, jikesPath)); + } + + Commandline cmd = new Commandline(); + cmd.setExecutable("jikes"); + + if (deprecation == true) + cmd.createArgument().setValue("-deprecation"); + + if (destDir != null) { + cmd.createArgument().setValue("-d"); + cmd.createArgument().setFile(destDir); + } + + cmd.createArgument().setValue("-classpath"); + cmd.createArgument().setPath(classpath); + + if (encoding != null) { + cmd.createArgument().setValue("-encoding"); + cmd.createArgument().setValue(encoding); + } + if (debug) { + cmd.createArgument().setValue("-g"); + } + if (optimize) { + cmd.createArgument().setValue("-O"); + } + if (verbose) { + cmd.createArgument().setValue("-verbose"); + } + if (depend) { + cmd.createArgument().setValue("-depend"); + } + /** + * XXX + * Perhaps we shouldn't use properties for these + * three options (emacs mode, warnings and pedantic), + * but include it in the javac directive? + */ + + /** + * Jikes has the nice feature to print error + * messages in a form readable by emacs, so + * that emacs can directly set the cursor + * to the place, where the error occured. + */ + String emacsProperty = project.getProperty("build.compiler.emacs"); + if (emacsProperty != null && Project.toBoolean(emacsProperty)) { + cmd.createArgument().setValue("+E"); + } + + /** + * Jikes issues more warnings that javac, for + * example, when you have files in your classpath + * that don't exist. As this is often the case, these + * warning can be pretty annoying. + */ + String warningsProperty = project.getProperty("build.compiler.warnings"); + if (warningsProperty != null && !Project.toBoolean(warningsProperty)) { + cmd.createArgument().setValue("-nowarn"); + } + + /** + * Jikes can issue pedantic warnings. + */ + String pedanticProperty = project.getProperty("build.compiler.pedantic"); + if (pedanticProperty != null && Project.toBoolean(pedanticProperty)) { + cmd.createArgument().setValue("+P"); + } + + /** + * Jikes supports something it calls "full dependency + * checking", see the jikes documentation for differences + * between -depend and +F. + */ + String fullDependProperty = project.getProperty("build.compiler.fulldepend"); + if (fullDependProperty != null && Project.toBoolean(fullDependProperty)) { + cmd.createArgument().setValue("+F"); + } + + int firstFileName = cmd.size(); + logAndAddFilesToCompile(cmd); + + return executeExternalCompile(cmd.getCommandline(), firstFileName) == 0; + } + + +} diff --git a/src/main/org/apache/tools/ant/taskdefs/compilers/Jvc.java b/src/main/org/apache/tools/ant/taskdefs/compilers/Jvc.java new file mode 100644 index 000000000..415b3fb58 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/compilers/Jvc.java @@ -0,0 +1,134 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.tools.ant.taskdefs.compilers; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.*; + +/** + * The implementation of the jvc compiler from microsoft. + * This is primarily a cut-and-paste from the original javac task before it + * was refactored. + * + * @author James Davidson duncan@x180.com + * @author Robin Green greenrd@hotmail.com + * @author Stefan Bodewig + * @author J D Glanville + */ +public class Jvc extends DefaultCompilerAdapter { + + public boolean execute() throws BuildException { + attributes.log("Using jvc compiler", Project.MSG_VERBOSE); + + Path classpath = new Path(project); + + // jvc doesn't support bootclasspath dir (-bootclasspath) + // so we'll emulate it for compatibility and convenience. + if (bootclasspath != null) { + classpath.append(bootclasspath); + } + + // jvc doesn't support an extension dir (-extdir) + // so we'll emulate it for compatibility and convenience. + addExtdirsToClasspath(classpath); + + if ( (bootclasspath == null) || (bootclasspath.size() == 0) ) { + // no bootclasspath, therefore, get one from the java runtime + includeJavaRuntime = true; + } else { + // there is a bootclasspath stated. By default, the + // includeJavaRuntime is false. If the user has stated a + // bootclasspath and said to include the java runtime, it's on + // their head! + } + classpath.append(getCompileClasspath()); + + // jvc has no option for source-path so we + // will add it to classpath. + classpath.append(src); + + Commandline cmd = new Commandline(); + cmd.setExecutable("jvc"); + + if (destDir != null) { + cmd.createArgument().setValue("/d"); + cmd.createArgument().setFile(destDir); + } + + // Add the Classpath before the "internal" one. + cmd.createArgument().setValue("/cp:p"); + cmd.createArgument().setPath(classpath); + + // Enable MS-Extensions and ... + cmd.createArgument().setValue("/x-"); + // ... do not display a Message about this. + cmd.createArgument().setValue("/nomessage"); + // Do not display Logo + cmd.createArgument().setValue("/nologo"); + + if (debug) { + cmd.createArgument().setValue("/g"); + } + if (optimize) { + cmd.createArgument().setValue("/O"); + } + + int firstFileName = cmd.size(); + logAndAddFilesToCompile(cmd); + + return executeExternalCompile(cmd.getCommandline(), firstFileName) == 0; + } +} diff --git a/src/main/org/apache/tools/ant/types/Path.java b/src/main/org/apache/tools/ant/types/Path.java index f9a27a4c3..6241cf198 100644 --- a/src/main/org/apache/tools/ant/types/Path.java +++ b/src/main/org/apache/tools/ant/types/Path.java @@ -467,15 +467,25 @@ public class Path extends DataType implements Cloneable { } /** - * Concatenates the system class path in the order specified - * by the ${build.sysclasspath} property. + * Concatenates the system class path in the order specified by + * the ${build.sysclasspath} property - using "last" as + * default value. */ public Path concatSystemClasspath() { + return concatSystemClasspath("last"); + } + + /** + * Concatenates the system class path in the order specified by + * the ${build.sysclasspath} property - using the supplied value + * if ${build.sysclasspath} has not been set. + */ + public Path concatSystemClasspath(String defValue) { Path result = new Path(project); String order = project.getProperty("build.sysclasspath"); - if (order == null) order="last"; + if (order == null) order=defValue; if (order.equals("only")) { // only: the developer knows what (s)he is doing