Skip to content

sbt-dotty: Rework classpath and ScalaInstance handling, fix minimum sbt version check, release 0.3.0 #5835

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Feb 13, 2019
111 changes: 23 additions & 88 deletions project/Build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import xerial.sbt.pack.PackPlugin
import xerial.sbt.pack.PackPlugin.autoImport._

import dotty.tools.sbtplugin.DottyPlugin.autoImport._
import dotty.tools.sbtplugin.DottyPlugin.makeScalaInstance
import dotty.tools.sbtplugin.DottyIDEPlugin.{ installCodeExtension, prepareCommand, runProcess }
import dotty.tools.sbtplugin.DottyIDEPlugin.autoImport._

Expand All @@ -27,20 +28,11 @@ import sbtbuildinfo.BuildInfoPlugin.autoImport._

import scala.util.Properties.isJavaAtLeast

/* In sbt 0.13 the Build trait would expose all vals to the shell, where you
* can use them in "set a := b" like expressions. This re-exposes them.
*/
object ExposedValues extends AutoPlugin {
object autoImport {
val bootstrapFromPublishedJars = Build.bootstrapFromPublishedJars
}
}

object Build {
val scalacVersion = "2.12.8"

val baseVersion = "0.13.0"
val baseSbtDottyVersion = "0.2.7"
val baseSbtDottyVersion = "0.3.1"

// Versions used by the vscode extension to create a new project
// This should be the latest published releases.
Expand Down Expand Up @@ -100,8 +92,6 @@ object Build {
// Shorthand for compiling a docs site
val dottydoc = inputKey[Unit]("run dottydoc")

val bootstrapFromPublishedJars = settingKey[Boolean]("If true, bootstrap dotty from published non-bootstrapped dotty")

// Only available in vscode-dotty
val unpublish = taskKey[Unit]("Unpublish a package")

Expand Down Expand Up @@ -129,9 +119,6 @@ object Build {

javacOptions in (Compile, compile) ++= Seq("-Xlint:unchecked", "-Xlint:deprecation"),

// Change this to true if you want to bootstrap using a published non-bootstrapped compiler
bootstrapFromPublishedJars := false,

// Override `runCode` from sbt-dotty to use the language-server and
// vscode extension from the source repository of dotty instead of a
// published version.
Expand Down Expand Up @@ -220,20 +207,6 @@ object Build {
// Use the same name as the non-bootstrapped projects for the artifacts
moduleName ~= { _.stripSuffix("-bootstrapped") },

// Prevent sbt from setting the Scala bootclasspath, otherwise it will
// contain `scalaInstance.value.libraryJar` which in our case is the
// non-bootstrapped dotty-library that will then take priority over
// the bootstrapped dotty-library on the classpath or sourcepath.
classpathOptions ~= (_.withAutoBoot(false)),
// ... but when running under Java 8, we still need a Scala bootclasspath that contains the JVM bootclasspath,
// otherwise sbt incremental compilation breaks.
scalacOptions ++= {
if (isJavaAtLeast("9"))
Seq()
else
Seq("-bootclasspath", sys.props("sun.boot.class.path"))
},

// Enforce that the only Scala 2 classfiles we unpickle come from scala-library
/*
scalacOptions ++= {
Expand All @@ -251,64 +224,31 @@ object Build {
// ...but scala-library is
libraryDependencies += "org.scala-lang" % "scala-library" % scalacVersion,

ivyConfigurations ++= {
if (bootstrapFromPublishedJars.value)
Seq(Configurations.ScalaTool)
else
Seq()
},
libraryDependencies ++= {
if (bootstrapFromPublishedJars.value)
Seq(
dottyOrganization %% "dotty-library" % dottyNonBootstrappedVersion % Configurations.ScalaTool.name,
dottyOrganization %% "dotty-compiler" % dottyNonBootstrappedVersion % Configurations.ScalaTool.name
).map(_.withDottyCompat(scalaVersion.value))
else
Seq()
},

// Compile using the non-bootstrapped and non-published dotty
managedScalaInstance := false,
scalaInstance := {
import sbt.internal.inc.ScalaInstance
import sbt.internal.inc.classpath.ClasspathUtilities

val updateReport = update.value
var libraryJar = packageBin.in(`dotty-library`, Compile).value
var compilerJar = packageBin.in(`dotty-compiler`, Compile).value

if (bootstrapFromPublishedJars.value) {
val jars = updateReport.select(
configuration = configurationFilter(Configurations.ScalaTool.name),
module = moduleFilter(),
artifact = artifactFilter(extension = "jar")
)
libraryJar = jars.find(_.getName.startsWith("dotty-library_2.12")).get
compilerJar = jars.find(_.getName.startsWith("dotty-compiler_2.12")).get
}

// All dotty-doc's and compiler's dependencies except the library.
// (we get the compiler's dependencies because dottydoc depends on the compiler)
val otherDependencies = {
val excluded = Set("dotty-library", "dotty-compiler")
fullClasspath.in(`dotty-doc`, Compile).value
.filterNot(_.get(artifact.key).exists(a => excluded.contains(a.name)))
.map(_.data)
}

val allJars = libraryJar :: compilerJar :: otherDependencies.toList
val classLoader = state.value.classLoaderCache(allJars)
new ScalaInstance(
// TODO: Here we use the output class directories directly, this might impact
// performance when running the compiler (especially on Windows where file
// IO is slow). We should benchmark whether using jars is actually faster
// in practice (especially on our CI), this could be done using
// `exportJars := true`.
val all = fullClasspath.in(`dotty-doc`, Compile).value
def getArtifact(name: String): File =
all.find(_.get(artifact.key).exists(_.name == name))
.getOrElse(throw new MessageOnlyException(s"Artifact for $name not found in $all"))
.data

val scalaLibrary = getArtifact("scala-library")
val dottyLibrary = getArtifact("dotty-library")
val compiler = getArtifact("dotty-compiler")

makeScalaInstance(
state.value,
scalaVersion.value,
classLoader,
ClasspathUtilities.rootLoader, // FIXME: Should be a class loader which only includes the dotty-lib
// See: https://github.com/sbt/zinc/commit/9397b6aaf94ac3cfab386e3abd11c0ef9c2ceaff#diff-ea135f2f26f43e40ff045089da221e1e
// Should not matter, as it addresses an issue with `sbt run` that
// only occur when `(fork in run) := false`
libraryJar,
compilerJar,
allJars.toArray,
None
scalaLibrary,
dottyLibrary,
compiler,
all.map(_.data)
)
}
)
Expand All @@ -334,11 +274,6 @@ object Build {

/** Projects -------------------------------------------------------------- */

// Needed because the dotty project aggregates dotty-sbt-bridge but dotty-sbt-bridge
// currently refers to dotty in its scripted task and "aggregate" does not take by-name
// parameters: https://github.com/sbt/sbt/issues/2200
lazy val dottySbtBridgeRef = LocalProject("dotty-sbt-bridge")

// The root project:
// - aggregates other projects so that "compile", "test", etc are run on all projects at once.
// - publishes its own empty artifact "dotty" that depends on "dotty-library" and "dotty-compiler",
Expand Down
Loading