Permalink
Browse files

API for embedding incremental compilation

  • Loading branch information...
2 parents 8594e44 + 03ba47c commit 4a53ace752e2ce280f26d7d23b3aca72eb764997 @harrah committed Apr 18, 2012
@@ -0,0 +1,29 @@
+package xsbti.compile;
+
+/**
+* Configures modifications to the classpath based on the Scala instance used for compilation.
+* This is typically used for the Scala compiler only and all values set to false for the Java compiler.
+*/
+public interface ClasspathOptions
+{
+ /** If true, includes the Scala library on the boot classpath. This should usually be true.*/
+ boolean bootLibrary();
+
+ /** If true, includes the Scala compiler on the standard classpath.
+ * This is typically false and is instead managed by the build tool or environment.
+ */
+ boolean compiler();
+
+ /** If true, includes extra jars from the Scala instance on the standard classpath.
+ * This is typically false and is instead managed by the build tool or environment.
+ */
+ boolean extra();
+
+ /** If true, automatically configures the boot classpath. This should usually be true.*/
+ boolean autoBoot();
+
+ /** If true, the Scala library jar is filtered from the standard classpath.
+ * This should usually be true because the library should be included on the boot classpath of the Scala compiler and not the standard classpath.
+ */
+ boolean filterLibrary();
+}
@@ -0,0 +1,34 @@
+package xsbti.compile;
+
+/**
+* Defines the order in which Scala and Java sources are compiled when compiling a set of sources with both Java and Scala sources.
+* This setting has no effect if only Java sources or only Scala sources are being compiled.
+* It is generally more efficient to use JavaThenScala or ScalaThenJava when mixed compilation is not required.
+*/
+public enum CompileOrder
+{
+ /**
+ * Allows Scala sources to depend on Java sources and allows Java sources to depend on Scala sources.
+ *
+ * In this mode, both Java and Scala sources are passed to the Scala compiler, which generates class files for the Scala sources.
+ * Then, Java sources are passed to the Java compiler, which generates class files for the Java sources.
+ * The Scala classes compiled in the first step are included on the classpath to the Java compiler.
+ */
+ Mixed,
+ /**
+ * Allows Scala sources to depend on the Java sources in the compilation, but does not allow Java sources to depend on Scala sources.
+ *
+ * In this mode, both Java and Scala sources are passed to the Scala compiler, which generates class files for the Scala sources.
+ * Then, Java sources are passed to the Java compiler, which generates class files for the Java sources.
+ * The Scala classes compiled in the first step are included on the classpath to the Java compiler.
+ */
+ JavaThenScala,
+ /**
+ * Allows Java sources to depend on the Scala sources in the compilation, but does not allow Scala sources to depend on Java sources.
+ *
+ * In this mode, both Java and Scala sources are passed to the Scala compiler, which generates class files for the Scala sources.
+ * Then, Java sources are passed to the Java compiler, which generates class files for the Java sources.
+ * The Scala classes compiled in the first step are included on the classpath to the Java compiler.
+ */
+ ScalaThenJava;
+}
@@ -0,0 +1,8 @@
+package xsbti.compile;
+
+public interface Compilers<ScalaCompiler>
+{
+ JavaCompiler javac();
+ // should be cached by client if desired
+ ScalaCompiler scalac();
+}
@@ -0,0 +1,14 @@
+package xsbti.compile;
+
+import java.io.File;
+
+/**
+* Determines if an entry on a classpath contains a class.
+*/
+public interface DefinesClass
+{
+ /**
+ * Returns true if the classpath entry contains the requested class.
+ */
+ boolean apply(String className);
+}
@@ -0,0 +1,60 @@
+package xsbti.compile;
+
+import xsbti.Logger;
+import java.io.File;
+
+/*
+* This API is subject to change.
+*
+* It is the client's responsibility to:
+* 1. Manage class loaders. Usually the client will want to:
+* i. Keep the class loader used by the ScalaInstance warm.
+* ii. Keep the class loader of the incremental recompilation classes (xsbti.compile) warm.
+* iii. Share the class loader for Scala classes between the incremental compiler implementation and the ScalaInstance where possible (must be binary compatible)
+* 2. Manage the compiler interface jar. The interface must be compiled against the exact Scala version used for compilation and a compatible Java version.
+* 3. Manage compilation order between different compilations.
+* i. Execute a compilation for each dependency, obtaining an Analysis for each.
+* ii. Provide the Analysis from previous compilations to dependent compilations in the analysis map.
+* 4. Provide an implementation of JavaCompiler for compiling Java sources.
+* 5. Define a function that determines if a classpath entry contains a class (Setup.definesClass).
+* i. This is provided by the client so that the client can cache this information across compilations when compiling multiple sets of sources.
+* ii. The cache should be cleared for each new compilation run or else recompilation will not properly account for changes to the classpath.
+* 6. Provide a cache directory.
+* i. This directory is used by IncrementalCompiler to persist data between compilations.
+* ii. It should be a different directory for each set of sources being compiled.
+* 7. Manage parallel execution.
+* i. Each compilation may be performed in a different thread as long as the dependencies have been compiled already.
+* ii. Implementations of all types should be immutable and arrays treated as immutable.
+* 8. Ensure general invariants:
+* i. The implementations of all types are immutable, except for the already discussed Setup.definesClass.
+* ii. Arrays are treated as immutable.
+* iii. No value is ever null.
+*/
+public interface IncrementalCompiler<Analysis, ScalaCompiler>
+{
+ /**
+ * Performs an incremental compilation as configured by `in`.
+ * The returned Analysis should be provided to compilations depending on the classes from this compilation.
+ */
+ Analysis compile(Inputs<Analysis, ScalaCompiler> in, Logger log);
+
+ /**
+ * Creates a compiler instance that can be used by the `compile` method.
+ *
+ * @param instance The Scala version to use
+ * @param interfaceJar The compiler interface jar compiled for the Scala version being used
+ * @param options Configures how arguments to the underlying Scala compiler will be built.
+ */
+ ScalaCompiler newScalaCompiler(ScalaInstance instance, File interfaceJar, ClasspathOptions options, Logger log);
+
+ /**
+ * Compiles the source interface for a Scala version. The resulting jar can then be used by the `newScalaCompiler` method
+ * to create a ScalaCompiler for incremental compilation. It is the client's responsibility to manage compiled jars for
+ * different Scala versions.
+ *
+ * @param sourceJar The jar file containing the compiler interface sources. These are published as sbt's compiler-interface-src module.
+ * @param targetJar Where to create the output jar file containing the compiled classes.
+ * @param instance The ScalaInstance to compile the compiler interface for.
+ * @param log The logger to use during compilation. */
+ void compileInterfaceJar(File sourceJar, File targetJar, ScalaInstance instance, Logger log);
+}
@@ -0,0 +1,14 @@
+package xsbti.compile;
+
+/** Configures a single compilation of a single set of sources.*/
+public interface Inputs<Analysis,ScalaCompiler>
+{
+ /** The Scala and Java compilers to use for compilation.*/
+ Compilers<ScalaCompiler> compilers();
+
+ /** Standard compilation options, such as the sources and classpath to use. */
+ Options options();
+
+ /** Configures incremental compilation.*/
+ Setup<Analysis> setup();
+}
@@ -0,0 +1,15 @@
+package xsbti.compile;
+
+import java.io.File;
+import xsbti.Logger;
+
+/**
+* Interface to a Java compiler.
+*/
+public interface JavaCompiler
+{
+ /** Compiles Java sources using the provided classpath, output directory, and additional options.
+ * If supported, the number of reported errors should be limited to `maximumErrors`.
+ * Output should be sent to the provided logger.*/
+ void compile(File[] sources, File[] classpath, File outputDirectory, String[] options, int maximumErrors, Logger log);
+}
@@ -0,0 +1,33 @@
+package xsbti.compile;
+
+import java.io.File;
+
+/** Standard compilation options.*/
+public interface Options
+{
+ /** The classpath to use for compilation.
+ * This will be modified according to the ClasspathOptions used to configure the ScalaCompiler.*/
+ File[] classpath();
+
+ /** All sources that should be recompiled.
+ * This should include Scala and Java sources, which are identified by their extension. */
+ File[] sources();
+
+ /** The directory where class files should be generated.
+ * Incremental compilation will manage the class files in this directory.
+ * In particular, outdated class files will be deleted before compilation.
+ * It is important that this directory is exclusively used for one set of sources. */
+ File classesDirectory();
+
+ /** The options to pass to the Scala compiler other than the sources and classpath to use. */
+ String[] options();
+
+ /** The options to pass to the Java compiler other than the sources and classpath to use. */
+ String[] javacOptions();
+
+ /** The maximum number of errors that the Scala compiler should report.*/
+ int maxErrors();
+
+ /** Controls the order in which Java and Scala sources are compiled.*/
+ CompileOrder order();
+}
@@ -0,0 +1,34 @@
+package xsbti.compile;
+
+import java.io.File;
+
+/**
+* Defines Scala instance, which is a reference version String, a unique version String, a set of jars, and a class loader for a Scala version.
+*
+* Note that in this API a 'jar' can actually be any valid classpath entry.
+*/
+public interface ScalaInstance
+{
+ /** The version used to refer to this Scala version.
+ * It need not be unique and can be a dynamic version like 2.10.0-SNAPSHOT.
+ */
+ String version();
+
+ /** A class loader providing access to the classes and resources in the library and compiler jars. */
+ ClassLoader loader();
+
+ /** The library jar file.*/
+ File libraryJar();
+
+ /** The compiler jar file.*/
+ File compilerJar();
+
+ /** Jars provided by this Scala instance other than the compiler and library jars. */
+ File[] extraJars();
+
+ /** All jar files provided by this Scala instance.*/
+ File[] jars();
+
+ /** The unique identifier for this Scala instance. An implementation should usually obtain this from the compiler.properties file in the compiler jar. */
+ String actualVersion();
+}
@@ -0,0 +1,24 @@
+package xsbti.compile;
+
+import java.io.File;
+import xsbti.Maybe;
+
+/** Configures incremental recompilation. */
+public interface Setup<Analysis>
+{
+ /** Provides the Analysis for the given classpath entry.*/
+ Maybe<Analysis> analysisMap(File file);
+
+ /** Provides a function to determine if classpath entry `file` contains a given class.
+ * The returned function should generally cache information about `file`, such as the list of entries in a jar.
+ */
+ DefinesClass definesClass(File file);
+
+ /** If true, no sources are actually compiled and the Analysis from the previous compilation is returned.*/
+ boolean skip();
+
+ /** The directory used to cache information across compilations.
+ * This directory can be removed to force a full recompilation.
+ * The directory should be unique and not shared between compilations. */
+ File cacheDirectory();
+}

0 comments on commit 4a53ace

Please sign in to comment.