Mercurial > hg > truffle
diff graal/com.oracle.max.base/src/com/sun/max/ide/ToolChain.java @ 3733:e233f5660da4
Added Java files from Maxine project.
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Sat, 17 Dec 2011 19:59:18 +0100 |
parents | |
children | bc8527f3071c |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.base/src/com/sun/max/ide/ToolChain.java Sat Dec 17 19:59:18 2011 +0100 @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.sun.max.ide; + +import java.io.*; +import java.lang.reflect.*; +import java.net.*; +import java.util.*; + +import javax.tools.*; +import javax.tools.JavaCompiler.*; + +import com.sun.max.program.*; + +/** + * Provides an interface for invoking a Java source compiler (e.g. javac) and a C header and stub generator (i.e. + * javah). The Java source compiler used is determined the <a + * href="http://java.sun.com/javase/6/docs/api/java/util/ServiceLoader.html">service provider mechanism</a>. For + * example, if you want to use the Eclipse batch compiler, then simply place the stand alone ecj.jar JAR file on the + * classpath. + */ +public final class ToolChain { + + private ToolChain() { + } + + private static JavaCompiler javaCompiler; + + private static JavaCompiler javaCompiler() { + if (javaCompiler == null) { + final Iterator<JavaCompiler> iterator = ServiceLoader.load(JavaCompiler.class).iterator(); + if (iterator.hasNext()) { + javaCompiler = iterator.next(); + } else { + javaCompiler = ToolProvider.getSystemJavaCompiler(); + } + ProgramError.check(javaCompiler != null, "Cannot find a Java compiler"); + } + return javaCompiler; + } + + /** + * Compiles the source for a given class. The location of the source file to be compiled and the directory to which + * the output class files are to be written are determined by the current {@link JavaProject} context. + * <p> + * The supported {@code options} are: + * <p> + * + * <pre> + * -noinlinejsr implement {@code finally} clauses using the {@link Bytecode#JSR} and {@link Bytecode#RET} bytecodes + * </pre> + * + * + * @param projClass a class denoting a project (i.e. any class in the project) + * @param className the name of the class to be compiled + * @param options options for modifying the compilation + * @return true if the compilation succeeded without any errors, false otherwise + */ + public static boolean compile(Class projClass, String className, String... options) { + return compile(projClass, new String[] {className}, options); + } + + /** + * Compiles the source for one or more given classes. The location of the source files to be compiled and the + * directory to which the output class files are to be written are determined by a given project + * context. + * <p> + * The supported {@code options} are: + * <p> + * + * <pre> + * -noinlinejsr implement {@code finally} clauses using the {@link Bytecode#JSR} and {@link Bytecode#RET} bytecodes + * </pre> + * + * + * @param projClass a class denoting a project (i.e. any class in the project) + * @param className the name of the class to be compiled + * @param options options for modifying the compilation + * @return true if the compilation succeeded without any errors, false otherwise + */ + public static boolean compile(Class projClass, String[] classNames, String... options) { + + final Classpath classPath = JavaProject.getClassPath(projClass, true); + final Classpath sourcePath = JavaProject.getSourcePath(projClass, true); + final String outputDirectory = classPath.entries().get(0).toString(); + + final ArrayList<File> sourceFiles = new ArrayList<File>(classNames.length); + for (String className : classNames) { + final String sourceFilePathSuffix = className.replace('.', File.separatorChar) + ".java"; + final File sourceFile = sourcePath.findFile(sourceFilePathSuffix); + if (sourceFile == null) { + ProgramWarning.message("Could not find source file for " + className); + return false; + } + sourceFiles.add(sourceFile); + } + + final JavaCompiler compiler = javaCompiler(); + final String compilerName = compiler.getClass().getName(); + final List<String> opts = new ArrayList<String>(Arrays.asList(new String[] {"-cp", classPath.toString(), "-d", outputDirectory})); + if (compilerName.equals("com.sun.tools.javac.api.JavacTool")) { + opts.add("-cp"); + opts.add(classPath.toString()); + opts.add("-d"); + opts.add(outputDirectory); + for (String option : options) { + if (option.equals("-noinlinejsr")) { + opts.add("-source"); + opts.add("1.4"); + opts.add("-target"); + opts.add("1.4"); + opts.add("-XDjsrlimit=0"); + } else { + throw new IllegalArgumentException("Unsupported compiler option " + option); + } + } + } else if (compiler.getClass().getName().equals("org.eclipse.jdt.internal.compiler.tool.EclipseCompiler")) { + opts.add("-cp"); + opts.add(classPath.toString()); + opts.add("-d"); + opts.add(outputDirectory); + opts.add("-noExit"); + boolean inlineJSR = true; + for (String option : options) { + if (option.equals("-noinlinejsr")) { + inlineJSR = false; + } else { + throw new IllegalArgumentException("Unsupported compiler option " + option); + } + } + if (inlineJSR) { + opts.add("-inlineJSR"); + } else { + opts.add("-source"); + opts.add("1.4"); + opts.add("-target"); + opts.add("1.4"); + } + } else { + ProgramWarning.message("Unknown Java compiler may not accept same command line options as javac: " + compilerName); + opts.add("-cp"); + opts.add(classPath.toString()); + opts.add("-d"); + opts.add(outputDirectory); + } + + final DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>(); + final StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null); + final Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(sourceFiles); + final CompilationTask task = compiler.getTask(null, fileManager, diagnostics, opts, null, compilationUnits); + final boolean result = task.call(); + final Set<String> reportedDiagnostics = new HashSet<String>(); + for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) { + final String message = diagnostic.getMessage(Locale.getDefault()); + if (!reportedDiagnostics.contains(message)) { + reportedDiagnostics.add(message); + if (!message.contains("is Sun proprietary API and may be removed in a future release")) { + System.err.println(message); + } + } + } + try { + fileManager.close(); + } catch (IOException e) { + ProgramWarning.message("Error closing file manager: " + e); + } + return result; + } + + private static Method javahMainMethod; + + private static Method javah() { + if (javahMainMethod == null) { + Class<?> javahMainClass = null; + try { + // On the Apple JDKs, there is no tools.jar: all the tools are in classes.jar + javahMainClass = Class.forName("com.sun.tools.javah.Main"); + } catch (ClassNotFoundException classNotFoundException) { + // This is expected on non-Apple JDKs + final ClassLoader systemToolClassLoader = ToolProvider.getSystemToolClassLoader(); + ProgramError.check(systemToolClassLoader != null, "Cannot find the standard system tools class loader"); + try { + javahMainClass = Class.forName("com.sun.tools.javah.Main", true, systemToolClassLoader); + final URLClassLoader urlClassLoader = (URLClassLoader) javahMainClass.getClassLoader(); + updateJavaClassPath(urlClassLoader); + } catch (Exception exception) { + ProgramWarning.message("Cannot find or initialize javah: " + exception); + } + } + try { + if (javahMainClass != null) { + javahMainMethod = javahMainClass.getDeclaredMethod("main", String[].class); + } + } catch (Exception exception) { + ProgramWarning.message("Cannot find or initialize javah: " + exception); + } + } + return javahMainMethod; + } + + /** + * This hack is necessary as javah uses a doclet to do its actual work. The doclet class is found by creating a URL class loader + * from the system property "java.class.path" which does not include the path to tools.jar for + * standard JDK installations. + */ + private static void updateJavaClassPath(final URLClassLoader urlClassLoader) { + String javaClassPath = System.getProperty("java.class.path", "."); + for (URL url : urlClassLoader.getURLs()) { + final String path = url.getPath(); + if (path != null && !path.isEmpty()) { + final File file = new File(path); + if (file.exists()) { + javaClassPath += File.pathSeparator + file.getAbsolutePath(); + } + } + } + System.setProperty("java.class.path", javaClassPath); + } + + public static boolean javah(String[] args) { + try { + javah().invoke(null, (Object) args); + return true; + } catch (InvocationTargetException e) { + ProgramWarning.message("Error invoking javah: " + e.getTargetException()); + } catch (Exception e) { + ProgramWarning.message("Error invoking javah: " + e); + } + return false; + } + + private static Method javapMainMethod; + + private static Method javap() { + if (javapMainMethod == null) { + Class<?> javapMainClass = null; + try { + // On the Apple JDKs, there is no tools.jar: all the tools are in classes.jar + javapMainClass = Class.forName("sun.tools.javap.Main"); + } catch (ClassNotFoundException classNotFoundException) { + // This is expected on non-Apple JDKs + final ClassLoader systemToolClassLoader = ToolProvider.getSystemToolClassLoader(); + ProgramError.check(systemToolClassLoader != null, "Cannot find the standard system tools class loader"); + try { + javapMainClass = Class.forName("sun.tools.javap.Main", true, systemToolClassLoader); + } catch (Exception exception) { + ProgramWarning.message("Cannot find or initialize javap: " + exception); + } + } + try { + if (javapMainClass != null) { + javapMainMethod = javapMainClass.getDeclaredMethod("main", String[].class); + } + } catch (Exception exception) { + ProgramWarning.message("Cannot find or initialize javap: " + exception); + } + } + return javapMainMethod; + } + + public static boolean javap(String[] args) { + try { + javap().invoke(null, (Object) args); + return true; + } catch (InvocationTargetException e) { + ProgramWarning.message("Error invoking javap: " + e.getTargetException()); + } catch (Exception e) { + ProgramWarning.message("Error invoking javap: " + e); + } + return false; + } +}