diff --git a/src/sphinx/Community/ChangeSummary_0.13.0.rst b/src/sphinx/Community/ChangeSummary_0.13.0.rst index ca3dd6484..f29c2c084 100644 --- a/src/sphinx/Community/ChangeSummary_0.13.0.rst +++ b/src/sphinx/Community/ChangeSummary_0.13.0.rst @@ -57,6 +57,7 @@ Improvements - Make autoCompilerPlugins support compiler plugins defined in a internal dependency (only if ``exportJars := true`` due to scalac limitations) - Track ancestors of non-private templates and use this information to require fewer, smaller intermediate incremental compilation steps. - ``autoCompilerPlugins`` now supports compiler plugins defined in a internal dependency. The plugin project must define ``exportJars := true``. Depend on the plugin with ``...dependsOn(... % Configurations.CompilerPlugin)``. +- Add utilities for debugging API representation extracted by the incremental compiler. (Grzegorz K., gh-677, gh-793) Other ----- diff --git a/src/sphinx/Detailed-Topics/Command-Line-Reference.rst b/src/sphinx/Detailed-Topics/Command-Line-Reference.rst index c61f8217c..b55e9a6ad 100644 --- a/src/sphinx/Detailed-Topics/Command-Line-Reference.rst +++ b/src/sphinx/Detailed-Topics/Command-Line-Reference.rst @@ -182,325 +182,47 @@ System properties can be provided either as JVM options, or as SBT arguments, in both cases as ``-Dprop=value``. The following properties influence SBT execution. Also see :doc:`Launcher`. -.. raw:: html - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -.. raw:: html - - - - - ++------------------------------+-----------+---------------------+----------------------------------------------------+ +| Property | Values | Default | Meaning | ++==============================+===========+=====================+====================================================+ +| ``sbt.log.noformat`` | Boolean | false | If true, disable ANSI color codes. Useful on build | +| | | | servers or terminals that don't support color. | ++------------------------------+-----------+---------------------+----------------------------------------------------+ +| ``sbt.global.base`` | Directory | ~/.sbt | The directory containing global settings and | +| | | | plugins | ++------------------------------+-----------+---------------------+----------------------------------------------------+ +| ``sbt.ivy.home`` | Directory | ~/.ivy2 | The directory containing the local Ivy repository | +| | | | and artifact cache | ++------------------------------+-----------+---------------------+----------------------------------------------------+ +| ``sbt.boot.directory`` | Directory | ~/.sbt/boot | Path to shared boot directory | ++------------------------------+-----------+---------------------+----------------------------------------------------+ +| ``sbt.main.class`` | String | | | ++------------------------------+-----------+---------------------+----------------------------------------------------+ +| ``xsbt.inc.debug`` | Boolean | false | | ++------------------------------+-----------+---------------------+----------------------------------------------------+ +| ``sbt.extraClasspath`` | Classpath | | A list of classpath entries (jar files or | +| | Entries | | directories) that are added to sbt's classpath. | +| | | | Note that the entries are deliminted by comma, | +| | | | e.g.: ``entry1, entry2,..``. See also | +| | | | ``resources`` in the :doc:`Launcher` | +| | | | documentation. | ++------------------------------+-----------+---------------------+----------------------------------------------------+ +| ``sbt.version`` | Version | 0.11.3 | sbt version to use, usually taken from | +| | | | project/build.properties | ++------------------------------+-----------+---------------------+----------------------------------------------------+ +| ``sbt.boot.properties`` | File | | | ++------------------------------+-----------+---------------------+----------------------------------------------------+ +| ``sbt.override.build.repos`` | Boolean | false | If true, repositories configured in a build | +| | | | definition are ignored and the repositories | +| | | | configured for the launcher are used instead. See | +| | | | ``sbt.repository.config`` and the :doc:`Launcher` | +| | | | documentation. | ++------------------------------+-----------+---------------------+----------------------------------------------------+ +| ``sbt.repository.config`` | File | ~/.sbt/repositories | A file containing the repositories to use for the | +| | | | launcher. The format is the same as a | +| | | | ``[repositories]`` section for a :doc:`Launcher` | +| | | | configuration file. This setting is typically used | +| | | | in conjuction with setting | +| | | | ``sbt.override.build.repos`` to true (see previous | +| | | | row and the :doc:`Launcher` documentation). | ++------------------------------+-----------+---------------------+----------------------------------------------------+ diff --git a/src/sphinx/Detailed-Topics/Understanding-incremental-recompilation.rst b/src/sphinx/Detailed-Topics/Understanding-incremental-recompilation.rst index 9c6188fbb..51b96d3ee 100644 --- a/src/sphinx/Detailed-Topics/Understanding-incremental-recompilation.rst +++ b/src/sphinx/Detailed-Topics/Understanding-incremental-recompilation.rst @@ -56,10 +56,60 @@ SBT heuristics SBT tracks source dependencies at the granularity of source files. For each source file, SBT tracks files which depend on it directly; if the **interface** of classes, objects or traits in a file changes, all files -dependent on that source must be recompiled. In particular, this -currently includes all transitive dependencies, that is, also -dependencies of dependencies, dependencies of these and so on to -arbitrary depth. +dependent on that source must be recompiled. At the moment sbt uses the +following algorithm to calculate source files dependent on a given source +file: + + - dependencies introduced through inheritance are included *transitively*; + a dependency is introduced through inheritance if a class/trait in one + file inherits from a trait/class in another file + - all other direct dependencies are included; other dependencies are also + called "meber reference" dependencies because they are introduced by + referring to a member (class, method, type, etc.) defined in some other + source file + +Here's an example illustrating the definition above:: + + //A.scala + class A { + def foo: Int = 123 + } + + //B.scala + class B extends A + + //C.scala + class C extends B + + //D.scala + class D(a: A) + + //E.scala + class E(d: D) + +There are the following dependencies through inheritance: + +.. code-block:: none + + B.scala -> A.scala + C.scala -> B.scala + +There are also the following member reference dependencies: + +.. code-block:: none + + D.scala -> A.scala + E.scala -> D.scala + +Now if the interface of ``A.scala`` is changed the following files +will get invalidated: ``B.scala``, ``C.scala``, ``D.scala``. Both +``B.scala`` and ``C.scala`` were included through transtive closure +of inheritance dependencies. The ``E.scala`` was not included because +``E.scala`` doesn't depend directly on ``A.scala``. + +The distinction between depdencies by inheritance or member reference +is a new feature in sbt 0.13 and is responsible for improved recompilation +times in many cases where deep inheritance chains are not used extensively. SBT does not instead track dependencies to source code at the granularity of individual output ``.class`` files, as one might hope. @@ -107,6 +157,83 @@ just to illustrate the ideas; this list is not intended to be complete. issue `SI-2559 `_ for an example.) +Debugging an interface representation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you see spurious incremental recompilations or you want understand +what changes to an extracted interface cause incremental recompilation +then sbt 0.13 has the right tools for that. + +In order to debug the interface representation and its changes as you +modify and recompile source code you need to do two things: + + 1. Enable incremental compiler's ``apiDebug`` option. + 2. Add `diff-utils library `_ + to sbt's classpath. Check documentation of `sbt.extraClasspath` + system property in the :doc:`Command-Line-Reference`. + +.. warning:: Enabling the ``apiDebug`` option increases significantly + memory consumption and degrades performance of the + incremental compiler. The underlaying reason is that in + order to produce meaningful debugging information about + interface differences incremental compiler has to retain + the full representation of the interface instead of just + hash sum as it does by default. + + Keep this option enabled when you are debugging incremental + compiler problem only. + +Below is complete transcript which shows how to enable interface debugging +in your project. First, we download the ``diffutils`` jar and pass it +to sbt: + +.. code-block:: none + + curl -O https://java-diff-utils.googlecode.com/files/diffutils-1.2.1.jar + sbt -Dsbt.extraClasspath=diffutils-1.2.1.jar + [info] Loading project definition from /Users/grek/tmp/sbt-013/project + [info] Set current project to sbt-013 (in build file:/Users/grek/tmp/sbt-013/) + > set incOptions := incOptions.value.copy(apiDebug = true) + [info] Defining *:incOptions + [info] The new value will be used by compile:incCompileSetup, test:incCompileSetup + [info] Reapplying settings... + [info] Set current project to sbt-013 (in build file:/Users/grek/tmp/sbt-013/) + +Let's suppose you have the following source code in ``Test.scala``:: + + class A { + def b: Int = 123 + } + +compile it and then change the ``Test.scala`` file so it looks like:: + + class A { + def b: String = "abc" + } + +and run `compile` task again. Now if you run `last compile` you should see +the following lines in the debugging log + +.. code-block:: none + + > last compile + [...] + [debug] Detected a change in a public API: + [debug] --- /Users/grek/tmp/sbt-013/Test.scala + [debug] +++ /Users/grek/tmp/sbt-013/Test.scala + [debug] @@ -23,7 +23,7 @@ + [debug] ^inherited^ final def ##(): scala.this#Int + [debug] ^inherited^ final def synchronized[ java.lang.Object.T0 >: scala.this#Nothing <: scala.this#Any](x$1: ): + [debug] ^inherited^ final def $isInstanceOf[ java.lang.Object.T0 >: scala.this#Nothing <: scala.this#Any](): scala.this#Boolean + [debug] ^inherited^ final def $asInstanceOf[ java.lang.Object.T0 >: scala.this#Nothing <: scala.this#Any](): + [debug] def (): this#A + [debug] -def b: scala.this#Int + [debug] +def b: java.lang.this#String + [debug] } + +You can see an unified diff of two interface textual represetantions. As you can see, +the incremental compiler detected a change to the return type of `b` method. + How to take advantage of SBT heuristics ---------------------------------------
- -*Property* - -.. raw:: html - - - -*Values* - -.. raw:: html - - - -*Default* - -.. raw:: html - - - -*Meaning* - -.. raw:: html - -
- -``sbt.log.format`` - -.. raw:: html - - - -Boolean - -.. raw:: html - - - -unset - -.. raw:: html - - - -If true, enable ANSI escape codes such as colors. -If false, disable them, which can be useful on build servers or terminals -that don't support color. -If unset, whether to use escape codes is automatically detected. - -.. raw:: html - -
- -``sbt.global.base`` - -.. raw:: html - - - -Directory - -.. raw:: html - - - -``~/.sbt`` - -.. raw:: html - - - -The directory containing global settings and plugins - -.. raw:: html - -
- -``sbt.ivy.home`` - -.. raw:: html - - - -Directory - -.. raw:: html - - - -``~/.ivy2`` - -.. raw:: html - - - -The directory containing the local Ivy repository and artifact cache - -.. raw:: html - -
- -``sbt.boot.directory`` - -.. raw:: html - - - -Directory - -.. raw:: html - - - -``~/.sbt/boot`` - -.. raw:: html - - - -Path to shared boot directory - -.. raw:: html - -
- -``sbt.main.class`` - -.. raw:: html - - - -String - -.. raw:: html - -
- -``xsbt.inc.debug`` - -.. raw:: html - - - -Boolean - -.. raw:: html - - - -false - -.. raw:: html - -
- -``sbt.version`` - -.. raw:: html - - - -Version - -.. raw:: html - - - -0.11.3 - -.. raw:: html - - - -sbt version to use, usually taken from project/build.properties - -.. raw:: html - -
- -``sbt.boot.properties`` - -.. raw:: html - - - -File - -.. raw:: html - -
- -``sbt.override.build.repos`` - -.. raw:: html - - - -Boolean - -.. raw:: html - - - -false - -.. raw:: html - - - -If true, repositories configured in a build definition are ignored and -the repositories configured for the launcher are used instead. See -``sbt.repository.config`` and the :doc:`Launcher` documentation. - -.. raw:: html - -
- -``sbt.repository.config`` - -.. raw:: html - - - -File - -.. raw:: html - - - -~/.sbt/repositories - -.. raw:: html - - - -A file containing the repositories to use for the launcher. The format -is the same as a ``[repositories]`` section for a :doc:`Launcher` -configuration file. This setting is typically used in conjuction with -setting ``sbt.override.build.repos`` to true (see previous row and the -:doc:`Launcher` documentation). - -.. raw:: html - -