8.8 KiB
Fixes with compatibility implications
- Rolls back XML parsing workaround. See below.
Improvements
- Adds Maven resolver plugin. See below. #1793 by @jsuereth
- Adds project-level dependency exclusions. See below. #1748 by @eed3si9n
- Adds sequential tasks. See below. #1817/#1001 by @eed3si9n
- Discovered main classes will be sorted. #1180 by @kretes
- Implemented a new mechanism of forking javac, whereby errors are captured. Also more likely to run in-process. #1702 by @jsuereth
evictedwill display all evictions (including the ones not suspected of binary incompatibility). #1615 by @eed3si9n
Fixes
- Javac warnings are treated as warnings. #1702/#875 by @jsuereth
compilerReporteris fed to javac during incremental compilation. #1542 by @jsuereth- Ignores hidden build files from the build. #1746 by @j-keck
- Fixes build.sbt parsing of multiple import. #1741 by @ajozwik
- Fixes ANSI escape code for overwriting lines on Windows. #1771 by @dwickern
- sbt doesn't honor Maven's uniqueVersions (use sbt-maven-resolver to fix). #1322 by @jsuereth
- sbt doesn't see new SNAPSHOT dependency versions in local maven repos (use withLatestSnapshots + sbt-maven-resolver to fix) [#321][321] by @jsuereth
- Property in pom's version field results to wrong dependency resolution (use sbt-maven-resolver to fix). #647 by @jsuereth
- Maven local resolver with parent POM (use sbt-maven-resolver). #1616 by @jsuereth
- Fixes cached resolution being too verbose. #1752 by @eed3si9n
- Fixes eviction warning being too noisy. #1615 by @eed3si9n
- Issues warning if multiple dependencies to a same library is found with different version. #1634 by @eed3si9n
- Removes "No main class detected" warning. #1766 by @eed3si9n
Rolling back XML parsing workaround
sbt 0.13.7 implemented natural whitespace handling by switching build.sbt parsing to use Scala compiler, instead of blank line delimiting. We realized that some build definitions no longer parsed due to the difference in XML handling.
val a = <x/><y/>
val b = 0
At the time, we thought adding parentheses around XML nodes could work around this behavior. However, the workaround has caused more issues, and since then we have realized that this is a compiler issue SI-9027, so we have decided to roll back our workaround. In the meantime, if you have consecutive XML elements in your build.sbt, enclose them in <xml:group> tag, or parentheses.
val a = <xml:group><x/><y/></xml:group>
val b = 0
[#1765][1765] by @ajozwik
Maven resolver plugin
sbt 0.13.8 adds an extension point in the dependency resolution to customize Maven resolvers. This allows us to write sbt-maven-resolver auto plugin, which internally uses Eclipse Aether to resolve Maven dependencies instead of Apache Ivy.
To enable this plugin, add the following to project/maven.sbt (or project/plugin.sbt the file name doesn't matter):
libraryDependencies += Defaults.sbtPluginExtra("org.scala-sbt" % "sbt-maven-resolver" % sbtVersion.value,
sbtBinaryVersion.value, scalaBinaryVersion.value)
This will create a new ~/.ivy2/maven-cache directory, which contains the Aether cache of files.
You may notice some file will be re-downloaded for the new cache layout.
Additionally, sbt will now be able to fully construct
maven-metadata.xml files when publishing to remote repositories or when publishing to the local ~/.m2/repository.
This should help erase many of the deficiencies encountered when using Maven and sbt together.
Notes and known limitations:
- sbt-maven-resolver requires sbt 0.13.8 and above.
- The current implementation does not support Ivy-style dynamic revisions, such as "2.10.+" or "latest.snapshot". This is a fixable situation, but the version range query and Ivy -> Maven version range translation code has not been migrated.
Project-level dependency exclusions
sbt 0.13.8 adds project-level dependency exclusions:
excludeDependencies += "org.apache.logging.log4j"
excludeDependencies += "com.example" %% "foo"
In the first example, all artifacts from the organization "org.apache.logging.log4j" are excluded from the managed dependency.
In the second example, artifacts with the organization "com.example" and the name "foo" cross versioned to the current scalaVersion are excluded. #1748 by @eed3si9n
Sequential tasks
sbt 0.13.8 adds a new Def.sequential function to run tasks under semi-sequential semantics.
Here's an example usage:
lazy val root = project.
settings(
testFile := target.value / "test.txt",
sideEffect0 := {
val t = testFile.value
IO.append(t, "0")
t
},
sideEffect1 := {
val t = testFile.value
IO.append(t, "1")
t
},
foo := Def.sequential(compile in Compile, sideEffect0, sideEffect1, test in Test).value
)
Normally sbt's task engine will reorder tasks based on the dependencies among the tasks,
and run as many tasks in parallel (See Custom settings and tasks for more details on this).
Def.sequential instead tries to run the tasks in the specified order.
However, the task engine will still deduplicate tasks. For instance, when foo is executed, it will only compile once,
even though test in Test depends on compile. #1817/#1001 by @eed3si9n
Bytecode Enhancers
sbt 0.13.8 adds an extension point whereby users can effectively manipulate java bytecode (.class files) before the incremental compiler attempts to cache the classfile hashes. This allows libraries like ebean to function with sbt without corrupting the compiler cache and rerunning compile every few seconds.
This splits the compile task into several subTasks:
previousCompile: This task returns the previously persistedAnalysisobject for this project.compileIncremental: This is the core logic of compiling Scala/Java files together. This task actually does the work of compiling a project incrementally, including ensuring a minimum number of source files are compiled. After this method, all .class files that would be generated by scalac + javac will be available.manipulateByteCode: This is a stub task which takes thecompileIncrementalresult and returns it. Plugins which need to manipulate bytecode are expected to override this task with their own implementation, ensuring to call the previous behavior.compile: This task depends onmanipulateBytecodeand then persists theAnalysisobject containing all incremental compiler information.
Here's an example of how to hook the new manipulateBytecode key in your own plugin:
manipulateBytecode in Compile := {
val previous = (manipulateBytecode in Compile).value
doManipulateBytecode(previous) // Note: This must return a new Compiler.CompileResult with our changes.
}
See #1714 for the full details of the implementation.