From 62a0cb2d6fb083e019ab658723c58d456382f2f9 Mon Sep 17 00:00:00 2001 From: jvican Date: Mon, 20 Nov 2017 21:24:21 +0100 Subject: [PATCH 01/20] Add headers to missing files --- .../test/scala/sbt/internal/inc/BatchScriptRunner.scala | 7 +++++++ .../src/test/scala/sbt/internal/inc/ScriptedTests.scala | 7 +++++++ .../scala/sbt/internal/inc/caching/ClasspathCache.scala | 7 +++++++ 3 files changed, 21 insertions(+) diff --git a/internal/zinc-scripted/src/test/scala/sbt/internal/inc/BatchScriptRunner.scala b/internal/zinc-scripted/src/test/scala/sbt/internal/inc/BatchScriptRunner.scala index 5f36d99a67..e1159169af 100644 --- a/internal/zinc-scripted/src/test/scala/sbt/internal/inc/BatchScriptRunner.scala +++ b/internal/zinc-scripted/src/test/scala/sbt/internal/inc/BatchScriptRunner.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt.internal.inc import org.scalatest.exceptions.TestFailedException diff --git a/internal/zinc-scripted/src/test/scala/sbt/internal/inc/ScriptedTests.scala b/internal/zinc-scripted/src/test/scala/sbt/internal/inc/ScriptedTests.scala index 1af4282af8..7da51dc401 100644 --- a/internal/zinc-scripted/src/test/scala/sbt/internal/inc/ScriptedTests.scala +++ b/internal/zinc-scripted/src/test/scala/sbt/internal/inc/ScriptedTests.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt.internal.inc import java.io.File diff --git a/zinc/src/main/scala/sbt/internal/inc/caching/ClasspathCache.scala b/zinc/src/main/scala/sbt/internal/inc/caching/ClasspathCache.scala index cda89f31e0..3aab605eef 100644 --- a/zinc/src/main/scala/sbt/internal/inc/caching/ClasspathCache.scala +++ b/zinc/src/main/scala/sbt/internal/inc/caching/ClasspathCache.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt.internal.inc.caching import java.io.File From 8d60f1fe6807e59c031cab1b878efa3f22e2bff9 Mon Sep 17 00:00:00 2001 From: jvican Date: Wed, 11 Oct 2017 16:44:16 +0200 Subject: [PATCH 02/20] Move the logic from `build.sbt` to the build plugin This is a squashed commit. This is a general list of the things that are done. - Port common settings and commands to BuildPlugin - Remove repeated resolvers - Move `relaxNon212` to the build plugin - Move build and alternative publish settings. This commit consolidates the build settings and the settings to set up the alternative publishing process into the `BuildPlugin`. - Move `noPublish` to the `BuildPlugin` - Move the rest of the build logic to the plugin --- build.sbt | 428 +++++-------------------------------- project/BuildPlugin.scala | 359 +++++++++++++++++++++++++++++++ project/Dependencies.scala | 19 +- project/Scripted.scala | 5 +- 4 files changed, 416 insertions(+), 395 deletions(-) create mode 100644 project/BuildPlugin.scala diff --git a/build.sbt b/build.sbt index 9082141426..41c3590159 100644 --- a/build.sbt +++ b/build.sbt @@ -1,102 +1,9 @@ +import BuildImplementation.{BuildDefaults, BuildCommands} import Util._ import Dependencies._ -import Scripted._ - -def baseVersion = "1.1.0-SNAPSHOT" -def internalPath = file("internal") - -lazy val compilerBridgeScalaVersions = List(scala212, scala211, scala210) - -def mimaSettings: Seq[Setting[_]] = Seq( - mimaPreviousArtifacts := Set( - organization.value % moduleName.value % "1.0.0" - cross (if (crossPaths.value) CrossVersion.binary else CrossVersion.disabled) - ) -) - -def commonSettings: Seq[Setting[_]] = Seq( - scalaVersion := scala212, - // publishArtifact in packageDoc := false, - resolvers += Resolver.typesafeIvyRepo("releases"), - resolvers += Resolver.sonatypeRepo("snapshots"), - resolvers += "bintray-sbt-maven-releases" at "https://dl.bintray.com/sbt/maven-releases/", - resolvers += Resolver.url( - "bintray-sbt-ivy-snapshots", - new URL("https://dl.bintray.com/sbt/ivy-snapshots/"))(Resolver.ivyStylePatterns), - // concurrentRestrictions in Global += Util.testExclusiveRestriction, - testOptions += Tests.Argument(TestFrameworks.ScalaCheck, "-w", "1"), - javacOptions in compile ++= Seq("-Xlint", "-Xlint:-serial"), - crossScalaVersions := Seq(scala211, scala212), - publishArtifact in Test := false, - commands ++= Seq(publishBridgesAndTest, publishBridgesAndSet, crossTestBridges), - scalacOptions += "-YdisableFlatCpCaching" -) - -def relaxNon212: Seq[Setting[_]] = Seq( - scalacOptions := { - val old = scalacOptions.value - scalaBinaryVersion.value match { - case "2.12" => old - case _ => - old filterNot Set( - "-Xfatal-warnings", - "-deprecation", - "-Ywarn-unused", - "-Ywarn-unused-import", - "-YdisableFlatCpCaching" - ) - } - } -) - -def minimalSettings: Seq[Setting[_]] = commonSettings - -// def minimalSettings: Seq[Setting[_]] = -// commonSettings ++ customCommands ++ -// publishPomSettings ++ Release.javaVersionCheckSettings - -def baseSettings: Seq[Setting[_]] = - minimalSettings -// minimalSettings ++ baseScalacOptions ++ Licensed.settings ++ Formatting.settings - -def addBaseSettingsAndTestDeps(p: Project): Project = - p.settings(baseSettings).configure(addTestDependencies) - -val altLocalRepoName = "alternative-local" -val altLocalRepoPath = sys.props("user.home") + "/.ivy2/sbt-alternative" -lazy val altLocalResolver = Resolver.file( - altLocalRepoName, - file(sys.props("user.home") + "/.ivy2/sbt-alternative"))(Resolver.ivyStylePatterns) -lazy val altLocalPublish = - TaskKey[Unit]("alt-local-publish", "Publishes an artifact locally to an alternative location.") -def altPublishSettings: Seq[Setting[_]] = - Seq( - resolvers += altLocalResolver, - altLocalPublish := { - import sbt.librarymanagement._ - import sbt.internal.librarymanagement._ - val config = (Keys.publishLocalConfiguration).value - val moduleSettings = (Keys.moduleSettings).value - val ivy = new IvySbt((ivyConfiguration.value)) - - val module = new ivy.Module(moduleSettings) - val newConfig = config.withResolverName(altLocalRepoName).withOverwrite(false) - streams.value.log.info(s"Publishing $module to local repo: $altLocalRepoName") - IvyActions.publish(module, newConfig, streams.value.log) - } - ) - -val noPublish: Seq[Setting[_]] = List( - publish := {}, - publishLocal := {}, - publishArtifact in Compile := false, - publishArtifact in Test := false, - publishArtifact := false, - skip in publish := true, -) lazy val zincRoot: Project = (project in file(".")) -// configs(Sxr.sxrConf). + .configure(noPublish) .aggregate( zinc, zincTesting, @@ -114,60 +21,19 @@ lazy val zincRoot: Project = (project in file(".")) zincScripted ) .settings( - inThisBuild( - Seq( - git.baseVersion := baseVersion, - // https://github.com/sbt/sbt-git/issues/109 - // Workaround from https://github.com/sbt/sbt-git/issues/92#issuecomment-161853239 - git.gitUncommittedChanges := { - val statusCommands = Seq( - Seq("diff-index", "--cached", "HEAD"), - Seq("diff-index", "HEAD"), - Seq("diff-files"), - Seq("ls-files", "--exclude-standard", "--others") - ) - // can't use git.runner.value because it's a task - val runner = com.typesafe.sbt.git.ConsoleGitRunner - val dir = baseDirectory.value - // sbt/zinc#334 Seemingly "git status" resets some stale metadata. - runner("status")(dir, com.typesafe.sbt.git.NullLogger) - val uncommittedChanges = statusCommands flatMap { c => - val res = runner(c: _*)(dir, com.typesafe.sbt.git.NullLogger) - if (res.isEmpty) Nil else Seq(c -> res) - } - - val un = uncommittedChanges.nonEmpty - if (un) { - uncommittedChanges foreach { - case (cmd, res) => - sLog.value debug s"""Uncommitted changes found via "${cmd mkString " "}":\n${res}""" - } - } - un - }, - version := { - val v = version.value - if (v contains "SNAPSHOT") git.baseVersion.value - else v - }, - bintrayPackage := "zinc", - scmInfo := Some(ScmInfo(url("https://github.com/sbt/zinc"), "git@github.com:sbt/zinc.git")), - description := "Incremental compiler of Scala", - homepage := Some(url("https://github.com/sbt/zinc")), - developers += - Developer("jvican", "Jorge Vicente Cantero", "@jvican", url("https://github.com/jvican")), - scalafmtOnCompile := true, - scalafmtVersion := "1.2.0", - scalafmtOnCompile in Sbt := false, - )), - minimalSettings, - otherRootSettings, - noPublish, - name := "zinc Root", - customCommands + name := "Zinc Root", + Scripted.scriptedPrescripted := BuildDefaults.addSbtAlternateResolver _, + Scripted.scriptedSource := (sourceDirectory in zinc).value / "sbt-test", + scriptedPublishAll := (publishLocal).all(ScopeFilter(inAnyProject)).value, + Scripted.scriptedUnpublished := BuildDefaults.zincOnlyScripted(zincScripted).evaluated, + Scripted.scripted := + BuildDefaults.zincScripted(compilerBridge, compilerInterface, zincScripted).evaluated, + commands ++= List(BuildCommands.release, BuildCommands.runBenchmarks(zincScripted)) ) lazy val zinc = (project in file("zinc")) + .configure(addTestDependencies) + .settings(name := "zinc", mimaSettings) .dependsOn( zincCore, zincPersist, @@ -176,34 +42,27 @@ lazy val zinc = (project in file("zinc")) zincIvyIntegration % "compile->compile;test->test", zincTesting % Test ) - .configure(addBaseSettingsAndTestDeps) - .settings( - name := "zinc", - mimaSettings, - ) lazy val zincTesting = (project in internalPath / "zinc-testing") + .configure(addSbtLmCore, addSbtLmIvy, addTestDependencies, noPublish) .settings( - minimalSettings, - noPublish, name := "zinc Testing", - libraryDependencies ++= Seq(scalaCheck, scalatest, junit, sjsonnewScalaJson.value) + libraryDependencies ++= Seq(scalaCheck, scalatest, junit, sjsonnewScalaJson.value), ) - .configure(addSbtLmCore, addSbtLmIvy) lazy val zincCompile = (project in file("zinc-compile")) .dependsOn(zincCompileCore, zincCompileCore % "test->test") - .configure(addBaseSettingsAndTestDeps) + .configure(addTestDependencies) + .configure(addSbtUtilTracking) .settings( name := "zinc Compile", mimaSettings, ) - .configure(addSbtUtilTracking) // Persists the incremental data structures using Protobuf lazy val zincPersist = (project in internalPath / "zinc-persist") .dependsOn(zincCore, zincCore % "test->test") - .configure(addBaseSettingsAndTestDeps) + .configure(addTestDependencies) .settings( name := "zinc Persist", libraryDependencies += sbinary, @@ -215,6 +74,7 @@ lazy val zincPersist = (project in internalPath / "zinc-persist") // Implements the core functionality of detecting and propagating changes incrementally. // Defines the data structures for representing file fingerprints and relationships and the overall source analysis lazy val zincCore = (project in internalPath / "zinc-core") + .configure(addTestDependencies, addSbtIO, addSbtUtilLogging, addSbtUtilRelation) .dependsOn( zincApiInfo, zincClasspath, @@ -222,7 +82,6 @@ lazy val zincCore = (project in internalPath / "zinc-core") compilerBridge % Test, zincTesting % Test ) - .configure(addBaseSettingsAndTestDeps) .settings( // we need to fork because in unit tests we set usejavacp = true which means // we are expecting all of our dependencies to be on classpath so Scala compiler @@ -235,37 +94,32 @@ lazy val zincCore = (project in internalPath / "zinc-core") compileOrder := sbt.CompileOrder.Mixed, mimaSettings, ) - .configure(addSbtIO, addSbtUtilLogging, addSbtUtilRelation) lazy val zincBenchmarks = (project in internalPath / "zinc-benchmarks") .dependsOn(compilerInterface % "compile->compile;compile->test") .dependsOn(compilerBridge, zincCore, zincTesting % Test) .enablePlugins(JmhPlugin) + .configure(noPublish) .settings( - noPublish, name := "Benchmarks of Zinc and the compiler bridge", - libraryDependencies ++= Seq( - "org.eclipse.jgit" % "org.eclipse.jgit" % "4.6.0.201612231935-r", - "net.openhft" % "affinity" % "3.0.6" - ), - scalaVersion := scala212, - crossScalaVersions := Seq(scala211, scala212), javaOptions in Test += "-Xmx600M -Xms600M", + libraryDependencies ++= List(jgit, affinity), + tearDownBenchmarkResources := BuildDefaults.tearDownBenchmarkResources.value, ) lazy val zincIvyIntegration = (project in internalPath / "zinc-ivy-integration") .dependsOn(zincCompileCore, zincTesting % Test) + .configure(addSbtLmCore, addSbtLmIvyTest) .settings( - baseSettings, name := "zinc Ivy Integration", compileOrder := sbt.CompileOrder.ScalaThenJava, mimaSettings, ) - .configure(addSbtLmCore, addSbtLmIvyTest) // sbt-side interface to compiler. Calls compiler-side interface reflectively lazy val zincCompileCore = (project in internalPath / "zinc-compile-core") .enablePlugins(ContrabandPlugin) + .configure(addTestDependencies, addSbtUtilLogging, addSbtIO, addSbtUtilControl) .dependsOn( compilerInterface % "compile;test->test", zincClasspath, @@ -273,25 +127,23 @@ lazy val zincCompileCore = (project in internalPath / "zinc-compile-core") zincClassfile, zincTesting % Test ) - .configure(addBaseSettingsAndTestDeps) .settings( name := "zinc Compile Core", libraryDependencies ++= Seq(scalaCompiler.value % Test, launcherInterface, parserCombinator), unmanagedJars in Test := Seq(packageSrc in compilerBridge in Compile value).classpath, - managedSourceDirectories in Compile += + managedSourceDirectories in Compile += baseDirectory.value / "src" / "main" / "contraband-java", + sourceManaged in (Compile, generateContrabands) := baseDirectory.value / "src" / "main" / "contraband-java", - sourceManaged in (Compile, generateContrabands) := baseDirectory.value / "src" / "main" / "contraband-java", mimaSettings, ) - .configure(addSbtUtilLogging, addSbtIO, addSbtUtilControl) // defines Java structures used across Scala versions, such as the API structures and relationships extracted by // the analysis compiler phases and passed back to sbt. The API structures are defined in a simple // format from which Java sources are generated by the sbt-contraband plugin. -lazy val compilerInterface = (project in internalPath / "compiler-interface") +lazy val compilerInterface = (project in internalPath / CompilerInterfaceId) .enablePlugins(ContrabandPlugin) + .configure(addSbtUtilInterface) .settings( - minimalSettings, // javaOnlySettings, name := "Compiler Interface", // Use the smallest Scala version in the compilerBridgeScalaVersions @@ -299,7 +151,7 @@ lazy val compilerInterface = (project in internalPath / "compiler-interface") // but given that Scala 2.10 compiler cannot parse Java 8 source, it's probably good to keep this. crossScalaVersions := Seq(scala210), scalaVersion := scala210, - relaxNon212, + adaptOptionsForOldScalaVersions, libraryDependencies ++= Seq(scalaLibrary.value % Test), exportJars := true, resourceGenerators in Compile += Def @@ -314,30 +166,22 @@ lazy val compilerInterface = (project in internalPath / "compiler-interface") .taskValue, managedSourceDirectories in Compile += baseDirectory.value / "src" / "main" / "contraband-java", - sourceManaged in (Compile, generateContrabands) := baseDirectory.value / "src" / "main" / "contraband-java", + sourceManaged in (Compile, generateContrabands) := + baseDirectory.value / "src" / "main" / "contraband-java", crossPaths := false, autoScalaLibrary := false, - altPublishSettings, + zincPublishLocalSettings, mimaSettings, ) - .configure(addSbtUtilInterface) - -val cleanSbtBridge = taskKey[Unit]("Cleans the sbt bridge.") -def wrapIn(color: String, content: String): String = { - import sbt.internal.util.ConsoleAppender - if (!ConsoleAppender.formatEnabledInEnv) content - else color + content + scala.Console.RESET -} // Compiler-side interface to compiler that is compiled against the compiler being used either in advance or on the fly. // Includes API and Analyzer phases that extract source API and relationships. -lazy val compilerBridge: Project = (project in internalPath / "compiler-bridge") +lazy val compilerBridge: Project = (project in internalPath / CompilerBridgeId) .dependsOn(compilerInterface % "compile;test->test", zincApiInfo % "test->test") .settings( - baseSettings, - crossScalaVersions := compilerBridgeScalaVersions, - relaxNon212, + crossScalaVersions := bridgeScalaVersions, + adaptOptionsForOldScalaVersions, libraryDependencies += scalaCompiler.value % "provided", autoScalaLibrary := false, // precompiledSettings, @@ -350,224 +194,50 @@ lazy val compilerBridge: Project = (project in internalPath / "compiler-bridge") // needed because we fork tests and tests are ran in parallel so we have multiple Scala // compiler instances that are memory hungry javaOptions in Test += "-Xmx1G", - inBoth(unmanagedSourceDirectories ++= scalaPartialVersion.value.collect { - case (2, y) if y == 10 => new File(scalaSource.value.getPath + "_2.10") - case (2, y) if y >= 11 => new File(scalaSource.value.getPath + "_2.11+") - }.toList), - cleanSbtBridge := { - val sbtV = sbtVersion.value - val sbtOrg = "org.scala-sbt" - val sbtScalaVersion = "2.10.6" - val bridgeVersion = version.value - val scalaV = scalaVersion.value - - // Assumes that JDK version is the same than the one that publishes the bridge - val classVersion = System.getProperty("java.class.version") - - val home = System.getProperty("user.home") - val org = organization.value - val artifact = moduleName.value - val artifactName = - s"$org-$artifact-$bridgeVersion-bin_${scalaV}__$classVersion" - - val targetsToDelete = List( - // We cannot use the target key, it's not scoped in `ThisBuild` nor `Global`. - (baseDirectory in ThisBuild).value / "target" / "zinc-components", - file(home) / ".ivy2/cache" / sbtOrg / artifactName, - file(home) / ".sbt/boot" / s"scala-$sbtScalaVersion" / sbtOrg / "sbt" / sbtV / artifactName - ) - val logger = streams.value.log - logger.info(wrapIn(scala.Console.BOLD, "Cleaning stale compiler bridges:")) - targetsToDelete.foreach { target => - IO.delete(target) - logger.info(s"${wrapIn(scala.Console.GREEN, " ✓ ")}${target.getAbsolutePath}") - } - }, + sourcesForAllScalaVersionsSetting.flatMap(inCompileAndTest), + cleanSbtBridge := BuildDefaults.cleanSbtBridge.value, publishLocal := publishLocal.dependsOn(cleanSbtBridge).value, - altPublishSettings, + zincPublishLocalSettings, mimaSettings, ) -val scalaPartialVersion = Def setting (CrossVersion partialVersion scalaVersion.value) - -def inBoth(ss: Setting[_]*): Seq[Setting[_]] = Seq(Compile, Test) flatMap (inConfig(_)(ss)) - // defines operations on the API of a source, including determining whether it has changed and converting it to a string // and discovery of Projclasses and annotations -lazy val zincApiInfo = (project in internalPath / "zinc-apiinfo") +lazy val zincApiInfo = (project in internalPath / ZincApiInfoId) .dependsOn(compilerInterface, zincClassfile % "compile;test->test") - .configure(addBaseSettingsAndTestDeps) + .configure(addTestDependencies) .settings( name := "zinc ApiInfo", - crossScalaVersions := compilerBridgeScalaVersions, - relaxNon212, + crossScalaVersions := bridgeScalaVersions, + adaptOptionsForOldScalaVersions, mimaSettings, ) // Utilities related to reflection, managing Scala versions, and custom class loaders lazy val zincClasspath = (project in internalPath / "zinc-classpath") .dependsOn(compilerInterface) - .configure(addBaseSettingsAndTestDeps) + .configure(addTestDependencies, addSbtIO) .settings( name := "zinc Classpath", - crossScalaVersions := compilerBridgeScalaVersions, - relaxNon212, + crossScalaVersions := bridgeScalaVersions, + adaptOptionsForOldScalaVersions, libraryDependencies ++= Seq(scalaCompiler.value, launcherInterface), mimaSettings, ) - .configure(addSbtIO) // class file reader and analyzer lazy val zincClassfile = (project in internalPath / "zinc-classfile") .dependsOn(compilerInterface % "compile;test->test") - .configure(addBaseSettingsAndTestDeps) + .configure(addTestDependencies, addSbtIO, addSbtUtilLogging) .settings( name := "zinc Classfile", - crossScalaVersions := compilerBridgeScalaVersions, - relaxNon212, + crossScalaVersions := bridgeScalaVersions, + adaptOptionsForOldScalaVersions, mimaSettings, ) - .configure(addSbtIO, addSbtUtilLogging) // re-implementation of scripted engine lazy val zincScripted = (project in internalPath / "zinc-scripted") .dependsOn(zinc, zincIvyIntegration % "test->test") - .settings( - minimalSettings, - noPublish, - name := "zinc Scripted", - ) - .configure(addSbtUtilScripted) - -lazy val crossTestBridges = { - Command.command("crossTestBridges") { state => - (compilerBridgeScalaVersions.flatMap { (bridgeVersion: String) => - // Note the ! here. You need this so compilerInterface gets forced to the scalaVersion - s"++ $bridgeVersion!" :: - s"${compilerBridge.id}/test" :: - Nil - }) ::: - (s"++ $scala212!" :: - state) - } -} - -lazy val publishBridgesAndSet = { - Command.args("publishBridgesAndSet", "") { (state, args) => - require(args.nonEmpty, "Missing Scala version argument.") - val userScalaVersion = args.mkString("") - s"${compilerInterface.id}/publishLocal" :: - compilerBridgeScalaVersions.flatMap { (bridgeVersion: String) => - s"++ $bridgeVersion!" :: - s"${zincApiInfo.id}/publishLocal" :: - s"${compilerBridge.id}/publishLocal" :: Nil - } ::: - s"++ $userScalaVersion!" :: - state - } -} - -lazy val publishBridgesAndTest = Command.args("publishBridgesAndTest", "") { - (state, args) => - require(args.nonEmpty, - "Missing arguments to publishBridgesAndTest. Maybe quotes are missing around command?") - val version = args mkString "" - s"${compilerInterface.id}/publishLocal" :: - (compilerBridgeScalaVersions.flatMap { (bridgeVersion: String) => - s"++ $bridgeVersion" :: - s"${zincApiInfo.id}/publishLocal" :: - s"${compilerBridge.id}/publishLocal" :: Nil - }) ::: - s"++ $version" :: - s"zincRoot/scalaVersion" :: - s"zincRoot/test" :: - s"zincRoot/scripted" :: - state -} - -val dir = IO.createTemporaryDirectory -val dirPath = dir.getAbsolutePath -lazy val tearDownBenchmarkResources = taskKey[Unit]("Remove benchmark resources.") -tearDownBenchmarkResources in ThisBuild := { IO.delete(dir) } - -addCommandAlias( - "runBenchmarks", - s""";zincBenchmarks/run $dirPath - |;zincBenchmarks/jmh:run -p _tempDir=$dirPath -prof gc - |;tearDownBenchmarkResources - """.stripMargin -) - -lazy val otherRootSettings = Seq( - Scripted.scriptedBufferLog := true, - Scripted.scriptedPrescripted := { addSbtAlternateResolver _ }, - Scripted.scripted := scriptedTask.evaluated, - Scripted.scriptedUnpublished := scriptedUnpublishedTask.evaluated, - Scripted.scriptedSource := (sourceDirectory in zinc).value / "sbt-test", - publishAll := { - val _ = (publishLocal).all(ScopeFilter(inAnyProject)).value - } -) - -def scriptedTask: Def.Initialize[InputTask[Unit]] = Def.inputTask { - val result = scriptedSource(dir => (s: State) => scriptedParser(dir)).parsed - publishAll.value - // These two projects need to be visible in a repo even if the default - // local repository is hidden, so we publish them to an alternate location and add - // that alternate repo to the running scripted test (in Scripted.scriptedpreScripted). - (altLocalPublish in compilerInterface).value - (altLocalPublish in compilerBridge).value - doScripted( - (fullClasspath in zincScripted in Test).value, - (scalaInstance in zincScripted).value, - scriptedSource.value, - result, - scriptedBufferLog.value, - scriptedPrescripted.value - ) -} - -def addSbtAlternateResolver(scriptedRoot: File) = { - val resolver = scriptedRoot / "project" / "AddResolverPlugin.scala" - if (!resolver.exists) { - IO.write( - resolver, - s"""import sbt._ - |import Keys._ - | - |object AddResolverPlugin extends AutoPlugin { - | override def requires = sbt.plugins.JvmPlugin - | override def trigger = allRequirements - | - | override lazy val projectSettings = Seq(resolvers += alternativeLocalResolver) - | lazy val alternativeLocalResolver = Resolver.file("$altLocalRepoName", file("$altLocalRepoPath"))(Resolver.ivyStylePatterns) - |} - |""".stripMargin - ) - } -} - -def scriptedUnpublishedTask: Def.Initialize[InputTask[Unit]] = Def.inputTask { - val result = scriptedSource(dir => (s: State) => scriptedParser(dir)).parsed - doScripted( - (fullClasspath in zincScripted in Test).value, - (scalaInstance in zincScripted).value, - scriptedSource.value, - result, - scriptedBufferLog.value, - scriptedPrescripted.value - ) -} - -lazy val publishAll = TaskKey[Unit]("publish-all") -lazy val publishLauncher = TaskKey[Unit]("publish-launcher") - -def customCommands: Seq[Setting[_]] = Seq( - commands += Command.command("release") { state => - "clean" :: // This is required since version number is generated in properties file. - "+compile" :: - "+publishSigned" :: - "reload" :: - state - } -) + .configure(addSbtUtilScripted, noPublish) + .settings(name := "zinc Scripted") diff --git a/project/BuildPlugin.scala b/project/BuildPlugin.scala new file mode 100644 index 0000000000..ef5e3e11db --- /dev/null +++ b/project/BuildPlugin.scala @@ -0,0 +1,359 @@ +import sbt.{ AutoPlugin, Compile, Def, Keys, Resolver, Test, TestFrameworks, Tests, URL, Project } +import com.typesafe.sbt.SbtGit.{ git => GitKeys } +import bintray.BintrayPlugin.{ autoImport => BintrayKeys } +import com.lucidchart.sbt.scalafmt.ScalafmtCorePlugin.{ autoImport => ScalafmtKeys } +import com.lucidchart.sbt.scalafmt.ScalafmtSbtPlugin.autoImport.Sbt +import com.typesafe.tools.mima.plugin.MimaKeys + +object BuildPlugin extends AutoPlugin { + override def requires = sbt.plugins.JvmPlugin + override def trigger = allRequirements + val autoImport = BuildKeys + + override def projectSettings: Seq[Def.Setting[_]] = BuildImplementation.projectSettings + override def buildSettings: Seq[Def.Setting[_]] = BuildImplementation.buildSettings + override def globalSettings: Seq[Def.Setting[_]] = BuildImplementation.globalSettings +} + +object BuildKeys { + import sbt.{ file, File, Developer, url } + import BuildImplementation.{ BuildDefaults, BuildResolvers } + + val baseVersion: String = "1.1.0-SNAPSHOT" + val internalPath: File = file("internal") + val bridgeScalaVersions: List[String] = + List(Dependencies.scala212, Dependencies.scala211, Dependencies.scala210) + + val ZincGitHomepage: URL = url("https://github.com/sbt/zinc") + val ScalaCenterMaintainer: Developer = + Developer("jvican", "Jorge Vicente Cantero", "@jvican", url("https://github.com/jvican")) + + // Ids that we will use to name our projects in build.sbt + val CompilerInterfaceId = "compiler-interface" + val CompilerBridgeId = "compiler-bridge" + val ZincApiInfoId = "zinc-apiinfo" + + // Defines the constants for the alternative publishing + val ZincAlternativeCacheName = "alternative-local" + val ZincAlternativeCacheDir: File = file(sys.props("user.home") + "/.ivy2/zinc-alternative") + + // Defines several settings that are exposed to the projects definition in build.sbt + private[this] val noPublishSettings: Seq[Def.Setting[_]] = BuildDefaults.noPublishSettings + def noPublish(p: Project): Project = p.settings(noPublishSettings) + + val adaptOptionsForOldScalaVersions: Seq[Def.Setting[_]] = + List(Keys.scalacOptions := BuildDefaults.zincScalacOptionsRedefinition.value) + // Sets up mima settings for modules that have to be binary compatible with Zinc 1.0.0 + val mimaSettings: Seq[Def.Setting[_]] = + List(MimaKeys.mimaPreviousArtifacts := BuildDefaults.zincPreviousArtifacts.value) + + import sbt.{ TaskKey, taskKey } + val scriptedPublishAll = taskKey[Unit]("Publishes all the Zinc artifacts for scripted") + val cleanSbtBridge: TaskKey[Unit] = taskKey[Unit]("Cleans the sbt bridge.") + val zincPublishLocal: TaskKey[Unit] = + taskKey[Unit]("Publishes Zinc artifacts to a alternative local cache.") + val zincPublishLocalSettings: Seq[Def.Setting[_]] = List( + Keys.resolvers += BuildResolvers.AlternativeLocalResolver, + zincPublishLocal := BuildDefaults.zincPublishLocal.value, + ) + + val tearDownBenchmarkResources: TaskKey[Unit] = taskKey[Unit]("Remove benchmark resources.") + val benchmarksTestDir = sbt.IO.createTemporaryDirectory + + val sourcesForAllScalaVersionsSetting: Seq[Def.Setting[_]] = + List(Keys.unmanagedSourceDirectories ++= BuildDefaults.handleScalaSpecificSources.value) + def inCompileAndTest(ss: Def.Setting[_]): Seq[Def.Setting[_]] = + List(Compile, Test).flatMap(sbt.inConfig(_)(ss)) +} + +object BuildImplementation { + import sbt.{ ScmInfo } + val buildSettings: Seq[Def.Setting[_]] = List( + Scripted.scriptedBufferLog := true, + GitKeys.baseVersion := BuildKeys.baseVersion, + GitKeys.gitUncommittedChanges := BuildDefaults.gitUncommitedChanges.value, + BintrayKeys.bintrayPackage := "zinc", + ScalafmtKeys.scalafmtOnCompile := true, + ScalafmtKeys.scalafmtVersion := "1.2.0", + ScalafmtKeys.scalafmtOnCompile in Sbt := false, + Keys.description := "Incremental compiler of Scala", + // The rest of the sbt developers come from the Sbt Houserules plugin + Keys.developers += BuildKeys.ScalaCenterMaintainer, + // TODO(jvican): Remove `scmInfo` and `homepage` when we have support for sbt-release-early + Keys.homepage := Some(BuildKeys.ZincGitHomepage), + Keys.scmInfo := Some(ScmInfo(BuildKeys.ZincGitHomepage, "git@github.com:sbt/zinc.git")), + Keys.version := { + val previous = Keys.version.value + if (previous.contains("-SNAPSHOT")) GitKeys.baseVersion.value else previous + }, + ) + + val globalSettings: Seq[Def.Setting[_]] = List( + Keys.commands ++= BuildCommands.all + ) + + val projectSettings: Seq[Def.Setting[_]] = List( + // publishArtifact in packageDoc := false, + // concurrentRestrictions in Global += Util.testExclusiveRestriction, + Keys.scalaVersion := Dependencies.scala212, + Keys.resolvers ++= BuildResolvers.all, + Keys.resolvers ~= BuildResolvers.removeRepeatedResolvers, + Keys.testOptions += Tests.Argument(TestFrameworks.ScalaCheck, "-w", "1"), + Keys.javacOptions in Compile ++= Seq("-Xlint", "-Xlint:-serial"), + Keys.crossScalaVersions := Seq(Dependencies.scala211, Dependencies.scala212), + Keys.publishArtifact in Test := false, + Keys.scalacOptions += "-YdisableFlatCpCaching" + ) + + object BuildResolvers { + import sbt.{ MavenRepository, file } + val TypesafeReleases: Resolver = Resolver.typesafeIvyRepo("releases") + val SonatypeSnapshots: Resolver = Resolver.sonatypeRepo("snapshots") + val BintrayMavenReleases: Resolver = + MavenRepository("bintray-sbt-maven-releases", "https://dl.bintray.com/sbt/maven-releases/") + val BintraySbtIvySnapshots: Resolver = + Resolver.url("bintray-sbt-ivy-snapshots", + new URL("https://dl.bintray.com/sbt/ivy-snapshots/"))(Resolver.ivyStylePatterns) + val all: List[Resolver] = + List(TypesafeReleases, SonatypeSnapshots, BintrayMavenReleases, BintraySbtIvySnapshots) + + import BuildKeys.{ ZincAlternativeCacheName, ZincAlternativeCacheDir } + val AlternativeLocalResolver: Resolver = + Resolver.file(ZincAlternativeCacheName, ZincAlternativeCacheDir)(Resolver.ivyStylePatterns) + + // Naive way of implementing a filter to remove repeated resolvers. + def removeRepeatedResolvers(rs: Seq[Resolver]): Seq[Resolver] = rs.toSet.toVector + } + + object BuildCommands { + import sbt.{ Command, State } + import BuildKeys.{ CompilerBridgeId, ZincApiInfoId, CompilerInterfaceId, bridgeScalaVersions } + val crossTestBridges: Command = { + Command.command("crossTestBridges") { (state: State) => + (bridgeScalaVersions.flatMap { (bridgeVersion: String) => + // Note the ! here. You need this so compilerInterface gets forced to the scalaVersion + s"++ $bridgeVersion!" :: s"$CompilerBridgeId/test" :: Nil + }) ::: (s"++ ${Dependencies.scala212}!" :: state) + } + } + + val publishBridgesAndSet: Command = { + Command.args("publishBridgesAndSet", "") { (state, args) => + require(args.nonEmpty, "Missing Scala version argument.") + val userScalaVersion = args.mkString("") + s"$CompilerInterfaceId/publishLocal" :: bridgeScalaVersions.flatMap { (v: String) => + s"++ $v!" :: s"$ZincApiInfoId/publishLocal" :: s"$CompilerBridgeId/publishLocal" :: Nil + } ::: s"++ $userScalaVersion!" :: state + } + } + + val publishBridgesAndTest: Command = Command.args("publishBridgesAndTest", "") { + (state, args) => + require(args.nonEmpty, "Missing arguments to publishBridgesAndTest.") + val version = args mkString "" + val bridgeCommands: List[String] = bridgeScalaVersions.flatMap { (v: String) => + s"++ $v" :: s"$ZincApiInfoId/publishLocal" :: s"$CompilerBridgeId/publishLocal" :: Nil + } + s"$CompilerInterfaceId/publishLocal" :: + bridgeCommands ::: + s"++ $version" :: + s"zincRoot/scalaVersion" :: + s"zincRoot/test" :: + s"zincRoot/scripted" :: + state + } + + val release: Command = + Command.command("release")(st => "clean" :: "+compile" :: "+publishSigned" :: "reload" :: st) + + def runBenchmarks(benchmarkProject: Project): Command = { + val dirPath = BuildKeys.benchmarksTestDir.getAbsolutePath + val projectId = benchmarkProject.id + val runPreSetup = s"$projectId/run $dirPath" + val runBenchmark = s"$projectId/jmh:run -p _tempDir=$dirPath -prof gc" + val tearDownResources = s"$projectId/tearDownBenchmarkResources" + Command.command("runBenchmarks")(st => runPreSetup :: runBenchmark :: tearDownResources :: st) + } + + val all: List[Command] = List(crossTestBridges, publishBridgesAndSet, publishBridgesAndTest) + } + + object BuildDefaults { + import BuildKeys.{ ZincAlternativeCacheName, ZincAlternativeCacheDir } + import sbt.{ Task, State, fileToRichFile, file, File, IO } + private[this] val statusCommands = List( + List("diff-index", "--cached", "HEAD"), + List("diff-index", "HEAD"), + List("diff-files"), + List("ls-files", "--exclude-standard", "--others") + ) + + // https://github.com/sbt/sbt-git/issues/109 + val gitUncommitedChanges: Def.Initialize[Boolean] = Def.setting { + // Workaround from https://github.com/sbt/sbt-git/issues/92#issuecomment-161853239 + val dir = Keys.baseDirectory.value + // can't use git.runner.value because it's a task + val runner = com.typesafe.sbt.git.ConsoleGitRunner + // sbt/zinc#334 Seemingly "git status" resets some stale metadata. + runner("status")(dir, com.typesafe.sbt.git.NullLogger) + val uncommittedChanges = statusCommands.flatMap { c => + val res = runner(c: _*)(dir, com.typesafe.sbt.git.NullLogger) + if (res.isEmpty) Nil else List(c -> res) + } + val logger = Keys.sLog.value + val areUncommited = uncommittedChanges.nonEmpty + if (areUncommited) { + uncommittedChanges.foreach { + case (cmd, res) => + logger.debug(s"""Uncommitted changes found via "${cmd.mkString(" ")}":\n${res}""") + } + } + areUncommited + } + + import sbt.{ CrossVersion, ModuleID, stringToOrganization } + val zincPreviousArtifacts: Def.Initialize[Set[ModuleID]] = Def.setting { + val zincModule = (Keys.organization.value % Keys.moduleName.value % "1.0.0") + .cross(if (Keys.crossPaths.value) CrossVersion.binary else CrossVersion.disabled) + Set(zincModule) + } + + private[this] val toFilterInOldScala: Set[String] = Set( + "-Xfatal-warnings", + "-deprecation", + "-Ywarn-unused", + "-Ywarn-unused-import", + "-YdisableFlatCpCaching" + ) + + val zincScalacOptionsRedefinition: Def.Initialize[Task[Seq[String]]] = Def.task { + val old = Keys.scalacOptions.value + Keys.scalaBinaryVersion.value match { + case v if v == "2.12" || v == "2.13" => old + case _ => old.filterNot(toFilterInOldScala) + } + } + + val zincPublishLocal: Def.Initialize[Task[Unit]] = Def.task { + import sbt.internal.librarymanagement._ + val logger = Keys.streams.value.log + val config = (Keys.publishLocalConfiguration).value + val ivy = new IvySbt((Keys.ivyConfiguration.value)) + val moduleSettings = (Keys.moduleSettings).value + val module = new ivy.Module(moduleSettings) + val newConfig = config.withResolverName(ZincAlternativeCacheName).withOverwrite(false) + logger.info(s"Publishing $module to local repo: $ZincAlternativeCacheName") + Set(IvyActions.publish(module, newConfig, logger)) + } + + val noPublishSettings: Seq[Def.Setting[_]] = List( + Keys.publish := {}, + Keys.publishLocal := {}, + Keys.publishArtifact in Compile := false, + Keys.publishArtifact in Test := false, + Keys.publishArtifact := false, + Keys.skip in Keys.publish := true, + ) + + private[this] def wrapIn(color: String, content: String): String = { + import sbt.internal.util.ConsoleAppender + if (!ConsoleAppender.formatEnabledInEnv) content + else color + content + scala.Console.RESET + } + + val cleanSbtBridge: Def.Initialize[Task[Unit]] = Def.task { + val sbtV = Keys.sbtVersion.value + val sbtOrg = "org.scala-sbt" + val sbtScalaVersion = "2.10.6" + val bridgeVersion = Keys.version.value + val scalaV = Keys.scalaVersion.value + + // Assumes that JDK version is the same than the one that publishes the bridge + val classVersion = System.getProperty("java.class.version") + + val home = System.getProperty("user.home") + val org = Keys.organization.value + val artifact = Keys.moduleName.value + val artifactName = s"$org-$artifact-$bridgeVersion-bin_${scalaV}__$classVersion" + + val targetsToDelete = List( + // We cannot use the target key, it's not scoped in `ThisBuild` nor `Global`. + (Keys.baseDirectory in sbt.ThisBuild).value / "target" / "zinc-components", + file(home) / ".ivy2/cache" / sbtOrg / artifactName, + file(home) / ".ivy2/local" / sbtOrg / artifactName, + file(home) / ".sbt/boot" / s"scala-$sbtScalaVersion" / sbtOrg / "sbt" / sbtV / artifactName + ) + + val logger = Keys.streams.value.log + logger.info(wrapIn(scala.Console.BOLD, "Cleaning stale compiler bridges:")) + targetsToDelete.foreach { target => + IO.delete(target) + logger.info(s"${wrapIn(scala.Console.GREEN, " ✓ ")}${target.getAbsolutePath}") + } + } + + private[this] val scalaPartialVersion = + Def.setting(CrossVersion.partialVersion(Keys.scalaVersion.value)) + val handleScalaSpecificSources: Def.Initialize[List[File]] = Def.setting { + val source = Keys.scalaSource.value + scalaPartialVersion.value.collect { + case (2, y) if y == 10 => new File(source.getPath + "_2.10") + case (2, y) if y >= 11 => new File(source.getPath + "_2.11+") + }.toList + } + + import sbt.{ InputTask } + import Scripted.{ scriptedSource, scriptedParser, scriptedBufferLog, scriptedPrescripted } + def zincScripted(bridgeRef: Project, + interfaceRef: Project, + scriptedRef: Project): Def.Initialize[InputTask[Unit]] = Def.inputTask { + val result = scriptedSource(dir => (s: State) => scriptedParser(dir)).parsed + // We first publish all the zinc modules + BuildKeys.scriptedPublishAll.value + + val source = scriptedSource.value + val logged = scriptedBufferLog.value + val hook = scriptedPrescripted.value + + // Publish the interface and the bridge for scripted to resolve them correctly + (BuildKeys.zincPublishLocal in interfaceRef).value + (BuildKeys.zincPublishLocal in bridgeRef).value + + val scriptedClasspath = (Keys.fullClasspath in scriptedRef in Test).value + val instance = (Keys.scalaInstance in scriptedRef in Test).value + Scripted.doScripted(scriptedClasspath, instance, source, result, logged, hook) + } + + def zincOnlyScripted(scriptedRef: Project): Def.Initialize[InputTask[Unit]] = Def.inputTask { + val result = scriptedSource(dir => (s: State) => scriptedParser(dir)).parsed + val scriptedClasspath = (Keys.fullClasspath in scriptedRef in Test).value + val instance = (Keys.scalaInstance in scriptedRef in Test).value + val source = scriptedSource.value + val logged = scriptedBufferLog.value + val hook = scriptedPrescripted.value + Scripted.doScripted(scriptedClasspath, instance, source, result, logged, hook) + } + + private[this] val ZincAlternativeResolverPlugin = s""" + |import sbt._ + |import Keys._ + | + |object AddResolverPlugin extends AutoPlugin { + | override def requires = sbt.plugins.JvmPlugin + | override def trigger = allRequirements + | + | override lazy val projectSettings = Seq(resolvers += alternativeLocalResolver) + | lazy val alternativeLocalResolver = Resolver.file("$ZincAlternativeCacheName", file("${ZincAlternativeCacheDir.getAbsolutePath}"))(Resolver.ivyStylePatterns) + |} + |""".stripMargin + + def addSbtAlternateResolver(scriptedRoot: File): Unit = { + val resolver = scriptedRoot / "project" / "AddResolverPlugin.scala" + if (!resolver.exists) IO.write(resolver, ZincAlternativeResolverPlugin) + else () + } + + val tearDownBenchmarkResources: Def.Initialize[Task[Unit]] = + Def.task(IO.delete(BuildKeys.benchmarksTestDir)) + } +} diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 729bca6115..567aac5484 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -79,19 +79,12 @@ object Dependencies { val scalaCheck = "org.scalacheck" %% "scalacheck" % "1.13.4" val scalatest = "org.scalatest" %% "scalatest" % "3.0.1" val junit = "junit" % "junit" % "4.11" - val sjsonnew = Def.setting { - "com.eed3si9n" %% "sjson-new-core" % contrabandSjsonNewVersion.value - } - val sjsonnewScalaJson = Def.setting { - "com.eed3si9n" %% "sjson-new-scalajson" % contrabandSjsonNewVersion.value - } + val sjsonnew = Def.setting("com.eed3si9n" %% "sjson-new-core" % contrabandSjsonNewVersion.value) + val sjsonnewScalaJson = + Def.setting("com.eed3si9n" %% "sjson-new-scalajson" % contrabandSjsonNewVersion.value) + val affinity = "net.openhft" % "affinity" % "3.0.6" + val jgit = "org.eclipse.jgit" % "org.eclipse.jgit" % "4.6.0.201612231935-r" def addTestDependencies(p: Project): Project = - p.settings( - libraryDependencies ++= Seq( - scalaCheck % Test, - scalatest % Test, - junit % Test - ) - ) + p.settings(libraryDependencies ++= Seq(scalaCheck % Test, scalatest % Test, junit % Test)) } diff --git a/project/Scripted.scala b/project/Scripted.scala index d018b64b69..07f893cdb7 100644 --- a/project/Scripted.scala +++ b/project/Scripted.scala @@ -82,8 +82,7 @@ object Scripted { val bridgeClass = Class.forName("sbt.internal.inc.IncScriptedRunner", true, loader) val bridge = bridgeClass.newInstance.asInstanceOf[IncScriptedRunner] // val launcherVmOptions = Array("-XX:MaxPermSize=256M") // increased after a failure in scripted source-dependencies/macro - try { - bridge.run(sourcePath, bufferLog, args.toArray) - } catch { case ite: java.lang.reflect.InvocationTargetException => throw ite.getCause } + try bridge.run(sourcePath, bufferLog, args.toArray) + catch { case ite: java.lang.reflect.InvocationTargetException => throw ite.getCause } } } From 59392e48598ee6db0bd1f29cf79d7a76bb80d3b4 Mon Sep 17 00:00:00 2001 From: jvican Date: Thu, 12 Oct 2017 13:49:23 +0200 Subject: [PATCH 03/20] Address Dale's feedback --- build.sbt | 13 +++--- project/BuildPlugin.scala | 98 +++++++++++++++++++-------------------- 2 files changed, 55 insertions(+), 56 deletions(-) diff --git a/build.sbt b/build.sbt index 41c3590159..f642f2024b 100644 --- a/build.sbt +++ b/build.sbt @@ -28,7 +28,8 @@ lazy val zincRoot: Project = (project in file(".")) Scripted.scriptedUnpublished := BuildDefaults.zincOnlyScripted(zincScripted).evaluated, Scripted.scripted := BuildDefaults.zincScripted(compilerBridge, compilerInterface, zincScripted).evaluated, - commands ++= List(BuildCommands.release, BuildCommands.runBenchmarks(zincScripted)) + commands in Global ++= + BuildCommands.all(compilerBridge, compilerInterface, zincApiInfo, zincBenchmarks), ) lazy val zinc = (project in file("zinc")) @@ -44,7 +45,7 @@ lazy val zinc = (project in file("zinc")) ) lazy val zincTesting = (project in internalPath / "zinc-testing") - .configure(addSbtLmCore, addSbtLmIvy, addTestDependencies, noPublish) + .configure(addSbtLmCore, addSbtLmIvy, noPublish) .settings( name := "zinc Testing", libraryDependencies ++= Seq(scalaCheck, scalatest, junit, sjsonnewScalaJson.value), @@ -140,7 +141,7 @@ lazy val zincCompileCore = (project in internalPath / "zinc-compile-core") // defines Java structures used across Scala versions, such as the API structures and relationships extracted by // the analysis compiler phases and passed back to sbt. The API structures are defined in a simple // format from which Java sources are generated by the sbt-contraband plugin. -lazy val compilerInterface = (project in internalPath / CompilerInterfaceId) +lazy val compilerInterface = (project in internalPath / "compiler-interface") .enablePlugins(ContrabandPlugin) .configure(addSbtUtilInterface) .settings( @@ -177,7 +178,7 @@ lazy val compilerInterface = (project in internalPath / CompilerInterfaceId) // Compiler-side interface to compiler that is compiled against the compiler being used either in advance or on the fly. // Includes API and Analyzer phases that extract source API and relationships. -lazy val compilerBridge: Project = (project in internalPath / CompilerBridgeId) +lazy val compilerBridge: Project = (project in internalPath / "compiler-bridge") .dependsOn(compilerInterface % "compile;test->test", zincApiInfo % "test->test") .settings( crossScalaVersions := bridgeScalaVersions, @@ -194,7 +195,7 @@ lazy val compilerBridge: Project = (project in internalPath / CompilerBridgeId) // needed because we fork tests and tests are ran in parallel so we have multiple Scala // compiler instances that are memory hungry javaOptions in Test += "-Xmx1G", - sourcesForAllScalaVersionsSetting.flatMap(inCompileAndTest), + inCompileAndTest(unmanagedSourceDirectories ++= BuildDefaults.handleScalaSpecificSources.value), cleanSbtBridge := BuildDefaults.cleanSbtBridge.value, publishLocal := publishLocal.dependsOn(cleanSbtBridge).value, zincPublishLocalSettings, @@ -203,7 +204,7 @@ lazy val compilerBridge: Project = (project in internalPath / CompilerBridgeId) // defines operations on the API of a source, including determining whether it has changed and converting it to a string // and discovery of Projclasses and annotations -lazy val zincApiInfo = (project in internalPath / ZincApiInfoId) +lazy val zincApiInfo = (project in internalPath / "zinc-apiinfo") .dependsOn(compilerInterface, zincClassfile % "compile;test->test") .configure(addTestDependencies) .settings( diff --git a/project/BuildPlugin.scala b/project/BuildPlugin.scala index ef5e3e11db..17a803ee24 100644 --- a/project/BuildPlugin.scala +++ b/project/BuildPlugin.scala @@ -8,14 +8,24 @@ import com.typesafe.tools.mima.plugin.MimaKeys object BuildPlugin extends AutoPlugin { override def requires = sbt.plugins.JvmPlugin override def trigger = allRequirements - val autoImport = BuildKeys + val autoImport = BuildAutoImported override def projectSettings: Seq[Def.Setting[_]] = BuildImplementation.projectSettings override def buildSettings: Seq[Def.Setting[_]] = BuildImplementation.buildSettings - override def globalSettings: Seq[Def.Setting[_]] = BuildImplementation.globalSettings + override def globalSettings: Seq[Def.Setting[_]] = Nil } -object BuildKeys { +trait BuildKeys { + import sbt.{ TaskKey, taskKey } + + val tearDownBenchmarkResources: TaskKey[Unit] = taskKey[Unit]("Remove benchmark resources.") + val scriptedPublishAll = taskKey[Unit]("Publishes all the Zinc artifacts for scripted") + val cleanSbtBridge: TaskKey[Unit] = taskKey[Unit]("Cleans the sbt bridge.") + val zincPublishLocal: TaskKey[Unit] = + taskKey[Unit]("Publishes Zinc artifacts to a alternative local cache.") +} + +object BuildAutoImported extends BuildKeys { import sbt.{ file, File, Developer, url } import BuildImplementation.{ BuildDefaults, BuildResolvers } @@ -28,11 +38,6 @@ object BuildKeys { val ScalaCenterMaintainer: Developer = Developer("jvican", "Jorge Vicente Cantero", "@jvican", url("https://github.com/jvican")) - // Ids that we will use to name our projects in build.sbt - val CompilerInterfaceId = "compiler-interface" - val CompilerBridgeId = "compiler-bridge" - val ZincApiInfoId = "zinc-apiinfo" - // Defines the constants for the alternative publishing val ZincAlternativeCacheName = "alternative-local" val ZincAlternativeCacheDir: File = file(sys.props("user.home") + "/.ivy2/zinc-alternative") @@ -41,28 +46,18 @@ object BuildKeys { private[this] val noPublishSettings: Seq[Def.Setting[_]] = BuildDefaults.noPublishSettings def noPublish(p: Project): Project = p.settings(noPublishSettings) - val adaptOptionsForOldScalaVersions: Seq[Def.Setting[_]] = - List(Keys.scalacOptions := BuildDefaults.zincScalacOptionsRedefinition.value) // Sets up mima settings for modules that have to be binary compatible with Zinc 1.0.0 val mimaSettings: Seq[Def.Setting[_]] = List(MimaKeys.mimaPreviousArtifacts := BuildDefaults.zincPreviousArtifacts.value) - - import sbt.{ TaskKey, taskKey } - val scriptedPublishAll = taskKey[Unit]("Publishes all the Zinc artifacts for scripted") - val cleanSbtBridge: TaskKey[Unit] = taskKey[Unit]("Cleans the sbt bridge.") - val zincPublishLocal: TaskKey[Unit] = - taskKey[Unit]("Publishes Zinc artifacts to a alternative local cache.") + val adaptOptionsForOldScalaVersions: Seq[Def.Setting[_]] = + List(Keys.scalacOptions := BuildDefaults.zincScalacOptionsRedefinition.value) val zincPublishLocalSettings: Seq[Def.Setting[_]] = List( Keys.resolvers += BuildResolvers.AlternativeLocalResolver, zincPublishLocal := BuildDefaults.zincPublishLocal.value, ) - val tearDownBenchmarkResources: TaskKey[Unit] = taskKey[Unit]("Remove benchmark resources.") val benchmarksTestDir = sbt.IO.createTemporaryDirectory - - val sourcesForAllScalaVersionsSetting: Seq[Def.Setting[_]] = - List(Keys.unmanagedSourceDirectories ++= BuildDefaults.handleScalaSpecificSources.value) - def inCompileAndTest(ss: Def.Setting[_]): Seq[Def.Setting[_]] = + def inCompileAndTest(ss: Def.Setting[_]*): Seq[Def.Setting[_]] = List(Compile, Test).flatMap(sbt.inConfig(_)(ss)) } @@ -70,7 +65,7 @@ object BuildImplementation { import sbt.{ ScmInfo } val buildSettings: Seq[Def.Setting[_]] = List( Scripted.scriptedBufferLog := true, - GitKeys.baseVersion := BuildKeys.baseVersion, + GitKeys.baseVersion := BuildAutoImported.baseVersion, GitKeys.gitUncommittedChanges := BuildDefaults.gitUncommitedChanges.value, BintrayKeys.bintrayPackage := "zinc", ScalafmtKeys.scalafmtOnCompile := true, @@ -78,20 +73,16 @@ object BuildImplementation { ScalafmtKeys.scalafmtOnCompile in Sbt := false, Keys.description := "Incremental compiler of Scala", // The rest of the sbt developers come from the Sbt Houserules plugin - Keys.developers += BuildKeys.ScalaCenterMaintainer, + Keys.developers += BuildAutoImported.ScalaCenterMaintainer, // TODO(jvican): Remove `scmInfo` and `homepage` when we have support for sbt-release-early - Keys.homepage := Some(BuildKeys.ZincGitHomepage), - Keys.scmInfo := Some(ScmInfo(BuildKeys.ZincGitHomepage, "git@github.com:sbt/zinc.git")), + Keys.homepage := Some(BuildAutoImported.ZincGitHomepage), + Keys.scmInfo := Some(ScmInfo(BuildAutoImported.ZincGitHomepage, "git@github.com:sbt/zinc.git")), Keys.version := { val previous = Keys.version.value if (previous.contains("-SNAPSHOT")) GitKeys.baseVersion.value else previous }, ) - val globalSettings: Seq[Def.Setting[_]] = List( - Keys.commands ++= BuildCommands.all - ) - val projectSettings: Seq[Def.Setting[_]] = List( // publishArtifact in packageDoc := false, // concurrentRestrictions in Global += Util.testExclusiveRestriction, @@ -117,57 +108,58 @@ object BuildImplementation { val all: List[Resolver] = List(TypesafeReleases, SonatypeSnapshots, BintrayMavenReleases, BintraySbtIvySnapshots) - import BuildKeys.{ ZincAlternativeCacheName, ZincAlternativeCacheDir } + import BuildAutoImported.{ ZincAlternativeCacheName, ZincAlternativeCacheDir } val AlternativeLocalResolver: Resolver = Resolver.file(ZincAlternativeCacheName, ZincAlternativeCacheDir)(Resolver.ivyStylePatterns) // Naive way of implementing a filter to remove repeated resolvers. - def removeRepeatedResolvers(rs: Seq[Resolver]): Seq[Resolver] = rs.toSet.toVector + def removeRepeatedResolvers(rs: Seq[Resolver]): Seq[Resolver] = rs.distinct } object BuildCommands { import sbt.{ Command, State } - import BuildKeys.{ CompilerBridgeId, ZincApiInfoId, CompilerInterfaceId, bridgeScalaVersions } - val crossTestBridges: Command = { + import BuildAutoImported.bridgeScalaVersions + def crossTestBridges(bridge: Project): Command = { Command.command("crossTestBridges") { (state: State) => (bridgeScalaVersions.flatMap { (bridgeVersion: String) => // Note the ! here. You need this so compilerInterface gets forced to the scalaVersion - s"++ $bridgeVersion!" :: s"$CompilerBridgeId/test" :: Nil + s"++ $bridgeVersion!" :: s"${bridge.id}/test" :: Nil }) ::: (s"++ ${Dependencies.scala212}!" :: state) } } - val publishBridgesAndSet: Command = { + def publishBridgesAndSet(bridge: Project, interface: Project, apiInfo: Project): Command = { Command.args("publishBridgesAndSet", "") { (state, args) => require(args.nonEmpty, "Missing Scala version argument.") val userScalaVersion = args.mkString("") - s"$CompilerInterfaceId/publishLocal" :: bridgeScalaVersions.flatMap { (v: String) => - s"++ $v!" :: s"$ZincApiInfoId/publishLocal" :: s"$CompilerBridgeId/publishLocal" :: Nil + s"${interface.id}/publishLocal" :: bridgeScalaVersions.flatMap { (v: String) => + s"++ $v!" :: s"${apiInfo.id}/publishLocal" :: s"${bridge.id}/publishLocal" :: Nil } ::: s"++ $userScalaVersion!" :: state } } - val publishBridgesAndTest: Command = Command.args("publishBridgesAndTest", "") { - (state, args) => + def publishBridgesAndTest(bridge: Project, interface: Project, apiInfo: Project): Command = { + Command.args("publishBridgesAndTest", "") { (state, args) => require(args.nonEmpty, "Missing arguments to publishBridgesAndTest.") val version = args mkString "" val bridgeCommands: List[String] = bridgeScalaVersions.flatMap { (v: String) => - s"++ $v" :: s"$ZincApiInfoId/publishLocal" :: s"$CompilerBridgeId/publishLocal" :: Nil + s"++ $v" :: s"${apiInfo.id}/publishLocal" :: s"${bridge.id}/publishLocal" :: Nil } - s"$CompilerInterfaceId/publishLocal" :: + s"${interface.id}/publishLocal" :: bridgeCommands ::: s"++ $version" :: s"zincRoot/scalaVersion" :: s"zincRoot/test" :: s"zincRoot/scripted" :: state + } } val release: Command = Command.command("release")(st => "clean" :: "+compile" :: "+publishSigned" :: "reload" :: st) def runBenchmarks(benchmarkProject: Project): Command = { - val dirPath = BuildKeys.benchmarksTestDir.getAbsolutePath + val dirPath = BuildAutoImported.benchmarksTestDir.getAbsolutePath val projectId = benchmarkProject.id val runPreSetup = s"$projectId/run $dirPath" val runBenchmark = s"$projectId/jmh:run -p _tempDir=$dirPath -prof gc" @@ -175,11 +167,17 @@ object BuildImplementation { Command.command("runBenchmarks")(st => runPreSetup :: runBenchmark :: tearDownResources :: st) } - val all: List[Command] = List(crossTestBridges, publishBridgesAndSet, publishBridgesAndTest) + def all(bridge: Project, interface: Project, apiInfo: Project, bench: Project): Seq[Command] = { + val crossTest = crossTestBridges(bridge) + val publishBridges = publishBridgesAndSet(bridge, interface, apiInfo) + val publishBridgesTest = publishBridgesAndTest(bridge, interface, apiInfo) + val runBench = runBenchmarks(bench) + List(crossTest, publishBridges, publishBridgesTest, runBench, release) + } } object BuildDefaults { - import BuildKeys.{ ZincAlternativeCacheName, ZincAlternativeCacheDir } + import BuildAutoImported.{ ZincAlternativeCacheName, ZincAlternativeCacheDir } import sbt.{ Task, State, fileToRichFile, file, File, IO } private[this] val statusCommands = List( List("diff-index", "--cached", "HEAD"), @@ -309,25 +307,25 @@ object BuildImplementation { scriptedRef: Project): Def.Initialize[InputTask[Unit]] = Def.inputTask { val result = scriptedSource(dir => (s: State) => scriptedParser(dir)).parsed // We first publish all the zinc modules - BuildKeys.scriptedPublishAll.value + BuildAutoImported.scriptedPublishAll.value val source = scriptedSource.value val logged = scriptedBufferLog.value val hook = scriptedPrescripted.value // Publish the interface and the bridge for scripted to resolve them correctly - (BuildKeys.zincPublishLocal in interfaceRef).value - (BuildKeys.zincPublishLocal in bridgeRef).value + (BuildAutoImported.zincPublishLocal in interfaceRef).value + (BuildAutoImported.zincPublishLocal in bridgeRef).value val scriptedClasspath = (Keys.fullClasspath in scriptedRef in Test).value - val instance = (Keys.scalaInstance in scriptedRef in Test).value + val instance = (Keys.scalaInstance in scriptedRef).value Scripted.doScripted(scriptedClasspath, instance, source, result, logged, hook) } def zincOnlyScripted(scriptedRef: Project): Def.Initialize[InputTask[Unit]] = Def.inputTask { val result = scriptedSource(dir => (s: State) => scriptedParser(dir)).parsed val scriptedClasspath = (Keys.fullClasspath in scriptedRef in Test).value - val instance = (Keys.scalaInstance in scriptedRef in Test).value + val instance = (Keys.scalaInstance in scriptedRef).value val source = scriptedSource.value val logged = scriptedBufferLog.value val hook = scriptedPrescripted.value @@ -354,6 +352,6 @@ object BuildImplementation { } val tearDownBenchmarkResources: Def.Initialize[Task[Unit]] = - Def.task(IO.delete(BuildKeys.benchmarksTestDir)) + Def.task(IO.delete(BuildAutoImported.benchmarksTestDir)) } } From fc859fadbfc168cedf9a0e8d99c9e4e3db5cbcba Mon Sep 17 00:00:00 2001 From: jvican Date: Thu, 12 Oct 2017 14:22:43 +0200 Subject: [PATCH 04/20] Add checks, remove defaults and add headers to test sources --- bin/run-ci.sh | 2 ++ build.sbt | 2 ++ .../src/test/scala/xsbt/ClassNameSpecification.scala | 7 +++++++ .../src/test/scala/xsbt/DependencySpecification.scala | 7 +++++++ .../src/test/scala/xsbt/ExtractAPISpecification.scala | 7 +++++++ .../xsbt/ExtractUsedNamesPerformanceSpecification.scala | 7 +++++++ .../test/scala/xsbt/ExtractUsedNamesSpecification.scala | 7 +++++++ .../xsbt/InteractiveConsoleInterfaceSpecification.scala | 7 +++++++ .../src/test/scala/xsbt/ScalaCompilerForUnitTesting.scala | 7 +++++++ .../src/test/scala/xsbti/TestCallback.scala | 7 +++++++ .../scala/sbt/internal/inc/ClassCanonicalNameSpec.scala | 7 +++++++ .../scala/sbt/internal/inc/ClassToAPISpecification.scala | 7 +++++++ .../test/scala/xsbt/api/NameHashingSpecification.scala | 7 +++++++ .../src/test/scala/xsbt/ZincBenchmarkSpec.scala | 7 +++++++ .../src/test/scala/sbt/internal/inc/UnitSpec.scala | 7 +++++++ .../sbt/internal/inc/classfile/AnalyzeSpecification.scala | 7 +++++++ .../inc/classfile/JavaCompilerForUnitTesting.scala | 7 +++++++ .../sbt/internal/inc/classfile/ParserSpecification.scala | 7 +++++++ .../src/test/resources/sbt/internal/inc/javac/good.java | 2 -- .../scala/sbt/internal/inc/TestClassFileManager.scala | 7 +++++++ .../scala/sbt/internal/inc/javac/JavaCompilerSpec.scala | 7 +++++++ .../sbt/internal/inc/javac/javaErrorParserSpec.scala | 7 +++++++ .../src/test/scala/sbt/internal/inc/HashSpec.scala | 7 +++++++ .../sbt/internal/inc/BridgeProviderSpecification.scala | 7 +++++++ .../sbt/internal/inc/ZincComponentCompilerSpec.scala | 7 +++++++ .../src/test/scala/sbt/inc/AnalysisGenerators.scala | 7 +++++++ .../inc/binary/BinaryAnalysisFormatSpecification.scala | 7 +++++++ .../scala/sbt/inc/binary/BinaryMappersSpecification.scala | 7 +++++++ .../sbt/inc/text/TextAnalysisFormatSpecification.scala | 7 +++++++ .../src/test/scala/sbt/internal/inc/IncHandler.scala | 7 +++++++ .../test/scala/sbt/internal/inc/IncScriptedRunner.scala | 7 +++++++ .../test/scala/sbt/internal/inc/ScriptedHandlers.scala | 7 +++++++ project/Header.scala | 8 ++------ zinc-compile/src/test/scala/inc/DocSpec.scala | 7 +++++++ .../sjsonnew/support/scalajson/unsafe/FixedParser.scala | 7 +++++++ zinc/src/test/resources/sbt/inc/Depender.scala | 7 +++++++ zinc/src/test/resources/sbt/inc/Depender2.scala | 7 +++++++ zinc/src/test/resources/sbt/inc/Ext1.scala | 7 +++++++ zinc/src/test/resources/sbt/inc/Ext2.scala | 7 +++++++ zinc/src/test/resources/sources/Foo.scala | 7 +++++++ zinc/src/test/resources/sources/Good.scala | 7 +++++++ .../sources/naha/ClientWithImplicitNotUsed.scala | 7 +++++++ .../resources/sources/naha/ClientWithImplicitUsed.scala | 7 +++++++ .../sources/naha/ClientWithoutAnythingUsed.scala | 7 +++++++ .../resources/sources/naha/ClientWithoutImplicit.scala | 7 +++++++ .../src/test/resources/sources/naha/NormalDependecy.scala | 7 +++++++ zinc/src/test/resources/sources/naha/Other.scala | 7 +++++++ zinc/src/test/resources/sources/naha/Other2.scala | 7 +++++++ zinc/src/test/resources/sources/naha/Other3.scala | 7 +++++++ zinc/src/test/resources/sources/naha/WithImplicits.scala | 7 +++++++ zinc/src/test/scala/sbt/inc/IncrementalCompilerSpec.scala | 7 +++++++ .../test/scala/sbt/inc/MultiProjectIncrementalSpec.scala | 7 +++++++ zinc/src/test/scala/sbt/inc/NameHashingCompilerSpec.scala | 7 +++++++ zinc/src/test/scala/sbt/inc/TestResource.scala | 7 +++++++ 54 files changed, 356 insertions(+), 8 deletions(-) diff --git a/bin/run-ci.sh b/bin/run-ci.sh index d7611391d6..aad4fb1492 100755 --- a/bin/run-ci.sh +++ b/bin/run-ci.sh @@ -10,6 +10,8 @@ sbt -Dfile.encoding=UTF-8 \ +mimaReportBinaryIssues \ scalafmt::test \ test:scalafmt::test \ + headerCheck \ + test:headerCheck \ zincRoot/test:compile \ crossTestBridges \ "publishBridgesAndSet $SCALA_VERSION" \ diff --git a/build.sbt b/build.sbt index f642f2024b..4ae44d8aa2 100644 --- a/build.sbt +++ b/build.sbt @@ -136,6 +136,8 @@ lazy val zincCompileCore = (project in internalPath / "zinc-compile-core") sourceManaged in (Compile, generateContrabands) := baseDirectory.value / "src" / "main" / "contraband-java", mimaSettings, + // We disable check here temporarily because of https://github.com/sbt/sbt-header/issues/130 + headerCheck in Test := List() ) // defines Java structures used across Scala versions, such as the API structures and relationships extracted by diff --git a/internal/compiler-bridge/src/test/scala/xsbt/ClassNameSpecification.scala b/internal/compiler-bridge/src/test/scala/xsbt/ClassNameSpecification.scala index aa4c18a7d8..2dda8dc0f1 100644 --- a/internal/compiler-bridge/src/test/scala/xsbt/ClassNameSpecification.scala +++ b/internal/compiler-bridge/src/test/scala/xsbt/ClassNameSpecification.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package xsbt import sbt.internal.inc.UnitSpec diff --git a/internal/compiler-bridge/src/test/scala/xsbt/DependencySpecification.scala b/internal/compiler-bridge/src/test/scala/xsbt/DependencySpecification.scala index f529163f8d..70a8e112c1 100644 --- a/internal/compiler-bridge/src/test/scala/xsbt/DependencySpecification.scala +++ b/internal/compiler-bridge/src/test/scala/xsbt/DependencySpecification.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package xsbt import xsbti.TestCallback.ExtractedClassDependencies diff --git a/internal/compiler-bridge/src/test/scala/xsbt/ExtractAPISpecification.scala b/internal/compiler-bridge/src/test/scala/xsbt/ExtractAPISpecification.scala index 697a441458..d786b183d5 100644 --- a/internal/compiler-bridge/src/test/scala/xsbt/ExtractAPISpecification.scala +++ b/internal/compiler-bridge/src/test/scala/xsbt/ExtractAPISpecification.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package xsbt import xsbti.api._ diff --git a/internal/compiler-bridge/src/test/scala/xsbt/ExtractUsedNamesPerformanceSpecification.scala b/internal/compiler-bridge/src/test/scala/xsbt/ExtractUsedNamesPerformanceSpecification.scala index 1a61fa925f..a1bb27c08e 100644 --- a/internal/compiler-bridge/src/test/scala/xsbt/ExtractUsedNamesPerformanceSpecification.scala +++ b/internal/compiler-bridge/src/test/scala/xsbt/ExtractUsedNamesPerformanceSpecification.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package xsbt import java.net.URI diff --git a/internal/compiler-bridge/src/test/scala/xsbt/ExtractUsedNamesSpecification.scala b/internal/compiler-bridge/src/test/scala/xsbt/ExtractUsedNamesSpecification.scala index e77e301462..e546b1b1e6 100644 --- a/internal/compiler-bridge/src/test/scala/xsbt/ExtractUsedNamesSpecification.scala +++ b/internal/compiler-bridge/src/test/scala/xsbt/ExtractUsedNamesSpecification.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package xsbt import sbt.internal.inc.UnitSpec diff --git a/internal/compiler-bridge/src/test/scala/xsbt/InteractiveConsoleInterfaceSpecification.scala b/internal/compiler-bridge/src/test/scala/xsbt/InteractiveConsoleInterfaceSpecification.scala index 12f82dc223..3419c8ce27 100644 --- a/internal/compiler-bridge/src/test/scala/xsbt/InteractiveConsoleInterfaceSpecification.scala +++ b/internal/compiler-bridge/src/test/scala/xsbt/InteractiveConsoleInterfaceSpecification.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package xsbt import sbt.internal.inc.UnitSpec diff --git a/internal/compiler-bridge/src/test/scala/xsbt/ScalaCompilerForUnitTesting.scala b/internal/compiler-bridge/src/test/scala/xsbt/ScalaCompilerForUnitTesting.scala index 423d968c20..c6e11cc8ec 100644 --- a/internal/compiler-bridge/src/test/scala/xsbt/ScalaCompilerForUnitTesting.scala +++ b/internal/compiler-bridge/src/test/scala/xsbt/ScalaCompilerForUnitTesting.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package xsbt import xsbti.TestCallback.ExtractedClassDependencies diff --git a/internal/compiler-interface/src/test/scala/xsbti/TestCallback.scala b/internal/compiler-interface/src/test/scala/xsbti/TestCallback.scala index 7f0c6eed3f..e55309348d 100644 --- a/internal/compiler-interface/src/test/scala/xsbti/TestCallback.scala +++ b/internal/compiler-interface/src/test/scala/xsbti/TestCallback.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package xsbti import java.io.File diff --git a/internal/zinc-apiinfo/src/test/scala/sbt/internal/inc/ClassCanonicalNameSpec.scala b/internal/zinc-apiinfo/src/test/scala/sbt/internal/inc/ClassCanonicalNameSpec.scala index ed9fc0af0f..0617bb6096 100644 --- a/internal/zinc-apiinfo/src/test/scala/sbt/internal/inc/ClassCanonicalNameSpec.scala +++ b/internal/zinc-apiinfo/src/test/scala/sbt/internal/inc/ClassCanonicalNameSpec.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt package internal package inc diff --git a/internal/zinc-apiinfo/src/test/scala/sbt/internal/inc/ClassToAPISpecification.scala b/internal/zinc-apiinfo/src/test/scala/sbt/internal/inc/ClassToAPISpecification.scala index 709c61a217..b5d509d1f4 100644 --- a/internal/zinc-apiinfo/src/test/scala/sbt/internal/inc/ClassToAPISpecification.scala +++ b/internal/zinc-apiinfo/src/test/scala/sbt/internal/inc/ClassToAPISpecification.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt package internal package inc diff --git a/internal/zinc-apiinfo/src/test/scala/xsbt/api/NameHashingSpecification.scala b/internal/zinc-apiinfo/src/test/scala/xsbt/api/NameHashingSpecification.scala index 877b026dee..1d489c2e0b 100644 --- a/internal/zinc-apiinfo/src/test/scala/xsbt/api/NameHashingSpecification.scala +++ b/internal/zinc-apiinfo/src/test/scala/xsbt/api/NameHashingSpecification.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package xsbt.api import xsbti.api._ diff --git a/internal/zinc-benchmarks/src/test/scala/xsbt/ZincBenchmarkSpec.scala b/internal/zinc-benchmarks/src/test/scala/xsbt/ZincBenchmarkSpec.scala index e0ebc143e0..7cb49ca212 100644 --- a/internal/zinc-benchmarks/src/test/scala/xsbt/ZincBenchmarkSpec.scala +++ b/internal/zinc-benchmarks/src/test/scala/xsbt/ZincBenchmarkSpec.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package xsbt import org.scalatest.FunSuite diff --git a/internal/zinc-classfile/src/test/scala/sbt/internal/inc/UnitSpec.scala b/internal/zinc-classfile/src/test/scala/sbt/internal/inc/UnitSpec.scala index bf2d70ea51..3e3794f340 100644 --- a/internal/zinc-classfile/src/test/scala/sbt/internal/inc/UnitSpec.scala +++ b/internal/zinc-classfile/src/test/scala/sbt/internal/inc/UnitSpec.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt package internal package inc diff --git a/internal/zinc-classfile/src/test/scala/sbt/internal/inc/classfile/AnalyzeSpecification.scala b/internal/zinc-classfile/src/test/scala/sbt/internal/inc/classfile/AnalyzeSpecification.scala index 913218d331..0192eeae6f 100644 --- a/internal/zinc-classfile/src/test/scala/sbt/internal/inc/classfile/AnalyzeSpecification.scala +++ b/internal/zinc-classfile/src/test/scala/sbt/internal/inc/classfile/AnalyzeSpecification.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt package internal package inc diff --git a/internal/zinc-classfile/src/test/scala/sbt/internal/inc/classfile/JavaCompilerForUnitTesting.scala b/internal/zinc-classfile/src/test/scala/sbt/internal/inc/classfile/JavaCompilerForUnitTesting.scala index f9e0ed3602..c7746f57cf 100644 --- a/internal/zinc-classfile/src/test/scala/sbt/internal/inc/classfile/JavaCompilerForUnitTesting.scala +++ b/internal/zinc-classfile/src/test/scala/sbt/internal/inc/classfile/JavaCompilerForUnitTesting.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt package internal package inc diff --git a/internal/zinc-classfile/src/test/scala/sbt/internal/inc/classfile/ParserSpecification.scala b/internal/zinc-classfile/src/test/scala/sbt/internal/inc/classfile/ParserSpecification.scala index 338e853c42..d1ae7e55ec 100644 --- a/internal/zinc-classfile/src/test/scala/sbt/internal/inc/classfile/ParserSpecification.scala +++ b/internal/zinc-classfile/src/test/scala/sbt/internal/inc/classfile/ParserSpecification.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt package internal package inc diff --git a/internal/zinc-compile-core/src/test/resources/sbt/internal/inc/javac/good.java b/internal/zinc-compile-core/src/test/resources/sbt/internal/inc/javac/good.java index d4004211a0..63a0bb01bf 100644 --- a/internal/zinc-compile-core/src/test/resources/sbt/internal/inc/javac/good.java +++ b/internal/zinc-compile-core/src/test/resources/sbt/internal/inc/javac/good.java @@ -1,5 +1,3 @@ - - public class good { public static String test() { return "Hello"; diff --git a/internal/zinc-compile-core/src/test/scala/sbt/internal/inc/TestClassFileManager.scala b/internal/zinc-compile-core/src/test/scala/sbt/internal/inc/TestClassFileManager.scala index 05c2885a69..00e6e5bc1f 100644 --- a/internal/zinc-compile-core/src/test/scala/sbt/internal/inc/TestClassFileManager.scala +++ b/internal/zinc-compile-core/src/test/scala/sbt/internal/inc/TestClassFileManager.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt.internal.inc import java.io.File diff --git a/internal/zinc-compile-core/src/test/scala/sbt/internal/inc/javac/JavaCompilerSpec.scala b/internal/zinc-compile-core/src/test/scala/sbt/internal/inc/javac/JavaCompilerSpec.scala index d1e0bae3b7..eb2c160cf4 100644 --- a/internal/zinc-compile-core/src/test/scala/sbt/internal/inc/javac/JavaCompilerSpec.scala +++ b/internal/zinc-compile-core/src/test/scala/sbt/internal/inc/javac/JavaCompilerSpec.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt package internal package inc diff --git a/internal/zinc-compile-core/src/test/scala/sbt/internal/inc/javac/javaErrorParserSpec.scala b/internal/zinc-compile-core/src/test/scala/sbt/internal/inc/javac/javaErrorParserSpec.scala index 862a7f4d5e..8c2115dbef 100644 --- a/internal/zinc-compile-core/src/test/scala/sbt/internal/inc/javac/javaErrorParserSpec.scala +++ b/internal/zinc-compile-core/src/test/scala/sbt/internal/inc/javac/javaErrorParserSpec.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt package internal package inc diff --git a/internal/zinc-core/src/test/scala/sbt/internal/inc/HashSpec.scala b/internal/zinc-core/src/test/scala/sbt/internal/inc/HashSpec.scala index 8f94fc7510..992ab34e83 100644 --- a/internal/zinc-core/src/test/scala/sbt/internal/inc/HashSpec.scala +++ b/internal/zinc-core/src/test/scala/sbt/internal/inc/HashSpec.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt package internal package inc diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index abd2485a4c..9170152265 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt.internal.inc import java.io.File diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala index 3fbd1a24f6..d671240a60 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/ZincComponentCompilerSpec.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt.internal.inc import sbt.internal.util.ConsoleLogger diff --git a/internal/zinc-persist/src/test/scala/sbt/inc/AnalysisGenerators.scala b/internal/zinc-persist/src/test/scala/sbt/inc/AnalysisGenerators.scala index 468eb0b1fa..0edc7e2abe 100644 --- a/internal/zinc-persist/src/test/scala/sbt/inc/AnalysisGenerators.scala +++ b/internal/zinc-persist/src/test/scala/sbt/inc/AnalysisGenerators.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt package internal package inc diff --git a/internal/zinc-persist/src/test/scala/sbt/inc/binary/BinaryAnalysisFormatSpecification.scala b/internal/zinc-persist/src/test/scala/sbt/inc/binary/BinaryAnalysisFormatSpecification.scala index e0f4766f27..cbfa70d248 100644 --- a/internal/zinc-persist/src/test/scala/sbt/inc/binary/BinaryAnalysisFormatSpecification.scala +++ b/internal/zinc-persist/src/test/scala/sbt/inc/binary/BinaryAnalysisFormatSpecification.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt.inc.binary import java.io.File diff --git a/internal/zinc-persist/src/test/scala/sbt/inc/binary/BinaryMappersSpecification.scala b/internal/zinc-persist/src/test/scala/sbt/inc/binary/BinaryMappersSpecification.scala index acd8923258..96511587b4 100644 --- a/internal/zinc-persist/src/test/scala/sbt/inc/binary/BinaryMappersSpecification.scala +++ b/internal/zinc-persist/src/test/scala/sbt/inc/binary/BinaryMappersSpecification.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt.inc.binary import java.nio.file.Paths diff --git a/internal/zinc-persist/src/test/scala/sbt/inc/text/TextAnalysisFormatSpecification.scala b/internal/zinc-persist/src/test/scala/sbt/inc/text/TextAnalysisFormatSpecification.scala index de5fe13911..854ecd320c 100644 --- a/internal/zinc-persist/src/test/scala/sbt/inc/text/TextAnalysisFormatSpecification.scala +++ b/internal/zinc-persist/src/test/scala/sbt/inc/text/TextAnalysisFormatSpecification.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt.inc.text import java.io.{ BufferedReader, File, StringReader, StringWriter } diff --git a/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncHandler.scala b/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncHandler.scala index 8fdf8417ea..53ecd9e51b 100644 --- a/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncHandler.scala +++ b/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncHandler.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt package internal package inc diff --git a/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncScriptedRunner.scala b/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncScriptedRunner.scala index 0f5cca876b..ea88044627 100644 --- a/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncScriptedRunner.scala +++ b/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncScriptedRunner.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt.internal.inc import java.io.File diff --git a/internal/zinc-scripted/src/test/scala/sbt/internal/inc/ScriptedHandlers.scala b/internal/zinc-scripted/src/test/scala/sbt/internal/inc/ScriptedHandlers.scala index dc23dc9cfa..193db7dff9 100644 --- a/internal/zinc-scripted/src/test/scala/sbt/internal/inc/ScriptedHandlers.scala +++ b/internal/zinc-scripted/src/test/scala/sbt/internal/inc/ScriptedHandlers.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt.internal.inc import java.io.File diff --git a/project/Header.scala b/project/Header.scala index b6daaa577a..0cf167e33b 100644 --- a/project/Header.scala +++ b/project/Header.scala @@ -7,19 +7,15 @@ import de.heikoseeberger.sbtheader.HeaderPlugin.{autoImport => SbtHeaderKeys} object CustomHeaderPlugin extends AutoPlugin { override def requires = plugins.JvmPlugin && HeaderPlugin override def trigger = allRequirements - import SbtHeaderKeys.{HeaderFileType, HeaderCommentStyle, HeaderLicense} + import SbtHeaderKeys.HeaderLicense override def projectSettings = Seq( - SbtHeaderKeys.headerMappings ++= Map( - HeaderFileType.scala -> HeaderCommentStyle.CStyleBlockComment, - HeaderFileType.java -> HeaderCommentStyle.CStyleBlockComment - ), SbtHeaderKeys.headerLicense := Some(HeaderLicense.Custom( """|Zinc - The incremental compiler for Scala. |Copyright 2011 - 2017, Lightbend, Inc. |Copyright 2008 - 2010, Mark Harrah |This software is released under the terms written in LICENSE. |""".stripMargin - )) + )), ) } diff --git a/zinc-compile/src/test/scala/inc/DocSpec.scala b/zinc-compile/src/test/scala/inc/DocSpec.scala index 7eafe4aa95..46628a6dc7 100644 --- a/zinc-compile/src/test/scala/inc/DocSpec.scala +++ b/zinc-compile/src/test/scala/inc/DocSpec.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt package inc diff --git a/zinc-compile/src/test/scala/sjsonnew/support/scalajson/unsafe/FixedParser.scala b/zinc-compile/src/test/scala/sjsonnew/support/scalajson/unsafe/FixedParser.scala index ec55b454ab..36de4e8871 100644 --- a/zinc-compile/src/test/scala/sjsonnew/support/scalajson/unsafe/FixedParser.scala +++ b/zinc-compile/src/test/scala/sjsonnew/support/scalajson/unsafe/FixedParser.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sjsonnew package support.scalajson.unsafe diff --git a/zinc/src/test/resources/sbt/inc/Depender.scala b/zinc/src/test/resources/sbt/inc/Depender.scala index 966775f655..0017b8b898 100644 --- a/zinc/src/test/resources/sbt/inc/Depender.scala +++ b/zinc/src/test/resources/sbt/inc/Depender.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package test.pkg object Depender { diff --git a/zinc/src/test/resources/sbt/inc/Depender2.scala b/zinc/src/test/resources/sbt/inc/Depender2.scala index 7254665c40..7b6e1cb79f 100644 --- a/zinc/src/test/resources/sbt/inc/Depender2.scala +++ b/zinc/src/test/resources/sbt/inc/Depender2.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package test.pkg object Depender2 { diff --git a/zinc/src/test/resources/sbt/inc/Ext1.scala b/zinc/src/test/resources/sbt/inc/Ext1.scala index 5b0d1ccd87..9eaa746048 100644 --- a/zinc/src/test/resources/sbt/inc/Ext1.scala +++ b/zinc/src/test/resources/sbt/inc/Ext1.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package test.pkg object Ext1 { diff --git a/zinc/src/test/resources/sbt/inc/Ext2.scala b/zinc/src/test/resources/sbt/inc/Ext2.scala index e93423b850..c66c33e487 100644 --- a/zinc/src/test/resources/sbt/inc/Ext2.scala +++ b/zinc/src/test/resources/sbt/inc/Ext2.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package test.pkg object Ext2 { diff --git a/zinc/src/test/resources/sources/Foo.scala b/zinc/src/test/resources/sources/Foo.scala index 87f4fa5fa7..071a88404e 100644 --- a/zinc/src/test/resources/sources/Foo.scala +++ b/zinc/src/test/resources/sources/Foo.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package pkg object Foo { diff --git a/zinc/src/test/resources/sources/Good.scala b/zinc/src/test/resources/sources/Good.scala index acb2590edc..3d3a9f7b5d 100644 --- a/zinc/src/test/resources/sources/Good.scala +++ b/zinc/src/test/resources/sources/Good.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package pkg object Good extends App { diff --git a/zinc/src/test/resources/sources/naha/ClientWithImplicitNotUsed.scala b/zinc/src/test/resources/sources/naha/ClientWithImplicitNotUsed.scala index bc94001337..30e4a0f9cb 100644 --- a/zinc/src/test/resources/sources/naha/ClientWithImplicitNotUsed.scala +++ b/zinc/src/test/resources/sources/naha/ClientWithImplicitNotUsed.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package naha object ClientWithImplicitNotUsed { diff --git a/zinc/src/test/resources/sources/naha/ClientWithImplicitUsed.scala b/zinc/src/test/resources/sources/naha/ClientWithImplicitUsed.scala index ab83737eaa..1e022dc841 100644 --- a/zinc/src/test/resources/sources/naha/ClientWithImplicitUsed.scala +++ b/zinc/src/test/resources/sources/naha/ClientWithImplicitUsed.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package naha object ClientWithImplicitUsed { diff --git a/zinc/src/test/resources/sources/naha/ClientWithoutAnythingUsed.scala b/zinc/src/test/resources/sources/naha/ClientWithoutAnythingUsed.scala index 56af96f9b4..35b1a4a666 100644 --- a/zinc/src/test/resources/sources/naha/ClientWithoutAnythingUsed.scala +++ b/zinc/src/test/resources/sources/naha/ClientWithoutAnythingUsed.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package naha object ClientWithoutAnythingUsed { diff --git a/zinc/src/test/resources/sources/naha/ClientWithoutImplicit.scala b/zinc/src/test/resources/sources/naha/ClientWithoutImplicit.scala index 2bcf3da0ab..f06ccbf0d8 100644 --- a/zinc/src/test/resources/sources/naha/ClientWithoutImplicit.scala +++ b/zinc/src/test/resources/sources/naha/ClientWithoutImplicit.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package naha object ClientWithoutImplicit { diff --git a/zinc/src/test/resources/sources/naha/NormalDependecy.scala b/zinc/src/test/resources/sources/naha/NormalDependecy.scala index b24bdf1f03..9daffc9102 100644 --- a/zinc/src/test/resources/sources/naha/NormalDependecy.scala +++ b/zinc/src/test/resources/sources/naha/NormalDependecy.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package naha object NormalDependecy { diff --git a/zinc/src/test/resources/sources/naha/Other.scala b/zinc/src/test/resources/sources/naha/Other.scala index 4cb71e1560..da80440262 100644 --- a/zinc/src/test/resources/sources/naha/Other.scala +++ b/zinc/src/test/resources/sources/naha/Other.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package naha object Other { diff --git a/zinc/src/test/resources/sources/naha/Other2.scala b/zinc/src/test/resources/sources/naha/Other2.scala index 897e846135..d5f5188d26 100644 --- a/zinc/src/test/resources/sources/naha/Other2.scala +++ b/zinc/src/test/resources/sources/naha/Other2.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package naha object Other2 { diff --git a/zinc/src/test/resources/sources/naha/Other3.scala b/zinc/src/test/resources/sources/naha/Other3.scala index da855c1699..c11180d162 100644 --- a/zinc/src/test/resources/sources/naha/Other3.scala +++ b/zinc/src/test/resources/sources/naha/Other3.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package naha object Other3 { diff --git a/zinc/src/test/resources/sources/naha/WithImplicits.scala b/zinc/src/test/resources/sources/naha/WithImplicits.scala index ee88d725a4..ca469d2e8d 100644 --- a/zinc/src/test/resources/sources/naha/WithImplicits.scala +++ b/zinc/src/test/resources/sources/naha/WithImplicits.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package naha object WithImplicits { diff --git a/zinc/src/test/scala/sbt/inc/IncrementalCompilerSpec.scala b/zinc/src/test/scala/sbt/inc/IncrementalCompilerSpec.scala index 6f3ff188d0..0e7c55b721 100644 --- a/zinc/src/test/scala/sbt/inc/IncrementalCompilerSpec.scala +++ b/zinc/src/test/scala/sbt/inc/IncrementalCompilerSpec.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt.inc import xsbti.compile.AnalysisStore diff --git a/zinc/src/test/scala/sbt/inc/MultiProjectIncrementalSpec.scala b/zinc/src/test/scala/sbt/inc/MultiProjectIncrementalSpec.scala index 0be56c2c21..aa7129567f 100644 --- a/zinc/src/test/scala/sbt/inc/MultiProjectIncrementalSpec.scala +++ b/zinc/src/test/scala/sbt/inc/MultiProjectIncrementalSpec.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt.inc import java.io.File diff --git a/zinc/src/test/scala/sbt/inc/NameHashingCompilerSpec.scala b/zinc/src/test/scala/sbt/inc/NameHashingCompilerSpec.scala index 60d486709a..49e1d596e9 100644 --- a/zinc/src/test/scala/sbt/inc/NameHashingCompilerSpec.scala +++ b/zinc/src/test/scala/sbt/inc/NameHashingCompilerSpec.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt.inc import java.nio.file.Paths diff --git a/zinc/src/test/scala/sbt/inc/TestResource.scala b/zinc/src/test/scala/sbt/inc/TestResource.scala index 9b2cf643d0..03c64525e6 100644 --- a/zinc/src/test/scala/sbt/inc/TestResource.scala +++ b/zinc/src/test/scala/sbt/inc/TestResource.scala @@ -1,3 +1,10 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * This software is released under the terms written in LICENSE. + */ + package sbt.inc import java.io.File From d46f22b757ada40b7cff56c945ac107e8792d82b Mon Sep 17 00:00:00 2001 From: jvican Date: Thu, 12 Oct 2017 14:33:00 +0200 Subject: [PATCH 05/20] Add build information to the CONTRIBUTING guide --- CONTRIBUTING.md | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a59c16b7fc..f4aebab3e0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -31,8 +31,7 @@ Once you understand the basics of incremental compilation, start having a look at open tickets you can help with. All issues are labelled and will give you an idea about its difficulty and scope. -Hacking on Zinc should not seem like a difficult task. Zinc does not implement -a compiler, it defines the logic to analyse dependencies based on the compiler +Hacking on Zinc should not seem like a difficult task. Zinc does not implement a compiler, it defines the logic to analyse dependencies based on the compiler API and creates all the required infrastructure around it to let build tools use it. @@ -55,6 +54,48 @@ bridge, you don't need to run these benchmarks. If you need any help, the Zinc team hangs out in [sbt/zinc-contrib][]. Feel free to ask any question. +### Getting familiar with the build + +#### Project structure + +As of now, the current project structure is not as simple as it can be and we +believe that it can be simpler in the future. However, as of now, no work is +happening in this area because it's deemed to have low impact on the overall +quality of the project. + +How is the Zinc build structured? Let's see it. + +|Project name| Project description| +|------------|--------------------| +|zincRoot| The root of the project. Aggregates all projects except the benchmarks.| +|zinc|The user-facing Zinc incremental compiler.| +|zincTesting|The project that defines testing facilities.| +|zincCompile|A thin wrapper that provides doc capabilities.| +|zincPersist|The project that persists incremental compiler's data into a binary file.| +|zincCore|The project that defines relations, analysis, stamps, and essential core utils.| +|zincBenchmarks|The project that defines the benchmarks.| +|zincIvyIntegration|The project that defines the ivy utilities to fetch compiler bridges.| +|zincCompileCore|The project that interfaces with the compiler API and provides compilation capabilities.| +|zincApiInfo|The project that defines name hashes and provides way to interpret api changes.| +|zincClassfile|The project that parses class files to provide Java incremental compilation.| +|zincClasspath|The project that provides basic utilities to load libraries with classloaders and represents Scala instances.| +|zincScripted|The project that defines the scripted logic to run Zinc's integration test suite.| +|compilerInterface|The public binary interface used to connect the bridges with the Zinc modules. It is written in Java and uses Contraband.| +|compilerBridge|The module that defines the compiler plugin phases that provide incrementality for all Scala versions.| + +#### Build-specific commands/keys + +The sbt build defines several keys that help contributors run and test Zinc. +Zinc's build requires the compiler bridges to be published before tests are run +(compiler bridges are compiler-specific Scala sources that need to be fetched +to perform incremental compilation). + +|Key|Use| +|---|---| +|crossTestBridges|Runs compiler bridge unit tests for all scala versions.| +|publishBridgesAndTest|Publish bridges and test the whole incremental compiler.| +|publishBridgesAndSet|Publish bridges and set the current Scala version.| + ### Benchmarking Zinc To run JMH benchmarks, run the sbt task `runBenchmarks`. By default, From 2ad8ac6a33c19fd5914b10426657634d5a3bf58d Mon Sep 17 00:00:00 2001 From: jvican Date: Thu, 12 Oct 2017 14:46:13 +0200 Subject: [PATCH 06/20] Add project structure diagram to the guide --- CONTRIBUTING.md | 7 +++++++ docs/project-structure.png | Bin 0 -> 58111 bytes 2 files changed, 7 insertions(+) create mode 100644 docs/project-structure.png diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f4aebab3e0..518550c8bc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -83,6 +83,13 @@ How is the Zinc build structured? Let's see it. |compilerInterface|The public binary interface used to connect the bridges with the Zinc modules. It is written in Java and uses Contraband.| |compilerBridge|The module that defines the compiler plugin phases that provide incrementality for all Scala versions.| +If you want to visualize the relationships between the projects, have a look at +the following diagram: + +![Diagram of projects](docs/project-structure.png) + +Note: ignore `jar2`, `jar1` and `classesDep1`. + #### Build-specific commands/keys The sbt build defines several keys that help contributors run and test Zinc. diff --git a/docs/project-structure.png b/docs/project-structure.png new file mode 100644 index 0000000000000000000000000000000000000000..ef017fa3416409b1cc3d4e6d745f93f7b5dd45b7 GIT binary patch literal 58111 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çr#FI;sB8U1dJDG&WQ7{Kc{9-(@iSB^3FQV z?dI2>COtYOGINAn36dz5L*BF)Gc|Bj*O494yN?gZK|KjzQn%Tsm~j2!LA+&v>GqD{ zr7g0rWNhFg-X8%$1fj$$un#Z7KH{P#aOolf^AXWi(2J?zQa Gowb>#6`Z4zX;g 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

oJ9FFPTbtt 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 literal 0 HcmV?d00001 From fd34606b8cc315cfc1a510d27066945d82b26eb7 Mon Sep 17 00:00:00 2001 From: jvican Date: Thu, 12 Oct 2017 16:12:20 +0200 Subject: [PATCH 07/20] Address last piece of feedback from Dale --- project/BuildPlugin.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/project/BuildPlugin.scala b/project/BuildPlugin.scala index 17a803ee24..6a4b781efa 100644 --- a/project/BuildPlugin.scala +++ b/project/BuildPlugin.scala @@ -12,7 +12,6 @@ object BuildPlugin extends AutoPlugin { override def projectSettings: Seq[Def.Setting[_]] = BuildImplementation.projectSettings override def buildSettings: Seq[Def.Setting[_]] = BuildImplementation.buildSettings - override def globalSettings: Seq[Def.Setting[_]] = Nil } trait BuildKeys { @@ -97,7 +96,7 @@ object BuildImplementation { ) object BuildResolvers { - import sbt.{ MavenRepository, file } + import sbt.MavenRepository val TypesafeReleases: Resolver = Resolver.typesafeIvyRepo("releases") val SonatypeSnapshots: Resolver = Resolver.sonatypeRepo("snapshots") val BintrayMavenReleases: Resolver = From e9114f2f85f38f64d16d549117db4d08c2d1f94b Mon Sep 17 00:00:00 2001 From: jvican Date: Thu, 12 Oct 2017 17:11:17 +0200 Subject: [PATCH 08/20] Add sbt-release-early `sbt-scalafmt` is removed because it's already brought in by `sbt-houserules`. --- project/plugins.sbt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index c6926192a9..0c97245f66 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,9 +1,7 @@ addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.2.27") -addSbtPlugin("org.foundweekends" % "sbt-bintray" % "0.5.1") -addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0-M1") -addSbtPlugin("com.lucidchart" % "sbt-scalafmt" % "1.12") addSbtPlugin("de.heikoseeberger" % "sbt-header" % "3.0.2") -addSbtPlugin("org.scala-sbt" % "sbt-houserules" % "0.3.3") +addSbtPlugin("ch.epfl.scala" % "sbt-release-early" % "2.0.0") +addSbtPlugin("org.scala-sbt" % "sbt-houserules" % "0.3.4") addSbtPlugin("org.scala-sbt" % "sbt-contraband" % "0.3.0") addSbtPlugin("com.thesamet" % "sbt-protoc" % "0.99.12-rc5") libraryDependencies += "com.trueaccord.scalapb" %% "compilerplugin" % "0.6.0" From 96519ab0faae72d7803b757e11a56bce4b191f38 Mon Sep 17 00:00:00 2001 From: jvican Date: Thu, 12 Oct 2017 17:32:31 +0200 Subject: [PATCH 09/20] Set up sbt-release-early We only set it up for Bintray for now. In the future we can release to Sonatype, but we need either sbt org's credentials or the sbt org to give us Sonatype rights to publish to "org.scala-sbt" or change org to "ch.epfl.scala". --- .drone.yml | 16 +++++++++++++++- .drone.yml.sig | 2 +- project/BuildPlugin.scala | 17 +++++++++-------- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/.drone.yml b/.drone.yml index 7c57dbafb9..f38a2449a0 100644 --- a/.drone.yml +++ b/.drone.yml @@ -12,11 +12,25 @@ pipeline: event: [push, pull_request, tag, deployment] tests: - image: scalacenter/scala:1.0 + image: scalacenter/scala:1.3 commands: - git fetch --tags && git log | head -n 20 - ./bin/run-ci.sh ${CI_SCALA_VERSION} + publish: + image: scalacenter/scala:1.3 + volumes: + - /scalacenter:/keys + when: + event: [ push, tag, deployment ] + status: success + commands: + # To know what we're releasing + - git log | head -n 20 + - /usr/local/bin/setup_keys.sh + - /usr/local/bin/store_credentials.sh + - sbt releaseEarly + # Save folders in distributed cache sftp_cache_rebuild: image: plugins/sftp-cache diff --git a/.drone.yml.sig b/.drone.yml.sig index 73a9c94e73..31781fd27b 100644 --- a/.drone.yml.sig +++ b/.drone.yml.sig @@ -1 +1 @@ -eyJhbGciOiJIUzI1NiJ9.cGlwZWxpbmU6CiAgIyBGZXRjaCBmb2xkZXJzIGZyb20gZGlzdHJpYnV0ZWQgY2FjaGUKICBzZnRwX2NhY2hlX3Jlc3RvcmU6CiAgICBpbWFnZTogcGx1Z2lucy9zZnRwLWNhY2hlCiAgICByZXN0b3JlOiB0cnVlCiAgICBtb3VudDoKICAgICAgLSAvZHJvbmUvLml2eTIKICAgICAgLSAvZHJvbmUvLmNvdXJzaWVyLWNhY2hlCiAgICAgIC0gL2Ryb25lLy5zYnQKICAgICAgLSAvZHJvbmUvLmdpdAogICAgd2hlbjoKICAgICAgZXZlbnQ6IFtwdXNoLCBwdWxsX3JlcXVlc3QsIHRhZywgZGVwbG95bWVudF0KCiAgdGVzdHM6CiAgICBpbWFnZTogc2NhbGFjZW50ZXIvc2NhbGE6MS4wCiAgICBjb21tYW5kczoKICAgICAgLSBnaXQgZmV0Y2ggLS10YWdzICYmIGdpdCBsb2cgfCBoZWFkIC1uIDIwCiAgICAgIC0gLi9iaW4vcnVuLWNpLnNoICR7Q0lfU0NBTEFfVkVSU0lPTn0KCiAgIyBTYXZlIGZvbGRlcnMgaW4gZGlzdHJpYnV0ZWQgY2FjaGUKICBzZnRwX2NhY2hlX3JlYnVpbGQ6CiAgICBpbWFnZTogcGx1Z2lucy9zZnRwLWNhY2hlCiAgICByZWJ1aWxkOiB0cnVlCiAgICBtb3VudDoKICAgICAgLSAvZHJvbmUvLml2eTIKICAgICAgLSAvZHJvbmUvLmNvdXJzaWVyLWNhY2hlCiAgICAgIC0gL2Ryb25lLy5zYnQKICAgICAgLSAvZHJvbmUvLmdpdAogICAgd2hlbjoKICAgICAgZXZlbnQ6IFtwdXNoLCBwdWxsX3JlcXVlc3QsIHRhZywgZGVwbG95bWVudF0KCm1hdHJpeDoKICBDSV9TQ0FMQV9WRVJTSU9OOgogICAgLSAyLjExLjExCiAgICAtIDIuMTIuMwo.usuc6GVWQgjD1XYQW9Fd8U8N7Qj1b6WfmGdtIn44Q-8 \ No newline at end of file +eyJhbGciOiJIUzI1NiJ9.cGlwZWxpbmU6CiAgIyBGZXRjaCBmb2xkZXJzIGZyb20gZGlzdHJpYnV0ZWQgY2FjaGUKICBzZnRwX2NhY2hlX3Jlc3RvcmU6CiAgICBpbWFnZTogcGx1Z2lucy9zZnRwLWNhY2hlCiAgICByZXN0b3JlOiB0cnVlCiAgICBtb3VudDoKICAgICAgLSAvZHJvbmUvLml2eTIKICAgICAgLSAvZHJvbmUvLmNvdXJzaWVyLWNhY2hlCiAgICAgIC0gL2Ryb25lLy5zYnQKICAgICAgLSAvZHJvbmUvLmdpdAogICAgd2hlbjoKICAgICAgZXZlbnQ6IFtwdXNoLCBwdWxsX3JlcXVlc3QsIHRhZywgZGVwbG95bWVudF0KCiAgdGVzdHM6CiAgICBpbWFnZTogc2NhbGFjZW50ZXIvc2NhbGE6MS4zCiAgICBjb21tYW5kczoKICAgICAgLSBnaXQgZmV0Y2ggLS10YWdzICYmIGdpdCBsb2cgfCBoZWFkIC1uIDIwCiAgICAgIC0gLi9iaW4vcnVuLWNpLnNoICR7Q0lfU0NBTEFfVkVSU0lPTn0KCiAgcHVibGlzaDoKICAgIGltYWdlOiBzY2FsYWNlbnRlci9zY2FsYToxLjMKICAgIHZvbHVtZXM6CiAgICAgIC0gL3NjYWxhY2VudGVyOi9rZXlzCiAgICB3aGVuOgogICAgICBldmVudDogWyBwdXNoLCB0YWcsIGRlcGxveW1lbnQgXQogICAgICBzdGF0dXM6IHN1Y2Nlc3MKICAgIGNvbW1hbmRzOgogICAgICAjIFRvIGtub3cgd2hhdCB3ZSdyZSByZWxlYXNpbmcKICAgICAgLSBnaXQgbG9nIHwgaGVhZCAtbiAyMAogICAgICAtIC91c3IvbG9jYWwvYmluL3NldHVwX2tleXMuc2gKICAgICAgLSAvdXNyL2xvY2FsL2Jpbi9zdG9yZV9jcmVkZW50aWFscy5zaAogICAgICAtIHNidCByZWxlYXNlRWFybHkKCiAgIyBTYXZlIGZvbGRlcnMgaW4gZGlzdHJpYnV0ZWQgY2FjaGUKICBzZnRwX2NhY2hlX3JlYnVpbGQ6CiAgICBpbWFnZTogcGx1Z2lucy9zZnRwLWNhY2hlCiAgICByZWJ1aWxkOiB0cnVlCiAgICBtb3VudDoKICAgICAgLSAvZHJvbmUvLml2eTIKICAgICAgLSAvZHJvbmUvLmNvdXJzaWVyLWNhY2hlCiAgICAgIC0gL2Ryb25lLy5zYnQKICAgICAgLSAvZHJvbmUvLmdpdAogICAgd2hlbjoKICAgICAgZXZlbnQ6IFtwdXNoLCBwdWxsX3JlcXVlc3QsIHRhZywgZGVwbG95bWVudF0KCm1hdHJpeDoKICBDSV9TQ0FMQV9WRVJTSU9OOgogICAgLSAyLjExLjExCiAgICAtIDIuMTIuMwo.hqDOPvurmUpIxCK_VDzn_v7mH6DPqZBSR6EqO-8mJm8 \ No newline at end of file diff --git a/project/BuildPlugin.scala b/project/BuildPlugin.scala index 6a4b781efa..578de049e6 100644 --- a/project/BuildPlugin.scala +++ b/project/BuildPlugin.scala @@ -1,12 +1,18 @@ import sbt.{ AutoPlugin, Compile, Def, Keys, Resolver, Test, TestFrameworks, Tests, URL, Project } +import com.typesafe.sbt.GitPlugin import com.typesafe.sbt.SbtGit.{ git => GitKeys } import bintray.BintrayPlugin.{ autoImport => BintrayKeys } +import ch.epfl.scala.sbt.release.ReleaseEarlyPlugin +import ch.epfl.scala.sbt.release.ReleaseEarlyPlugin.{autoImport => ReleaseEarlyKeys} +import com.lucidchart.sbt.scalafmt.ScalafmtCorePlugin import com.lucidchart.sbt.scalafmt.ScalafmtCorePlugin.{ autoImport => ScalafmtKeys } import com.lucidchart.sbt.scalafmt.ScalafmtSbtPlugin.autoImport.Sbt import com.typesafe.tools.mima.plugin.MimaKeys +import com.typesafe.tools.mima.plugin.MimaPlugin object BuildPlugin extends AutoPlugin { - override def requires = sbt.plugins.JvmPlugin + override def requires = + sbt.plugins.JvmPlugin && ScalafmtCorePlugin && GitPlugin && ReleaseEarlyPlugin && MimaPlugin override def trigger = allRequirements val autoImport = BuildAutoImported @@ -61,7 +67,6 @@ object BuildAutoImported extends BuildKeys { } object BuildImplementation { - import sbt.{ ScmInfo } val buildSettings: Seq[Def.Setting[_]] = List( Scripted.scriptedBufferLog := true, GitKeys.baseVersion := BuildAutoImported.baseVersion, @@ -70,12 +75,11 @@ object BuildImplementation { ScalafmtKeys.scalafmtOnCompile := true, ScalafmtKeys.scalafmtVersion := "1.2.0", ScalafmtKeys.scalafmtOnCompile in Sbt := false, + ReleaseEarlyKeys.releaseEarlyWith := ReleaseEarlyKeys.BintrayPublisher, Keys.description := "Incremental compiler of Scala", // The rest of the sbt developers come from the Sbt Houserules plugin Keys.developers += BuildAutoImported.ScalaCenterMaintainer, - // TODO(jvican): Remove `scmInfo` and `homepage` when we have support for sbt-release-early Keys.homepage := Some(BuildAutoImported.ZincGitHomepage), - Keys.scmInfo := Some(ScmInfo(BuildAutoImported.ZincGitHomepage, "git@github.com:sbt/zinc.git")), Keys.version := { val previous = Keys.version.value if (previous.contains("-SNAPSHOT")) GitKeys.baseVersion.value else previous @@ -154,9 +158,6 @@ object BuildImplementation { } } - val release: Command = - Command.command("release")(st => "clean" :: "+compile" :: "+publishSigned" :: "reload" :: st) - def runBenchmarks(benchmarkProject: Project): Command = { val dirPath = BuildAutoImported.benchmarksTestDir.getAbsolutePath val projectId = benchmarkProject.id @@ -171,7 +172,7 @@ object BuildImplementation { val publishBridges = publishBridgesAndSet(bridge, interface, apiInfo) val publishBridgesTest = publishBridgesAndTest(bridge, interface, apiInfo) val runBench = runBenchmarks(bench) - List(crossTest, publishBridges, publishBridgesTest, runBench, release) + List(crossTest, publishBridges, publishBridgesTest, runBench) } } From 20760f5accf8bd3665b349703d0a8dabd56b799b Mon Sep 17 00:00:00 2001 From: jvican Date: Tue, 17 Oct 2017 15:05:11 +0200 Subject: [PATCH 10/20] Add reasonable jvmopts for all users This build requires too much cross-compiling and cross-publishing, and hence at the moment sbt loads all the compiler classes from all the different versions everything starts to slow down and be close to OOMs and SOs. The following commit adds a jvmopts file that sets up the java flags to be used by sbt when starting up on this repository. These jvmopts file include: - 1024m for the memory at startup time. - 4086m as the maximum allocated memory for sbt. - 512m for the code cache size (otherwise code cache becomes full and JDK disables C2 and fallbacks on interpreter). - Using a bigger inline level considerably helps with compile times and speeds up the whole build (tested in several places). --- .jvmopts | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .jvmopts diff --git a/.jvmopts b/.jvmopts new file mode 100644 index 0000000000..dd893dcfd2 --- /dev/null +++ b/.jvmopts @@ -0,0 +1,4 @@ +-Xms1024m +-Xmx4086m +-XX:ReservedCodeCacheSize=512m +-XX:MaxInlineLevel=20 From 98baaadac20b9f60e140ed7984ceeeddfbb34557 Mon Sep 17 00:00:00 2001 From: jvican Date: Tue, 17 Oct 2017 12:24:24 +0200 Subject: [PATCH 11/20] Add cached `publishLocal` to zinc These changes to the build allow a better workflow with scripted. `cachedPublishLocal` is a special task that avoids publishing if an artifact has already been published and the publication time is greater than the changes to the source directories. In order to find this out, `cachedPublishLocal` resolves the artifact intransitively and in a project-specific directory. This directory is also the used to resolve everything from scripted. This resolution is fast because it assumes that no other task is able to publish that jar to that concrete resolver. As a result, this assumption allows us to remove the global dependency lock. Running `cachedPublishLocal` in the root directory takes from 0 to 1 second. When a new change is written into a project's source file or a resource file, `cachedPublishLocal` publishes only the project that received the changes. This is possible because the optimizer is not allowed and jars are independent from each other. In this setup, `scripted` uses `cachedPublishLocal`. `scripted` **needs** the compiler bridges for all the Scala versions, so if you change the bridge or this is the first time you use this setup, you must run `+compilerBridge/cachedPublishLocal`. --- .gitignore | 1 + build.sbt | 7 +- .../inc/BridgeProviderSpecification.scala | 8 +- .../scala/sbt/internal/inc/IncHandler.scala | 17 ++ project/BuildPlugin.scala | 192 +++++++++++++----- 5 files changed, 171 insertions(+), 54 deletions(-) diff --git a/.gitignore b/.gitignore index e8a589fd3f..6d33e61133 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ target/ zinc/src/test/resources/bin +.ivy2/ diff --git a/build.sbt b/build.sbt index 4ae44d8aa2..419bcc1b55 100644 --- a/build.sbt +++ b/build.sbt @@ -24,7 +24,7 @@ lazy val zincRoot: Project = (project in file(".")) name := "Zinc Root", Scripted.scriptedPrescripted := BuildDefaults.addSbtAlternateResolver _, Scripted.scriptedSource := (sourceDirectory in zinc).value / "sbt-test", - scriptedPublishAll := (publishLocal).all(ScopeFilter(inAnyProject)).value, + scriptedPublish := cachedPublishLocal.all(ScopeFilter(inAnyProject)).value, Scripted.scriptedUnpublished := BuildDefaults.zincOnlyScripted(zincScripted).evaluated, Scripted.scripted := BuildDefaults.zincScripted(compilerBridge, compilerInterface, zincScripted).evaluated, @@ -198,10 +198,11 @@ lazy val compilerBridge: Project = (project in internalPath / "compiler-bridge") // compiler instances that are memory hungry javaOptions in Test += "-Xmx1G", inCompileAndTest(unmanagedSourceDirectories ++= BuildDefaults.handleScalaSpecificSources.value), - cleanSbtBridge := BuildDefaults.cleanSbtBridge.value, - publishLocal := publishLocal.dependsOn(cleanSbtBridge).value, zincPublishLocalSettings, mimaSettings, + cachedPublishLocal := cachedPublishLocal.dependsOn(cachedPublishLocal.in(zincApiInfo)).value, + // Make sure that the sources are published for the bridge because we need them to compile it + publishArtifact in (Compile, packageSrc) := true, ) // defines operations on the API of a source, including determining whether it has changed and converting it to a string diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index 9170152265..60fdfc7b04 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -27,13 +27,11 @@ abstract class BridgeProviderSpecification extends UnitSpec { def currentManaged: File = currentBase / "target" / "lib_managed" val resolvers = Array(ZincComponentCompiler.LocalResolver, Resolver.mavenCentral) - private val ivyConfiguration = + private def ivyConfiguration = getDefaultConfiguration(currentBase, currentTarget, resolvers, log) - def secondaryCacheDirectory: File = { - val target = file("target").getAbsoluteFile - target / "zinc-components" - } + // Place where we store the compiled and installed bridges for every Scala version + def secondaryCacheDirectory: File = file("target").getAbsoluteFile./("zinc-components") def getZincProvider(targetDir: File, log: Logger): CompilerBridgeProvider = { val lock = ZincComponentCompiler.getDefaultLock diff --git a/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncHandler.scala b/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncHandler.scala index 53ecd9e51b..6deb42cc91 100644 --- a/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncHandler.scala +++ b/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncHandler.scala @@ -41,6 +41,7 @@ import java.util.{ Optional, Properties } import sbt.internal.inc.classpath.{ ClassLoaderCache, ClasspathUtilities } import sbt.internal.scripted.{ StatementHandler, TestFailed } import sbt.internal.util.ManagedLogger +import sbt.librarymanagement.Resolver import sjsonnew.support.scalajson.unsafe.{ Converter, Parser => JsonParser } import scala.{ PartialFunction => ?=> } @@ -63,6 +64,22 @@ final class IncHandler(directory: File, cacheDir: File, scriptedLog: ManagedLogg type State = Option[IncInstance] type IncCommand = (ProjectStructure, List[String], IncInstance) => Unit + private final val ZincScriptedLocal = + s"$${user.dir}/.ivy2/zinc-scripted-local/${Resolver.localBasePattern}" + private final val ScriptedResolver: Resolver = { + import sbt.librarymanagement.{ FileRepository, Patterns } + val toUse = Vector(ZincScriptedLocal) + val ivyPattern = Patterns().withIsMavenCompatible(false) + val finalPatterns = ivyPattern + .withIvyPatterns(toUse) + .withArtifactPatterns(toUse) + .withSkipConsistencyCheck(true) + FileRepository("zinc-scripted-local", Resolver.defaultFileConfiguration, finalPatterns) + } + + // Use the scripted resolver to make sure that we don't mistakenly get other jars + override val resolvers: Array[Resolver] = Array(ScriptedResolver, Resolver.mavenCentral) + val compiler = new IncrementalCompilerImpl def initialState: Option[IncInstance] = { diff --git a/project/BuildPlugin.scala b/project/BuildPlugin.scala index 578de049e6..2c53c44354 100644 --- a/project/BuildPlugin.scala +++ b/project/BuildPlugin.scala @@ -1,14 +1,15 @@ -import sbt.{ AutoPlugin, Compile, Def, Keys, Resolver, Test, TestFrameworks, Tests, URL, Project } +import sbt.{ AutoPlugin, Compile, Def, Keys, Project, Resolver, Test, TestFrameworks, Tests, URL } import com.typesafe.sbt.GitPlugin import com.typesafe.sbt.SbtGit.{ git => GitKeys } import bintray.BintrayPlugin.{ autoImport => BintrayKeys } import ch.epfl.scala.sbt.release.ReleaseEarlyPlugin -import ch.epfl.scala.sbt.release.ReleaseEarlyPlugin.{autoImport => ReleaseEarlyKeys} +import ch.epfl.scala.sbt.release.ReleaseEarlyPlugin.{ autoImport => ReleaseEarlyKeys } import com.lucidchart.sbt.scalafmt.ScalafmtCorePlugin import com.lucidchart.sbt.scalafmt.ScalafmtCorePlugin.{ autoImport => ScalafmtKeys } import com.lucidchart.sbt.scalafmt.ScalafmtSbtPlugin.autoImport.Sbt import com.typesafe.tools.mima.plugin.MimaKeys import com.typesafe.tools.mima.plugin.MimaPlugin +import sbt.librarymanagement.ivy.{ InlineIvyConfiguration, IvyDependencyResolution } object BuildPlugin extends AutoPlugin { override def requires = @@ -24,14 +25,14 @@ trait BuildKeys { import sbt.{ TaskKey, taskKey } val tearDownBenchmarkResources: TaskKey[Unit] = taskKey[Unit]("Remove benchmark resources.") - val scriptedPublishAll = taskKey[Unit]("Publishes all the Zinc artifacts for scripted") - val cleanSbtBridge: TaskKey[Unit] = taskKey[Unit]("Cleans the sbt bridge.") + val scriptedPublish = taskKey[Unit]("Publishes all the Zinc artifacts for scripted") + val cachedPublishLocal = taskKey[Unit]("Publishes a project if it hasn't been published before.") val zincPublishLocal: TaskKey[Unit] = taskKey[Unit]("Publishes Zinc artifacts to a alternative local cache.") } object BuildAutoImported extends BuildKeys { - import sbt.{ file, File, Developer, url } + import sbt.{ file, File, Developer, url, State } import BuildImplementation.{ BuildDefaults, BuildResolvers } val baseVersion: String = "1.1.0-SNAPSHOT" @@ -67,6 +68,8 @@ object BuildAutoImported extends BuildKeys { } object BuildImplementation { + import sbt.{ fileToRichFile, file, File, ThisBuild, Tags } + val buildSettings: Seq[Def.Setting[_]] = List( Scripted.scriptedBufferLog := true, GitKeys.baseVersion := BuildAutoImported.baseVersion, @@ -80,6 +83,10 @@ object BuildImplementation { // The rest of the sbt developers come from the Sbt Houserules plugin Keys.developers += BuildAutoImported.ScalaCenterMaintainer, Keys.homepage := Some(BuildAutoImported.ZincGitHomepage), + Keys.publishArtifact in (Compile, Keys.packageDoc) := + BuildDefaults.publishDocAndSourceArtifact.value, + Keys.publishArtifact in (Compile, Keys.packageSrc) := + BuildDefaults.publishDocAndSourceArtifact.value, Keys.version := { val previous = Keys.version.value if (previous.contains("-SNAPSHOT")) GitKeys.baseVersion.value else previous @@ -96,7 +103,8 @@ object BuildImplementation { Keys.javacOptions in Compile ++= Seq("-Xlint", "-Xlint:-serial"), Keys.crossScalaVersions := Seq(Dependencies.scala211, Dependencies.scala212), Keys.publishArtifact in Test := false, - Keys.scalacOptions += "-YdisableFlatCpCaching" + Keys.scalacOptions += "-YdisableFlatCpCaching", + BuildAutoImported.cachedPublishLocal := BuildDefaults.cachedPublishLocal.value, ) object BuildResolvers { @@ -108,13 +116,25 @@ object BuildImplementation { val BintraySbtIvySnapshots: Resolver = Resolver.url("bintray-sbt-ivy-snapshots", new URL("https://dl.bintray.com/sbt/ivy-snapshots/"))(Resolver.ivyStylePatterns) - val all: List[Resolver] = - List(TypesafeReleases, SonatypeSnapshots, BintrayMavenReleases, BintraySbtIvySnapshots) import BuildAutoImported.{ ZincAlternativeCacheName, ZincAlternativeCacheDir } val AlternativeLocalResolver: Resolver = Resolver.file(ZincAlternativeCacheName, ZincAlternativeCacheDir)(Resolver.ivyStylePatterns) + // Defines a resolver that is used to publish only for local testing via scripted + val ScriptedResolverId = "zinc-scripted-local" + val ScriptedResolveCacheDir: File = file(sys.props("user.dir") + s"/.ivy2/$ScriptedResolverId") + val ScriptedResolver: Resolver = + Resolver.file(ScriptedResolverId, ScriptedResolveCacheDir)(Resolver.ivyStylePatterns) + + // All contains all the resolvers but `alternativeLocal` which is used project per project + val all: List[Resolver] = + List(ScriptedResolver, + TypesafeReleases, + SonatypeSnapshots, + BintrayMavenReleases, + BintraySbtIvySnapshots) + // Naive way of implementing a filter to remove repeated resolvers. def removeRepeatedResolvers(rs: Seq[Resolver]): Seq[Resolver] = rs.distinct } @@ -178,7 +198,7 @@ object BuildImplementation { object BuildDefaults { import BuildAutoImported.{ ZincAlternativeCacheName, ZincAlternativeCacheDir } - import sbt.{ Task, State, fileToRichFile, file, File, IO } + import sbt.{ Task, State, IO } private[this] val statusCommands = List( List("diff-index", "--cached", "HEAD"), List("diff-index", "HEAD"), @@ -244,6 +264,120 @@ object BuildImplementation { Set(IvyActions.publish(module, newConfig, logger)) } + /** + * This setting figures out whether the version is a snapshot or not and configures + * the source and doc artifacts that are published by the build. + * + * Snapshot is a term with no clear definition. In this code, a snapshot is a revision + * that has either build or time metadata in its representation. In those cases, the + * build will not publish doc and source artifacts by any of the publishing actions. + */ + val publishDocAndSourceArtifact: Def.Initialize[Boolean] = Def.setting { + import sbtdynver.{ GitDescribeOutput, DynVerPlugin } + import DynVerPlugin.{ autoImport => DynVerKeys } + def isDynVerSnapshot(gitInfo: Option[GitDescribeOutput], defaultValue: Boolean): Boolean = { + val isStable = gitInfo.map { info => + info.ref.value.startsWith("v") && + (info.commitSuffix.distance <= 0 || info.commitSuffix.sha.isEmpty) + } + val isNewSnapshot = + isStable.map(stable => !stable || defaultValue) + // Return previous snapshot definition in case users has overridden version + isNewSnapshot.getOrElse(defaultValue) + } + + // We publish doc and source artifacts if the version is not a snapshot + !isDynVerSnapshot(DynVerKeys.dynverGitDescribeOutput.value, Keys.isSnapshot.value) + } + + private val P = s"[${Console.BOLD}${Console.CYAN}scripted${Console.RESET}]" + val cachedPublishLocal: Def.Initialize[Task[Unit]] = Def.taskDyn { + import BuildResolvers.{ ScriptedResolveCacheDir, ScriptedResolver } + if ((Keys.skip in Keys.publish).value) Def.task(()) + else + Def.taskDyn { + import sbt.util.Logger.{ Null => NoLogger } + val logger = Keys.streams.value.log + + // Find out the configuration of this task to invoke source dirs in the right place + val taskConfig = Keys.resolvedScoped.value.scope.config + val currentConfig: sbt.ConfigKey = taskConfig.fold(identity, Compile, Compile) + + // Important to make it transitive, we just want to check if a jar exists + val moduleID = Keys.projectID.value.intransitive() + val scalaModule = Keys.scalaModuleInfo.value + val ivyConfig = Keys.ivyConfiguration.value + val options = ivyConfig.updateOptions + + // If it's another thing, just fail! We must have an inline ivy config here. + val inlineConfig = ivyConfig.asInstanceOf[InlineIvyConfiguration] + val fasterIvyConfig: InlineIvyConfiguration = inlineConfig + .withResolvers(Vector(ScriptedResolver)) + .withChecksums(Vector()) + // We can do this because we resolve intransitively and nobody but this task publishes + .withLock(None) + + val resolution = IvyDependencyResolution(fasterIvyConfig) + val result = resolution.retrieve(moduleID, scalaModule, ScriptedResolveCacheDir, NoLogger) + result match { + case l: Left[_, _] => publishLocalWrapper(moduleID, fasterIvyConfig, false) + case Right(resolved) => + Def.taskDyn { + val projectName = Keys.name.value + val baseDirectory = Keys.baseDirectory.value.toPath() + val sourceDirs = Keys.sourceDirectories.in(currentConfig).value + val resourceDirs = Keys.resourceDirectories.in(currentConfig).value + val allDirs = sourceDirs ++ resourceDirs + val files = allDirs.flatMap(sbt.Path.allSubpaths(_)).toIterator.map(_._1) + + val allJars = resolved.filter(_.getPath().endsWith(".jar")) + val lastPublicationTime = allJars.map(_.lastModified()).max + val invalidatedSources = files.filter(_.lastModified() >= lastPublicationTime) + if (invalidatedSources.isEmpty) { + Def.task(logger.info(s"$P Skip publish for `$projectName`.")) + } else { + Def.task { + val onlySources = invalidatedSources + .filter(_.isFile) + .map(f => baseDirectory.relativize(f.toPath).toString) + val allChanges = onlySources.mkString("\n\t-> ", "\n\t-> ", "\n") + logger.warn(s"$P Changes detected in $projectName: $allChanges") + publishLocalWrapper(moduleID, fasterIvyConfig, true).value + } + } + } + } + } + } + + def publishLocalWrapper(moduleID: ModuleID, + ivyConfiguration: InlineIvyConfiguration, + overwrite: Boolean): Def.Initialize[Task[Unit]] = { + import BuildResolvers.ScriptedResolverId + import sbt.internal.librarymanagement._ + import sbt.librarymanagement.{ ModuleSettings, PublishConfiguration } + Def.task { + val logger = Keys.streams.value.log + + def publishLocal(moduleSettings: ModuleSettings, config: PublishConfiguration): Unit = { + val ivy = new IvySbt(ivyConfiguration) + val module = new ivy.Module(moduleSettings) + val correctConfig = config.withOverwrite(overwrite) + val fastConfig: PublishConfiguration = + correctConfig.withResolverName(ScriptedResolverId).withChecksums(Vector()) + IvyActions.publish(module, fastConfig, logger) + } + + val name = Keys.name.value + val version = moduleID.revision + logger.warn(s"$P Publishing `$name`, version: '$version'.") + + val moduleSettings = Keys.moduleSettings.value + val publishConfig = Keys.publishLocalConfiguration.value + publishLocal(moduleSettings, publishConfig) + } + } + val noPublishSettings: Seq[Def.Setting[_]] = List( Keys.publish := {}, Keys.publishLocal := {}, @@ -259,37 +393,6 @@ object BuildImplementation { else color + content + scala.Console.RESET } - val cleanSbtBridge: Def.Initialize[Task[Unit]] = Def.task { - val sbtV = Keys.sbtVersion.value - val sbtOrg = "org.scala-sbt" - val sbtScalaVersion = "2.10.6" - val bridgeVersion = Keys.version.value - val scalaV = Keys.scalaVersion.value - - // Assumes that JDK version is the same than the one that publishes the bridge - val classVersion = System.getProperty("java.class.version") - - val home = System.getProperty("user.home") - val org = Keys.organization.value - val artifact = Keys.moduleName.value - val artifactName = s"$org-$artifact-$bridgeVersion-bin_${scalaV}__$classVersion" - - val targetsToDelete = List( - // We cannot use the target key, it's not scoped in `ThisBuild` nor `Global`. - (Keys.baseDirectory in sbt.ThisBuild).value / "target" / "zinc-components", - file(home) / ".ivy2/cache" / sbtOrg / artifactName, - file(home) / ".ivy2/local" / sbtOrg / artifactName, - file(home) / ".sbt/boot" / s"scala-$sbtScalaVersion" / sbtOrg / "sbt" / sbtV / artifactName - ) - - val logger = Keys.streams.value.log - logger.info(wrapIn(scala.Console.BOLD, "Cleaning stale compiler bridges:")) - targetsToDelete.foreach { target => - IO.delete(target) - logger.info(s"${wrapIn(scala.Console.GREEN, " ✓ ")}${target.getAbsolutePath}") - } - } - private[this] val scalaPartialVersion = Def.setting(CrossVersion.partialVersion(Keys.scalaVersion.value)) val handleScalaSpecificSources: Def.Initialize[List[File]] = Def.setting { @@ -306,17 +409,14 @@ object BuildImplementation { interfaceRef: Project, scriptedRef: Project): Def.Initialize[InputTask[Unit]] = Def.inputTask { val result = scriptedSource(dir => (s: State) => scriptedParser(dir)).parsed - // We first publish all the zinc modules - BuildAutoImported.scriptedPublishAll.value + + // First, publish all the zinc modules (not cross-compiled though) + BuildAutoImported.scriptedPublish.value val source = scriptedSource.value val logged = scriptedBufferLog.value val hook = scriptedPrescripted.value - // Publish the interface and the bridge for scripted to resolve them correctly - (BuildAutoImported.zincPublishLocal in interfaceRef).value - (BuildAutoImported.zincPublishLocal in bridgeRef).value - val scriptedClasspath = (Keys.fullClasspath in scriptedRef in Test).value val instance = (Keys.scalaInstance in scriptedRef).value Scripted.doScripted(scriptedClasspath, instance, source, result, logged, hook) From 2b65a81f54dac29c6df99c09f844387faa5f1eab Mon Sep 17 00:00:00 2001 From: jvican Date: Tue, 17 Oct 2017 16:41:03 +0200 Subject: [PATCH 12/20] Remove dead code The following code is not necessary anymore. - `zincPublishLocal` et al: Nobody is using the zinc-scripted-alternative because scripted does not use sbt, it uses its own backend. - `scriptedUnpublished` is not necessary anymore since scripted now relies on `cachedPublishLocal`. --- build.sbt | 5 +--- project/BuildPlugin.scala | 60 ++------------------------------------- project/Scripted.scala | 3 -- 3 files changed, 3 insertions(+), 65 deletions(-) diff --git a/build.sbt b/build.sbt index 419bcc1b55..22de23bb5b 100644 --- a/build.sbt +++ b/build.sbt @@ -22,10 +22,9 @@ lazy val zincRoot: Project = (project in file(".")) ) .settings( name := "Zinc Root", - Scripted.scriptedPrescripted := BuildDefaults.addSbtAlternateResolver _, + Scripted.scriptedPrescripted := {(f: File) => ()}, Scripted.scriptedSource := (sourceDirectory in zinc).value / "sbt-test", scriptedPublish := cachedPublishLocal.all(ScopeFilter(inAnyProject)).value, - Scripted.scriptedUnpublished := BuildDefaults.zincOnlyScripted(zincScripted).evaluated, Scripted.scripted := BuildDefaults.zincScripted(compilerBridge, compilerInterface, zincScripted).evaluated, commands in Global ++= @@ -173,7 +172,6 @@ lazy val compilerInterface = (project in internalPath / "compiler-interface") baseDirectory.value / "src" / "main" / "contraband-java", crossPaths := false, autoScalaLibrary := false, - zincPublishLocalSettings, mimaSettings, ) @@ -198,7 +196,6 @@ lazy val compilerBridge: Project = (project in internalPath / "compiler-bridge") // compiler instances that are memory hungry javaOptions in Test += "-Xmx1G", inCompileAndTest(unmanagedSourceDirectories ++= BuildDefaults.handleScalaSpecificSources.value), - zincPublishLocalSettings, mimaSettings, cachedPublishLocal := cachedPublishLocal.dependsOn(cachedPublishLocal.in(zincApiInfo)).value, // Make sure that the sources are published for the bridge because we need them to compile it diff --git a/project/BuildPlugin.scala b/project/BuildPlugin.scala index 2c53c44354..271966d358 100644 --- a/project/BuildPlugin.scala +++ b/project/BuildPlugin.scala @@ -27,8 +27,6 @@ trait BuildKeys { val tearDownBenchmarkResources: TaskKey[Unit] = taskKey[Unit]("Remove benchmark resources.") val scriptedPublish = taskKey[Unit]("Publishes all the Zinc artifacts for scripted") val cachedPublishLocal = taskKey[Unit]("Publishes a project if it hasn't been published before.") - val zincPublishLocal: TaskKey[Unit] = - taskKey[Unit]("Publishes Zinc artifacts to a alternative local cache.") } object BuildAutoImported extends BuildKeys { @@ -44,10 +42,6 @@ object BuildAutoImported extends BuildKeys { val ScalaCenterMaintainer: Developer = Developer("jvican", "Jorge Vicente Cantero", "@jvican", url("https://github.com/jvican")) - // Defines the constants for the alternative publishing - val ZincAlternativeCacheName = "alternative-local" - val ZincAlternativeCacheDir: File = file(sys.props("user.home") + "/.ivy2/zinc-alternative") - // Defines several settings that are exposed to the projects definition in build.sbt private[this] val noPublishSettings: Seq[Def.Setting[_]] = BuildDefaults.noPublishSettings def noPublish(p: Project): Project = p.settings(noPublishSettings) @@ -57,10 +51,6 @@ object BuildAutoImported extends BuildKeys { List(MimaKeys.mimaPreviousArtifacts := BuildDefaults.zincPreviousArtifacts.value) val adaptOptionsForOldScalaVersions: Seq[Def.Setting[_]] = List(Keys.scalacOptions := BuildDefaults.zincScalacOptionsRedefinition.value) - val zincPublishLocalSettings: Seq[Def.Setting[_]] = List( - Keys.resolvers += BuildResolvers.AlternativeLocalResolver, - zincPublishLocal := BuildDefaults.zincPublishLocal.value, - ) val benchmarksTestDir = sbt.IO.createTemporaryDirectory def inCompileAndTest(ss: Def.Setting[_]*): Seq[Def.Setting[_]] = @@ -117,10 +107,6 @@ object BuildImplementation { Resolver.url("bintray-sbt-ivy-snapshots", new URL("https://dl.bintray.com/sbt/ivy-snapshots/"))(Resolver.ivyStylePatterns) - import BuildAutoImported.{ ZincAlternativeCacheName, ZincAlternativeCacheDir } - val AlternativeLocalResolver: Resolver = - Resolver.file(ZincAlternativeCacheName, ZincAlternativeCacheDir)(Resolver.ivyStylePatterns) - // Defines a resolver that is used to publish only for local testing via scripted val ScriptedResolverId = "zinc-scripted-local" val ScriptedResolveCacheDir: File = file(sys.props("user.dir") + s"/.ivy2/$ScriptedResolverId") @@ -197,7 +183,6 @@ object BuildImplementation { } object BuildDefaults { - import BuildAutoImported.{ ZincAlternativeCacheName, ZincAlternativeCacheDir } import sbt.{ Task, State, IO } private[this] val statusCommands = List( List("diff-index", "--cached", "HEAD"), @@ -252,17 +237,6 @@ object BuildImplementation { } } - val zincPublishLocal: Def.Initialize[Task[Unit]] = Def.task { - import sbt.internal.librarymanagement._ - val logger = Keys.streams.value.log - val config = (Keys.publishLocalConfiguration).value - val ivy = new IvySbt((Keys.ivyConfiguration.value)) - val moduleSettings = (Keys.moduleSettings).value - val module = new ivy.Module(moduleSettings) - val newConfig = config.withResolverName(ZincAlternativeCacheName).withOverwrite(false) - logger.info(s"Publishing $module to local repo: $ZincAlternativeCacheName") - Set(IvyActions.publish(module, newConfig, logger)) - } /** * This setting figures out whether the version is a snapshot or not and configures @@ -290,7 +264,7 @@ object BuildImplementation { !isDynVerSnapshot(DynVerKeys.dynverGitDescribeOutput.value, Keys.isSnapshot.value) } - private val P = s"[${Console.BOLD}${Console.CYAN}scripted${Console.RESET}]" + private val P = "[" + wrapIn(Console.BOLD + Console.CYAN, "scripted") + "]" val cachedPublishLocal: Def.Initialize[Task[Unit]] = Def.taskDyn { import BuildResolvers.{ ScriptedResolveCacheDir, ScriptedResolver } if ((Keys.skip in Keys.publish).value) Def.task(()) @@ -408,11 +382,10 @@ object BuildImplementation { def zincScripted(bridgeRef: Project, interfaceRef: Project, scriptedRef: Project): Def.Initialize[InputTask[Unit]] = Def.inputTask { - val result = scriptedSource(dir => (s: State) => scriptedParser(dir)).parsed - // First, publish all the zinc modules (not cross-compiled though) BuildAutoImported.scriptedPublish.value + val result = scriptedSource(dir => (s: State) => scriptedParser(dir)).parsed val source = scriptedSource.value val logged = scriptedBufferLog.value val hook = scriptedPrescripted.value @@ -422,35 +395,6 @@ object BuildImplementation { Scripted.doScripted(scriptedClasspath, instance, source, result, logged, hook) } - def zincOnlyScripted(scriptedRef: Project): Def.Initialize[InputTask[Unit]] = Def.inputTask { - val result = scriptedSource(dir => (s: State) => scriptedParser(dir)).parsed - val scriptedClasspath = (Keys.fullClasspath in scriptedRef in Test).value - val instance = (Keys.scalaInstance in scriptedRef).value - val source = scriptedSource.value - val logged = scriptedBufferLog.value - val hook = scriptedPrescripted.value - Scripted.doScripted(scriptedClasspath, instance, source, result, logged, hook) - } - - private[this] val ZincAlternativeResolverPlugin = s""" - |import sbt._ - |import Keys._ - | - |object AddResolverPlugin extends AutoPlugin { - | override def requires = sbt.plugins.JvmPlugin - | override def trigger = allRequirements - | - | override lazy val projectSettings = Seq(resolvers += alternativeLocalResolver) - | lazy val alternativeLocalResolver = Resolver.file("$ZincAlternativeCacheName", file("${ZincAlternativeCacheDir.getAbsolutePath}"))(Resolver.ivyStylePatterns) - |} - |""".stripMargin - - def addSbtAlternateResolver(scriptedRoot: File): Unit = { - val resolver = scriptedRoot / "project" / "AddResolverPlugin.scala" - if (!resolver.exists) IO.write(resolver, ZincAlternativeResolverPlugin) - else () - } - val tearDownBenchmarkResources: Def.Initialize[Task[Unit]] = Def.task(IO.delete(BuildAutoImported.benchmarksTestDir)) } diff --git a/project/Scripted.scala b/project/Scripted.scala index 07f893cdb7..498a442268 100644 --- a/project/Scripted.scala +++ b/project/Scripted.scala @@ -9,9 +9,6 @@ import scala.language.reflectiveCalls object Scripted { def scriptedPath = file("scripted") lazy val scripted = InputKey[Unit]("scripted") - lazy val scriptedUnpublished = InputKey[Unit]( - "scripted-unpublished", - "Execute scripted without publishing SBT first. Saves you some time when only your test has changed.") lazy val scriptedSource = SettingKey[File]("scripted-source") lazy val scriptedPrescripted = TaskKey[File => Unit]("scripted-prescripted") lazy val scriptedBufferLog = SettingKey[Boolean]("scripted-buffer-log") From e7d38305e7b19671cecf4e0d2b77433811ea3af8 Mon Sep 17 00:00:00 2001 From: jvican Date: Mon, 13 Nov 2017 23:26:13 +0100 Subject: [PATCH 13/20] Make the build `+`-friendly Without this change, we get some linking errors (`scala.Product$` not found) because `+` is not capable of switching the compiler interface to the new scala version, and linking to it from other projects with newer scala versions breaks it. Forcing the scala 2.10 version as the only version of the interface causes also problems when testing the bridge on 2.11 and 2.12 (which are the default versions of the build). Therefore, we remove it from the build and we force that we validate that the interface can be compiled with 2.10 (and hence Java < 8). --- bin/run-ci.sh | 2 ++ build.sbt | 6 +----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/bin/run-ci.sh b/bin/run-ci.sh index aad4fb1492..194675a609 100755 --- a/bin/run-ci.sh +++ b/bin/run-ci.sh @@ -12,6 +12,8 @@ sbt -Dfile.encoding=UTF-8 \ test:scalafmt::test \ headerCheck \ test:headerCheck \ + ++2.10.11 \ + compilerInterface/compile \ zincRoot/test:compile \ crossTestBridges \ "publishBridgesAndSet $SCALA_VERSION" \ diff --git a/build.sbt b/build.sbt index 22de23bb5b..91caeaab9c 100644 --- a/build.sbt +++ b/build.sbt @@ -148,11 +148,7 @@ lazy val compilerInterface = (project in internalPath / "compiler-interface") .settings( // javaOnlySettings, name := "Compiler Interface", - // Use the smallest Scala version in the compilerBridgeScalaVersions - // Technically the scalaVersion shouldn't have any effect since scala library is not included, - // but given that Scala 2.10 compiler cannot parse Java 8 source, it's probably good to keep this. - crossScalaVersions := Seq(scala210), - scalaVersion := scala210, + crossScalaVersions := bridgeScalaVersions, adaptOptionsForOldScalaVersions, libraryDependencies ++= Seq(scalaLibrary.value % Test), exportJars := true, From 8b00dca01c5f13189862b02a41905e97c106b661 Mon Sep 17 00:00:00 2001 From: jvican Date: Tue, 17 Oct 2017 23:51:27 +0200 Subject: [PATCH 14/20] Remove `crossTestBridges` and `publishBridgesAndSet` These commands are not necessary anymore since they can be expressed by operations at the task level that are more intuitive than the previous commands. This helps simplifying the whole build setup a lot. --- bin/run-ci.sh | 14 +++++++++--- build.sbt | 6 ++++- project/BuildPlugin.scala | 48 +++++++++++---------------------------- 3 files changed, 29 insertions(+), 39 deletions(-) diff --git a/bin/run-ci.sh b/bin/run-ci.sh index 194675a609..9c1fac45a3 100755 --- a/bin/run-ci.sh +++ b/bin/run-ci.sh @@ -3,6 +3,13 @@ set -eu set -o nounset SCALA_VERSION="$1" +# Exemplifies how the build should be used by user +# The following script makes sure to: +# 1. Checking binary compatibility +# 2. Checking formatting and headers +# 3. Testing the compiler bridge for all versions +# 4. Setting up the scala version specified by the argument +# 5. Running tests for all the projects and then scripted sbt -Dfile.encoding=UTF-8 \ -J-XX:ReservedCodeCacheSize=256M \ @@ -12,10 +19,11 @@ sbt -Dfile.encoding=UTF-8 \ test:scalafmt::test \ headerCheck \ test:headerCheck \ - ++2.10.11 \ + ++2.10.6 \ compilerInterface/compile \ zincRoot/test:compile \ - crossTestBridges \ - "publishBridgesAndSet $SCALA_VERSION" \ + +compilerBridge/cachedPublishLocal \ + +compilerBridge/test \ + "++$SCALA_VERSION" \ zincRoot/test \ zincRoot/scripted diff --git a/build.sbt b/build.sbt index 91caeaab9c..581ee8ee27 100644 --- a/build.sbt +++ b/build.sbt @@ -193,9 +193,13 @@ lazy val compilerBridge: Project = (project in internalPath / "compiler-bridge") javaOptions in Test += "-Xmx1G", inCompileAndTest(unmanagedSourceDirectories ++= BuildDefaults.handleScalaSpecificSources.value), mimaSettings, - cachedPublishLocal := cachedPublishLocal.dependsOn(cachedPublishLocal.in(zincApiInfo)).value, // Make sure that the sources are published for the bridge because we need them to compile it publishArtifact in (Compile, packageSrc) := true, + // Cached publish local in the bridge also publishes api info and the compiler interface + cachedPublishLocal := cachedPublishLocal + .dependsOn(cachedPublishLocal.in(zincApiInfo)) + .dependsOn(cachedPublishLocal.in(compilerInterface)) + .value, ) // defines operations on the API of a source, including determining whether it has changed and converting it to a string diff --git a/project/BuildPlugin.scala b/project/BuildPlugin.scala index 271966d358..f29794e33f 100644 --- a/project/BuildPlugin.scala +++ b/project/BuildPlugin.scala @@ -126,40 +126,21 @@ object BuildImplementation { } object BuildCommands { - import sbt.{ Command, State } + import sbt.Command import BuildAutoImported.bridgeScalaVersions - def crossTestBridges(bridge: Project): Command = { - Command.command("crossTestBridges") { (state: State) => - (bridgeScalaVersions.flatMap { (bridgeVersion: String) => - // Note the ! here. You need this so compilerInterface gets forced to the scalaVersion - s"++ $bridgeVersion!" :: s"${bridge.id}/test" :: Nil - }) ::: (s"++ ${Dependencies.scala212}!" :: state) - } - } - def publishBridgesAndSet(bridge: Project, interface: Project, apiInfo: Project): Command = { - Command.args("publishBridgesAndSet", "") { (state, args) => - require(args.nonEmpty, "Missing Scala version argument.") - val userScalaVersion = args.mkString("") - s"${interface.id}/publishLocal" :: bridgeScalaVersions.flatMap { (v: String) => - s"++ $v!" :: s"${apiInfo.id}/publishLocal" :: s"${bridge.id}/publishLocal" :: Nil - } ::: s"++ $userScalaVersion!" :: state - } - } - - def publishBridgesAndTest(bridge: Project, interface: Project, apiInfo: Project): Command = { + def publishBridgesAndTest(bridge: Project, interface: Project, root: Project): Command = { Command.args("publishBridgesAndTest", "") { (state, args) => require(args.nonEmpty, "Missing arguments to publishBridgesAndTest.") val version = args mkString "" - val bridgeCommands: List[String] = bridgeScalaVersions.flatMap { (v: String) => - s"++ $v" :: s"${apiInfo.id}/publishLocal" :: s"${bridge.id}/publishLocal" :: Nil - } - s"${interface.id}/publishLocal" :: - bridgeCommands ::: - s"++ $version" :: - s"zincRoot/scalaVersion" :: - s"zincRoot/test" :: - s"zincRoot/scripted" :: + val bridgeCommands: List[String] = + bridgeScalaVersions.flatMap((v: String) => s"+${bridge.id}/publishLocal" :: Nil) + val rootProject = root.id + bridgeCommands ::: + s"++$version" :: + s"$rootProject/scalaVersion" :: + s"$rootProject/test" :: + s"$rootProject/scripted" :: state } } @@ -173,12 +154,10 @@ object BuildImplementation { Command.command("runBenchmarks")(st => runPreSetup :: runBenchmark :: tearDownResources :: st) } - def all(bridge: Project, interface: Project, apiInfo: Project, bench: Project): Seq[Command] = { - val crossTest = crossTestBridges(bridge) - val publishBridges = publishBridgesAndSet(bridge, interface, apiInfo) - val publishBridgesTest = publishBridgesAndTest(bridge, interface, apiInfo) + def all(bridge: Project, interface: Project, root: Project, bench: Project): Seq[Command] = { + val publishBridgesTest = publishBridgesAndTest(bridge, interface, root) val runBench = runBenchmarks(bench) - List(crossTest, publishBridges, publishBridgesTest, runBench) + List(publishBridgesTest, runBench) } } @@ -237,7 +216,6 @@ object BuildImplementation { } } - /** * This setting figures out whether the version is a snapshot or not and configures * the source and doc artifacts that are published by the build. From 83276686c6a1ca91dbe5d9b6e0f33e064cadd3ba Mon Sep 17 00:00:00 2001 From: jvican Date: Wed, 18 Oct 2017 10:26:20 +0200 Subject: [PATCH 15/20] Simplify comments in the `build.sbt` --- build.sbt | 38 +++++++++----------------------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/build.sbt b/build.sbt index 581ee8ee27..15cbfc9811 100644 --- a/build.sbt +++ b/build.sbt @@ -59,7 +59,6 @@ lazy val zincCompile = (project in file("zinc-compile")) mimaSettings, ) -// Persists the incremental data structures using Protobuf lazy val zincPersist = (project in internalPath / "zinc-persist") .dependsOn(zincCore, zincCore % "test->test") .configure(addTestDependencies) @@ -71,8 +70,6 @@ lazy val zincPersist = (project in internalPath / "zinc-persist") mimaSettings, ) -// Implements the core functionality of detecting and propagating changes incrementally. -// Defines the data structures for representing file fingerprints and relationships and the overall source analysis lazy val zincCore = (project in internalPath / "zinc-core") .configure(addTestDependencies, addSbtIO, addSbtUtilLogging, addSbtUtilRelation) .dependsOn( @@ -83,14 +80,11 @@ lazy val zincCore = (project in internalPath / "zinc-core") zincTesting % Test ) .settings( - // we need to fork because in unit tests we set usejavacp = true which means - // we are expecting all of our dependencies to be on classpath so Scala compiler - // can use them while constructing its own classpath for compilation + name := "zinc Core", + // Forking is mandatory because unit tests enable `usejavacp` and expects deps in the classpath fork in Test := true, - // needed because we fork tests and tests are ran in parallel so we have multiple Scala - // compiler instances that are memory hungry + // Tests are run in parallel and forked, so the compiler instances are memory hungry javaOptions in Test += "-Xmx1G", - name := "zinc Core", compileOrder := sbt.CompileOrder.Mixed, mimaSettings, ) @@ -116,7 +110,6 @@ lazy val zincIvyIntegration = (project in internalPath / "zinc-ivy-integration") mimaSettings, ) -// sbt-side interface to compiler. Calls compiler-side interface reflectively lazy val zincCompileCore = (project in internalPath / "zinc-compile-core") .enablePlugins(ContrabandPlugin) .configure(addTestDependencies, addSbtUtilLogging, addSbtIO, addSbtUtilControl) @@ -139,15 +132,14 @@ lazy val zincCompileCore = (project in internalPath / "zinc-compile-core") headerCheck in Test := List() ) -// defines Java structures used across Scala versions, such as the API structures and relationships extracted by -// the analysis compiler phases and passed back to sbt. The API structures are defined in a simple -// format from which Java sources are generated by the sbt-contraband plugin. +// This is a Java-only module, the set Scala version has no effect on it lazy val compilerInterface = (project in internalPath / "compiler-interface") .enablePlugins(ContrabandPlugin) .configure(addSbtUtilInterface) .settings( - // javaOnlySettings, name := "Compiler Interface", + // For compatibility, use bridge cross versions that include 2.10 + // 2.10 allows us to test that the java sources can be parsed before JDK8 crossScalaVersions := bridgeScalaVersions, adaptOptionsForOldScalaVersions, libraryDependencies ++= Seq(scalaLibrary.value % Test), @@ -171,25 +163,18 @@ lazy val compilerInterface = (project in internalPath / "compiler-interface") mimaSettings, ) - -// Compiler-side interface to compiler that is compiled against the compiler being used either in advance or on the fly. -// Includes API and Analyzer phases that extract source API and relationships. lazy val compilerBridge: Project = (project in internalPath / "compiler-bridge") .dependsOn(compilerInterface % "compile;test->test", zincApiInfo % "test->test") .settings( + name := "Compiler Bridge", crossScalaVersions := bridgeScalaVersions, adaptOptionsForOldScalaVersions, libraryDependencies += scalaCompiler.value % "provided", autoScalaLibrary := false, - // precompiledSettings, - name := "Compiler Bridge", exportJars := true, - // we need to fork because in unit tests we set usejavacp = true which means - // we are expecting all of our dependencies to be on classpath so Scala compiler - // can use them while constructing its own classpath for compilation + // Forking is mandatory because unit tests enable `usejavacp` and expects deps in the classpath fork in Test := true, - // needed because we fork tests and tests are ran in parallel so we have multiple Scala - // compiler instances that are memory hungry + // Tests are run in parallel and forked, so the compiler instances are memory hungry javaOptions in Test += "-Xmx1G", inCompileAndTest(unmanagedSourceDirectories ++= BuildDefaults.handleScalaSpecificSources.value), mimaSettings, @@ -202,8 +187,6 @@ lazy val compilerBridge: Project = (project in internalPath / "compiler-bridge") .value, ) -// defines operations on the API of a source, including determining whether it has changed and converting it to a string -// and discovery of Projclasses and annotations lazy val zincApiInfo = (project in internalPath / "zinc-apiinfo") .dependsOn(compilerInterface, zincClassfile % "compile;test->test") .configure(addTestDependencies) @@ -214,7 +197,6 @@ lazy val zincApiInfo = (project in internalPath / "zinc-apiinfo") mimaSettings, ) -// Utilities related to reflection, managing Scala versions, and custom class loaders lazy val zincClasspath = (project in internalPath / "zinc-classpath") .dependsOn(compilerInterface) .configure(addTestDependencies, addSbtIO) @@ -226,7 +208,6 @@ lazy val zincClasspath = (project in internalPath / "zinc-classpath") mimaSettings, ) -// class file reader and analyzer lazy val zincClassfile = (project in internalPath / "zinc-classfile") .dependsOn(compilerInterface % "compile;test->test") .configure(addTestDependencies, addSbtIO, addSbtUtilLogging) @@ -237,7 +218,6 @@ lazy val zincClassfile = (project in internalPath / "zinc-classfile") mimaSettings, ) -// re-implementation of scripted engine lazy val zincScripted = (project in internalPath / "zinc-scripted") .dependsOn(zinc, zincIvyIntegration % "test->test") .configure(addSbtUtilScripted, noPublish) From 419d5966ce8eb0f3b86db232760ffe4918114f38 Mon Sep 17 00:00:00 2001 From: jvican Date: Wed, 18 Oct 2017 10:40:54 +0200 Subject: [PATCH 16/20] Add build changes to the the CONTRIBUTING guide --- CONTRIBUTING.md | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 518550c8bc..309778dc29 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -97,11 +97,25 @@ Zinc's build requires the compiler bridges to be published before tests are run (compiler bridges are compiler-specific Scala sources that need to be fetched to perform incremental compilation). +The following keys assume that you're at the root project `zincRoot` (true unless you do `project somethingElse`). + |Key|Use| |---|---| -|crossTestBridges|Runs compiler bridge unit tests for all scala versions.| -|publishBridgesAndTest|Publish bridges and test the whole incremental compiler.| -|publishBridgesAndSet|Publish bridges and set the current Scala version.| +|+compilerBridge/cachedPublishLocal|Cross-publishes all the compiler bridges if there have been changes. Required by `scripted`.| +|cachedPublishLocal|Compiles and publishes all the modules if there have been changes. Executed by `scripted` internally.| +|test|Run the unit tests (if defined).| +|scripted|Run all the integration tests that check that incremental compilation happens with real-world examples. You can also pass the scripted test you want to run as an argument.| +|publishBridgesAndTest|Publish bridges and test the whole incremental compiler. Inefficient for a fast, local developer workflow, ideal for CI.| + +##### Workflow? + +The most likely scenario is that you don't change code in the bridges. In that case, if you want to +unit test you run `test` on whichever modules you want (typically in the `zincRoot` for all of them). +If you want to run integration tests, you run `scripted` directly. + +If you change code in the bridges and you want to test it, you must always run +`+compilerBridge/cachedPublishLocal` for scripted to pick up your changes for all the scala versions. +Then, you proceed with `scripted`. ### Benchmarking Zinc From 8af454fc79c5e1fa00603564b653a1d5c973b0a8 Mon Sep 17 00:00:00 2001 From: jvican Date: Mon, 13 Nov 2017 22:23:08 +0100 Subject: [PATCH 17/20] Remove unnecessary filter for `scriptedPublish` --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 15cbfc9811..98f3ef09ba 100644 --- a/build.sbt +++ b/build.sbt @@ -24,7 +24,7 @@ lazy val zincRoot: Project = (project in file(".")) name := "Zinc Root", Scripted.scriptedPrescripted := {(f: File) => ()}, Scripted.scriptedSource := (sourceDirectory in zinc).value / "sbt-test", - scriptedPublish := cachedPublishLocal.all(ScopeFilter(inAnyProject)).value, + scriptedPublish := cachedPublishLocal.value, Scripted.scripted := BuildDefaults.zincScripted(compilerBridge, compilerInterface, zincScripted).evaluated, commands in Global ++= From 0d582349384ad4e35024ccf559195feb60995466 Mon Sep 17 00:00:00 2001 From: jvican Date: Mon, 13 Nov 2017 23:22:30 +0100 Subject: [PATCH 18/20] Scope to the project instead of the build In sbt 1.x, it seems that `publishArtifact` is scoped in the project and not the build. The reason why I noticed this is because these settings were not being applied before this change. --- project/BuildPlugin.scala | 40 +++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/project/BuildPlugin.scala b/project/BuildPlugin.scala index f29794e33f..fca013b47d 100644 --- a/project/BuildPlugin.scala +++ b/project/BuildPlugin.scala @@ -71,15 +71,15 @@ object BuildImplementation { ReleaseEarlyKeys.releaseEarlyWith := ReleaseEarlyKeys.BintrayPublisher, Keys.description := "Incremental compiler of Scala", // The rest of the sbt developers come from the Sbt Houserules plugin - Keys.developers += BuildAutoImported.ScalaCenterMaintainer, - Keys.homepage := Some(BuildAutoImported.ZincGitHomepage), - Keys.publishArtifact in (Compile, Keys.packageDoc) := + developers += BuildAutoImported.ScalaCenterMaintainer, + homepage := Some(BuildAutoImported.ZincGitHomepage), + publishArtifact in (Compile, packageDoc) := BuildDefaults.publishDocAndSourceArtifact.value, - Keys.publishArtifact in (Compile, Keys.packageSrc) := + publishArtifact in (Compile, packageSrc) := BuildDefaults.publishDocAndSourceArtifact.value, - Keys.version := { - val previous = Keys.version.value - if (previous.contains("-SNAPSHOT")) GitKeys.baseVersion.value else previous + version := { + val previous = version.value + if (previous.contains("-SNAPSHOT")) baseVersion.value else previous }, ) @@ -95,6 +95,10 @@ object BuildImplementation { Keys.publishArtifact in Test := false, Keys.scalacOptions += "-YdisableFlatCpCaching", BuildAutoImported.cachedPublishLocal := BuildDefaults.cachedPublishLocal.value, + publishArtifact in (Compile, packageDoc) := + BuildDefaults.publishDocAndSourceArtifact.value, + publishArtifact in (Compile, packageSrc) := + BuildDefaults.publishDocAndSourceArtifact.value, ) object BuildResolvers { @@ -239,26 +243,26 @@ object BuildImplementation { } // We publish doc and source artifacts if the version is not a snapshot - !isDynVerSnapshot(DynVerKeys.dynverGitDescribeOutput.value, Keys.isSnapshot.value) + !isDynVerSnapshot(DynVerKeys.dynverGitDescribeOutput.value, isSnapshot.value) } private val P = "[" + wrapIn(Console.BOLD + Console.CYAN, "scripted") + "]" val cachedPublishLocal: Def.Initialize[Task[Unit]] = Def.taskDyn { import BuildResolvers.{ ScriptedResolveCacheDir, ScriptedResolver } - if ((Keys.skip in Keys.publish).value) Def.task(()) + if ((skip in publish).value) Def.task(()) else Def.taskDyn { import sbt.util.Logger.{ Null => NoLogger } - val logger = Keys.streams.value.log + val logger = streams.value.log // Find out the configuration of this task to invoke source dirs in the right place - val taskConfig = Keys.resolvedScoped.value.scope.config + val taskConfig = resolvedScoped.value.scope.config val currentConfig: sbt.ConfigKey = taskConfig.fold(identity, Compile, Compile) // Important to make it transitive, we just want to check if a jar exists - val moduleID = Keys.projectID.value.intransitive() - val scalaModule = Keys.scalaModuleInfo.value - val ivyConfig = Keys.ivyConfiguration.value + val moduleID = projectID.value.intransitive() + val scalaModule = scalaModuleInfo.value + val ivyConfig = ivyConfiguration.value val options = ivyConfig.updateOptions // If it's another thing, just fail! We must have an inline ivy config here. @@ -275,10 +279,10 @@ object BuildImplementation { case l: Left[_, _] => publishLocalWrapper(moduleID, fasterIvyConfig, false) case Right(resolved) => Def.taskDyn { - val projectName = Keys.name.value + val projectName = name.value val baseDirectory = Keys.baseDirectory.value.toPath() - val sourceDirs = Keys.sourceDirectories.in(currentConfig).value - val resourceDirs = Keys.resourceDirectories.in(currentConfig).value + val sourceDirs = sourceDirectories.in(currentConfig).value + val resourceDirs = resourceDirectories.in(currentConfig).value val allDirs = sourceDirs ++ resourceDirs val files = allDirs.flatMap(sbt.Path.allSubpaths(_)).toIterator.map(_._1) @@ -309,7 +313,7 @@ object BuildImplementation { import sbt.internal.librarymanagement._ import sbt.librarymanagement.{ ModuleSettings, PublishConfiguration } Def.task { - val logger = Keys.streams.value.log + val logger = streams.value.log def publishLocal(moduleSettings: ModuleSettings, config: PublishConfiguration): Unit = { val ivy = new IvySbt(ivyConfiguration) From 543dcb0d9aba092ec1e9fa11b46713277e81f59c Mon Sep 17 00:00:00 2001 From: jvican Date: Fri, 27 Oct 2017 09:16:46 +0200 Subject: [PATCH 19/20] Remove use of the `Keys` prefix Eugene and Dale think this way is better, because they are not used to the previous style that has a saner way of using scopes in Scala. They have proposed to make the changes in an independent pull request, but I don't have time for it. --- project/BuildPlugin.scala | 91 +++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 47 deletions(-) diff --git a/project/BuildPlugin.scala b/project/BuildPlugin.scala index fca013b47d..e615649199 100644 --- a/project/BuildPlugin.scala +++ b/project/BuildPlugin.scala @@ -1,15 +1,15 @@ -import sbt.{ AutoPlugin, Compile, Def, Keys, Project, Resolver, Test, TestFrameworks, Tests, URL } +import sbt._ +import sbt.Keys._ import com.typesafe.sbt.GitPlugin -import com.typesafe.sbt.SbtGit.{ git => GitKeys } -import bintray.BintrayPlugin.{ autoImport => BintrayKeys } +import com.typesafe.sbt.SbtGit.git._ +import bintray.BintrayPlugin.autoImport._ import ch.epfl.scala.sbt.release.ReleaseEarlyPlugin -import ch.epfl.scala.sbt.release.ReleaseEarlyPlugin.{ autoImport => ReleaseEarlyKeys } +import ch.epfl.scala.sbt.release.ReleaseEarlyPlugin.autoImport._ import com.lucidchart.sbt.scalafmt.ScalafmtCorePlugin -import com.lucidchart.sbt.scalafmt.ScalafmtCorePlugin.{ autoImport => ScalafmtKeys } +import com.lucidchart.sbt.scalafmt.ScalafmtCorePlugin.autoImport._ import com.lucidchart.sbt.scalafmt.ScalafmtSbtPlugin.autoImport.Sbt -import com.typesafe.tools.mima.plugin.MimaKeys import com.typesafe.tools.mima.plugin.MimaPlugin -import sbt.librarymanagement.ivy.{ InlineIvyConfiguration, IvyDependencyResolution } +import com.typesafe.tools.mima.plugin.MimaKeys._ object BuildPlugin extends AutoPlugin { override def requires = @@ -22,15 +22,12 @@ object BuildPlugin extends AutoPlugin { } trait BuildKeys { - import sbt.{ TaskKey, taskKey } - val tearDownBenchmarkResources: TaskKey[Unit] = taskKey[Unit]("Remove benchmark resources.") val scriptedPublish = taskKey[Unit]("Publishes all the Zinc artifacts for scripted") val cachedPublishLocal = taskKey[Unit]("Publishes a project if it hasn't been published before.") } object BuildAutoImported extends BuildKeys { - import sbt.{ file, File, Developer, url, State } import BuildImplementation.{ BuildDefaults, BuildResolvers } val baseVersion: String = "1.1.0-SNAPSHOT" @@ -48,9 +45,9 @@ object BuildAutoImported extends BuildKeys { // Sets up mima settings for modules that have to be binary compatible with Zinc 1.0.0 val mimaSettings: Seq[Def.Setting[_]] = - List(MimaKeys.mimaPreviousArtifacts := BuildDefaults.zincPreviousArtifacts.value) + List(mimaPreviousArtifacts := BuildDefaults.zincPreviousArtifacts.value) val adaptOptionsForOldScalaVersions: Seq[Def.Setting[_]] = - List(Keys.scalacOptions := BuildDefaults.zincScalacOptionsRedefinition.value) + List(scalacOptions := BuildDefaults.zincScalacOptionsRedefinition.value) val benchmarksTestDir = sbt.IO.createTemporaryDirectory def inCompileAndTest(ss: Def.Setting[_]*): Seq[Def.Setting[_]] = @@ -58,18 +55,16 @@ object BuildAutoImported extends BuildKeys { } object BuildImplementation { - import sbt.{ fileToRichFile, file, File, ThisBuild, Tags } - val buildSettings: Seq[Def.Setting[_]] = List( Scripted.scriptedBufferLog := true, - GitKeys.baseVersion := BuildAutoImported.baseVersion, - GitKeys.gitUncommittedChanges := BuildDefaults.gitUncommitedChanges.value, - BintrayKeys.bintrayPackage := "zinc", - ScalafmtKeys.scalafmtOnCompile := true, - ScalafmtKeys.scalafmtVersion := "1.2.0", - ScalafmtKeys.scalafmtOnCompile in Sbt := false, - ReleaseEarlyKeys.releaseEarlyWith := ReleaseEarlyKeys.BintrayPublisher, - Keys.description := "Incremental compiler of Scala", + baseVersion := BuildAutoImported.baseVersion, + gitUncommittedChanges := BuildDefaults.gitUncommitedChanges.value, + bintrayPackage := "zinc", + scalafmtOnCompile := true, + scalafmtVersion := "1.2.0", + scalafmtOnCompile in Sbt := false, + releaseEarlyWith := BintrayPublisher, + description := "Incremental compiler of Scala", // The rest of the sbt developers come from the Sbt Houserules plugin developers += BuildAutoImported.ScalaCenterMaintainer, homepage := Some(BuildAutoImported.ZincGitHomepage), @@ -86,14 +81,14 @@ object BuildImplementation { val projectSettings: Seq[Def.Setting[_]] = List( // publishArtifact in packageDoc := false, // concurrentRestrictions in Global += Util.testExclusiveRestriction, - Keys.scalaVersion := Dependencies.scala212, - Keys.resolvers ++= BuildResolvers.all, - Keys.resolvers ~= BuildResolvers.removeRepeatedResolvers, - Keys.testOptions += Tests.Argument(TestFrameworks.ScalaCheck, "-w", "1"), - Keys.javacOptions in Compile ++= Seq("-Xlint", "-Xlint:-serial"), - Keys.crossScalaVersions := Seq(Dependencies.scala211, Dependencies.scala212), - Keys.publishArtifact in Test := false, - Keys.scalacOptions += "-YdisableFlatCpCaching", + scalaVersion := Dependencies.scala212, + resolvers ++= BuildResolvers.all, + resolvers ~= BuildResolvers.removeRepeatedResolvers, + testOptions += Tests.Argument(TestFrameworks.ScalaCheck, "-w", "1"), + javacOptions in Compile ++= Seq("-Xlint", "-Xlint:-serial"), + crossScalaVersions := Seq(Dependencies.scala211, Dependencies.scala212), + publishArtifact in Test := false, + scalacOptions += "-YdisableFlatCpCaching", BuildAutoImported.cachedPublishLocal := BuildDefaults.cachedPublishLocal.value, publishArtifact in (Compile, packageDoc) := BuildDefaults.publishDocAndSourceArtifact.value, @@ -177,7 +172,7 @@ object BuildImplementation { // https://github.com/sbt/sbt-git/issues/109 val gitUncommitedChanges: Def.Initialize[Boolean] = Def.setting { // Workaround from https://github.com/sbt/sbt-git/issues/92#issuecomment-161853239 - val dir = Keys.baseDirectory.value + val dir = baseDirectory.value // can't use git.runner.value because it's a task val runner = com.typesafe.sbt.git.ConsoleGitRunner // sbt/zinc#334 Seemingly "git status" resets some stale metadata. @@ -186,7 +181,7 @@ object BuildImplementation { val res = runner(c: _*)(dir, com.typesafe.sbt.git.NullLogger) if (res.isEmpty) Nil else List(c -> res) } - val logger = Keys.sLog.value + val logger = sLog.value val areUncommited = uncommittedChanges.nonEmpty if (areUncommited) { uncommittedChanges.foreach { @@ -199,8 +194,8 @@ object BuildImplementation { import sbt.{ CrossVersion, ModuleID, stringToOrganization } val zincPreviousArtifacts: Def.Initialize[Set[ModuleID]] = Def.setting { - val zincModule = (Keys.organization.value % Keys.moduleName.value % "1.0.0") - .cross(if (Keys.crossPaths.value) CrossVersion.binary else CrossVersion.disabled) + val zincModule = (organization.value % moduleName.value % "1.0.0") + .cross(if (crossPaths.value) CrossVersion.binary else CrossVersion.disabled) Set(zincModule) } @@ -213,8 +208,8 @@ object BuildImplementation { ) val zincScalacOptionsRedefinition: Def.Initialize[Task[Seq[String]]] = Def.task { - val old = Keys.scalacOptions.value - Keys.scalaBinaryVersion.value match { + val old = scalacOptions.value + scalaBinaryVersion.value match { case v if v == "2.12" || v == "2.13" => old case _ => old.filterNot(toFilterInOldScala) } @@ -246,6 +241,7 @@ object BuildImplementation { !isDynVerSnapshot(DynVerKeys.dynverGitDescribeOutput.value, isSnapshot.value) } + import scala.Console private val P = "[" + wrapIn(Console.BOLD + Console.CYAN, "scripted") + "]" val cachedPublishLocal: Def.Initialize[Task[Unit]] = Def.taskDyn { import BuildResolvers.{ ScriptedResolveCacheDir, ScriptedResolver } @@ -273,6 +269,7 @@ object BuildImplementation { // We can do this because we resolve intransitively and nobody but this task publishes .withLock(None) + import sbt.librarymanagement.ivy.IvyDependencyResolution val resolution = IvyDependencyResolution(fasterIvyConfig) val result = resolution.retrieve(moduleID, scalaModule, ScriptedResolveCacheDir, NoLogger) result match { @@ -329,18 +326,18 @@ object BuildImplementation { logger.warn(s"$P Publishing `$name`, version: '$version'.") val moduleSettings = Keys.moduleSettings.value - val publishConfig = Keys.publishLocalConfiguration.value + val publishConfig = publishLocalConfiguration.value publishLocal(moduleSettings, publishConfig) } } val noPublishSettings: Seq[Def.Setting[_]] = List( - Keys.publish := {}, - Keys.publishLocal := {}, - Keys.publishArtifact in Compile := false, - Keys.publishArtifact in Test := false, - Keys.publishArtifact := false, - Keys.skip in Keys.publish := true, + publish := {}, + publishLocal := {}, + publishArtifact in Compile := false, + publishArtifact in Test := false, + publishArtifact := false, + skip in publish := true, ) private[this] def wrapIn(color: String, content: String): String = { @@ -350,9 +347,9 @@ object BuildImplementation { } private[this] val scalaPartialVersion = - Def.setting(CrossVersion.partialVersion(Keys.scalaVersion.value)) + Def.setting(CrossVersion.partialVersion(scalaVersion.value)) val handleScalaSpecificSources: Def.Initialize[List[File]] = Def.setting { - val source = Keys.scalaSource.value + val source = scalaSource.value scalaPartialVersion.value.collect { case (2, y) if y == 10 => new File(source.getPath + "_2.10") case (2, y) if y >= 11 => new File(source.getPath + "_2.11+") @@ -372,8 +369,8 @@ object BuildImplementation { val logged = scriptedBufferLog.value val hook = scriptedPrescripted.value - val scriptedClasspath = (Keys.fullClasspath in scriptedRef in Test).value - val instance = (Keys.scalaInstance in scriptedRef).value + val scriptedClasspath = (fullClasspath in scriptedRef in Test).value + val instance = (scalaInstance in scriptedRef).value Scripted.doScripted(scriptedClasspath, instance, source, result, logged, hook) } From af3fa212e966adc064bae85896b1fa544b2e7cd7 Mon Sep 17 00:00:00 2001 From: jvican Date: Tue, 14 Nov 2017 01:03:24 +0100 Subject: [PATCH 20/20] Use scripted resolver in ALL tests --- .../inc/BridgeProviderSpecification.scala | 16 +++++++++++++++- .../test/scala/sbt/internal/inc/IncHandler.scala | 16 ---------------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index 60fdfc7b04..8acad93e9a 100644 --- a/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/internal/zinc-ivy-integration/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -26,7 +26,21 @@ abstract class BridgeProviderSpecification extends UnitSpec { def currentTarget: File = currentBase / "target" / "ivyhome" def currentManaged: File = currentBase / "target" / "lib_managed" - val resolvers = Array(ZincComponentCompiler.LocalResolver, Resolver.mavenCentral) + private final val ZincScriptedLocal = + s"$${user.dir}/.ivy2/zinc-scripted-local/${Resolver.localBasePattern}" + private final val ScriptedResolver: Resolver = { + import sbt.librarymanagement.{ FileRepository, Patterns } + val toUse = Vector(ZincScriptedLocal) + val ivyPattern = Patterns().withIsMavenCompatible(false) + val finalPatterns = ivyPattern + .withIvyPatterns(toUse) + .withArtifactPatterns(toUse) + .withSkipConsistencyCheck(true) + FileRepository("zinc-scripted-local", Resolver.defaultFileConfiguration, finalPatterns) + } + + // Use the scripted resolver to make sure that we don't mistakenly get user local jars + val resolvers = Array(ScriptedResolver, Resolver.mavenCentral) private def ivyConfiguration = getDefaultConfiguration(currentBase, currentTarget, resolvers, log) diff --git a/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncHandler.scala b/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncHandler.scala index 6deb42cc91..4ae4df8d7d 100644 --- a/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncHandler.scala +++ b/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncHandler.scala @@ -64,22 +64,6 @@ final class IncHandler(directory: File, cacheDir: File, scriptedLog: ManagedLogg type State = Option[IncInstance] type IncCommand = (ProjectStructure, List[String], IncInstance) => Unit - private final val ZincScriptedLocal = - s"$${user.dir}/.ivy2/zinc-scripted-local/${Resolver.localBasePattern}" - private final val ScriptedResolver: Resolver = { - import sbt.librarymanagement.{ FileRepository, Patterns } - val toUse = Vector(ZincScriptedLocal) - val ivyPattern = Patterns().withIsMavenCompatible(false) - val finalPatterns = ivyPattern - .withIvyPatterns(toUse) - .withArtifactPatterns(toUse) - .withSkipConsistencyCheck(true) - FileRepository("zinc-scripted-local", Resolver.defaultFileConfiguration, finalPatterns) - } - - // Use the scripted resolver to make sure that we don't mistakenly get other jars - override val resolvers: Array[Resolver] = Array(ScriptedResolver, Resolver.mavenCentral) - val compiler = new IncrementalCompilerImpl def initialState: Option[IncInstance] = {