Docs: initial pass for updated task syntax, vals in .sbt, camelCase

This commit is contained in:
Mark Harrah 2012-11-18 20:29:01 -05:00
parent bb1725f580
commit 132e29415b
57 changed files with 716 additions and 1563 deletions

View File

@ -38,9 +38,9 @@ To automatically deploy snapshot/release versions of your plugin use the followi
::
publishTo <<= (version) { version: String =>
publishTo := {
val scalasbt = "http://repo.scala-sbt.org/scalasbt/"
val (name, url) = if (version.contains("-SNAPSHOT"))
val (name, url) = if (version.value.contains("-SNAPSHOT"))
("sbt-plugin-snapshots", scalasbt+"sbt-plugin-snapshots")
else
("sbt-plugin-releases", scalasbt+"sbt-plugin-releases")

View File

@ -32,9 +32,9 @@ the same URLs for everyone:
::
publishTo <<= version { (v: String) =>
publishTo := {
val nexus = "https://oss.sonatype.org/"
if (v.trim.endsWith("SNAPSHOT"))
if (version.value.trim.endsWith("SNAPSHOT"))
Some("snapshots" at nexus + "content/repositories/snapshots")
else
Some("releases" at nexus + "service/local/staging/deploy/maven2")
@ -226,9 +226,9 @@ others:
::
publishTo <<= version { v: String =>
publishTo := {
val nexus = "https://oss.sonatype.org/"
if (v.trim.endsWith("SNAPSHOT"))
if (version.value.trim.endsWith("SNAPSHOT"))
Some("snapshots" at nexus + "content/repositories/snapshots")
else
Some("releases" at nexus + "service/local/staging/deploy/maven2")

View File

@ -46,7 +46,7 @@ Modifying default artifacts
===========================
Each built-in artifact has several configurable settings in addition to
``publish-artifact``. The basic ones are ``artifact`` (of type
``publishArtifact``. The basic ones are ``artifact`` (of type
``SettingKey[Artifact]``), ``mappings`` (of type
``TaskKey[(File,String)]``), and ``artifactPath`` (of type
``SettingKey[File]``). They are scoped by ``(<config>, <task>)`` as
@ -60,7 +60,7 @@ To modify the type of the main artifact, for example:
art.copy(`type` = "bundle")
}
The generated artifact name is determined by the ``artifact-name``
The generated artifact name is determined by the ``artifactName``
setting. This setting is of type
``(ScalaVersion, ModuleID, Artifact) => String``. The ScalaVersion
argument provides the full Scala version String and the binary
@ -83,9 +83,9 @@ path:
(Note that in practice you rarely want to drop the classifier.)
Finally, you can get the ``(Artifact, File)`` pair for the artifact by
mapping the ``packaged-artifact`` task. Note that if you don't need the
mapping the ``packagedArtifact`` task. Note that if you don't need the
``Artifact``, you can get just the File from the package task
(``package``, ``package-doc``, or ``package-src``). In both cases,
(``package``, ``packageDoc``, or ``packageSrc``). In both cases,
mapping the task to get the file ensures that the artifact is generated
first and so the file is guaranteed to be up-to-date.
@ -93,7 +93,8 @@ For example:
::
myTask <<= packagedArtifact in (Compile, packageBin) map { case (art: Artifact, file: File) =>
myTask := {
val (art, file) = packagedArtifact.in(Compile, packageBin).value
println("Artifact definition: " + art)
println("Packaged file: " + file.getAbsolutePath)
}

View File

@ -26,9 +26,9 @@ beginning of the resolvers list:
::
resolvers <<= resolvers {rs =>
resolvers := {
val localMaven = "Local Maven Repository" at "file://"+Path.userHome.absolutePath+"/.m2/repository"
localMaven +: rs
localMaven +: resolvers.value
}
1. Put settings specific to a user in a global ``.sbt`` file, such as
@ -68,7 +68,7 @@ respect that. Instead, use the setting, like:
::
myDirectory <<= target(_ / "sub-directory")
myDirectory := target.value / "sub-directory"
Don't "mutate" files
~~~~~~~~~~~~~~~~~~~~
@ -92,7 +92,7 @@ For example:
::
lazy val makeFile = TaskKey[File]("make-file")
lazy val makeFile = TaskKey[File]("makeFile")
// define a task that creates a file,
// writes some content, and returns the File
@ -106,9 +106,8 @@ For example:
// The result of makeFile is the constructed File,
// so useFile can map makeFile and simultaneously
// get the File and declare the dependency on makeFile
useFile <<= makeFile map { (f: File) =>
doSomething( f )
}
useFile :=
doSomething( makeFile.value )
This arrangement is not always possible, but it should be the rule and
not the exception.
@ -135,7 +134,7 @@ directory.
::
myPath <<= baseDirectory(_ / "licenses")
myPath := baseDirectory.value / "licenses"
In Java (and thus in Scala), a relative File is relative to the current
working directory. The working directory is not always the same as the

View File

@ -53,32 +53,24 @@ Tasks that produce managed files should be inserted as follows:
::
sourceGenerators in Compile <+= sourceManaged in Compile map { out =>
generate(out / "some_directory")
}
sourceGenerators in Compile +=
generate( (sourceManaged in Compile).value / "some_directory")
In this example, ``generate`` is some function of type
``File => Seq[File]`` that actually does the work. The ``<+=`` method is
like ``+=``, but allows the right hand side to have inputs (like the
difference between ``:=`` and ``<<=``). So, we are appending a new task
``File => Seq[File]`` that actually does the work. So, we are appending a new task
to the list of main source generators (``sourceGenerators in Compile``).
To insert a named task, which is the better approach for plugins:
::
sourceGenerators in Compile <+= (mySourceGenerator in Compile).task
mySourceGenerator in Compile <<= sourceManaged in Compile map { out =>
generate(out / "some_directory")
}
where ``mySourceGenerator`` is defined as:
::
val mySourceGenerator = TaskKey[Seq[File]](...)
mySourceGenerator in Compile :=
generate( (sourceManaged in Compile).value / "some_directory")
sourceGenerators in Compile += (mySourceGenerator in Compile).task
The ``task`` method is used to refer to the actual task instead of the
result of the task.
@ -115,33 +107,33 @@ Keys
For classpaths, the relevant keys are:
- ``unmanaged-classpath``
- ``managed-classpath``
- ``external-dependency-classpath``
- ``internal-dependency-classpath``
- ``unmanagedClasspath``
- ``managedClasspath``
- ``externalDependencyClasspath``
- ``internalDependencyClasspath``
For sources:
- ``unmanaged-sources`` These are by default built up from
``unmanaged-source-directories``, which consists of ``scala-source``
and ``java-source``.
- ``managed-sources`` These are generated sources.
- ``sources`` Combines ``managed-sources`` and ``unmanaged-sources``.
- ``source-generators`` These are tasks that generate source files.
- ``unmanagedSources`` These are by default built up from
``unmanagedSourceDirectories``, which consists of ``scalaSource``
and ``javaSource``.
- ``managedSources`` These are generated sources.
- ``sources`` Combines ``managedSources`` and ``unmanagedSources``.
- ``sourceGenerators`` These are tasks that generate source files.
Typically, these tasks will put sources in the directory provided by
``source-managed``.
``sourceManaged``.
For resources
- ``unmanaged-resources`` These are by default built up from
``unmanaged-resource-directories``, which by default is
``resource-directory``, excluding files matched by
``default-excludes``.
- ``managed-resources`` By default, this is empty for standard
- ``unmanagedResources`` These are by default built up from
``unmanagedResourceDirectories``, which by default is
``resourceDirectory``, excluding files matched by
``defaultExcludes``.
- ``managedResources`` By default, this is empty for standard
projects. sbt plugins will have a generated descriptor file here.
- ``resource-generators`` These are tasks that generate resource files.
- ``resourceGenerators`` These are tasks that generate resource files.
Typically, these tasks will put resources in the directory provided
by ``resource-managed``.
by ``resourceManaged``.
Use the :doc:`inspect command </Detailed-Topics/Inspecting-Settings>` for more details.
@ -158,10 +150,4 @@ in classpath.
::
unmanagedClasspath in Runtime <<= (unmanagedClasspath in Runtime, baseDirectory) map { (cp, bd) => cp :+ Attributed.blank(bd / "config") }
Or shorter:
::
unmanagedClasspath in Runtime <+= (baseDirectory) map { bd => Attributed.blank(bd / "config") }
unmanagedClasspath in Runtime += baseDirectory.value / "config"

View File

@ -28,10 +28,10 @@ Project-level tasks
-------------------
- ``clean`` Deletes all generated files (the ``target`` directory).
- ``publish-local`` Publishes artifacts (such as jars) to the local Ivy
- ``publishLocal`` Publishes artifacts (such as jars) to the local Ivy
repository as described in :doc:`Publishing`.
- ``publish`` Publishes artifacts (such as jars) to the repository
defined by the ``publish-to`` setting, described in :doc:`Publishing`.
defined by the ``publishTo`` setting, described in :doc:`Publishing`.
- ``update`` Resolves and retrieves external dependencies as described
in :doc:`library dependencies </Getting-Started/Library-Dependencies>`.
@ -54,14 +54,14 @@ equivalent in the ``test`` configuration that can be run using a
libraries. To return to sbt, type ``:quit``, Ctrl+D (Unix), or Ctrl+Z
(Windows). Similarly, ``test:console`` starts the interpreter with
the test classes and classpath.
- ``console-quick`` Starts the Scala interpreter with the project's
compile-time dependencies on the classpath. ``test:console-quick``
- ``consoleQuick`` Starts the Scala interpreter with the project's
compile-time dependencies on the classpath. ``test:consoleQuick``
uses the test dependencies. This task differs from ``console`` in
that it does not force compilation of the current project's sources.
- ``console-project`` Enters an interactive session with sbt and the
- ``consoleProject`` Enters an interactive session with sbt and the
build definition on the classpath. The build definition and related
values are bound to variables and common packages and values are
imported. See the :doc:`console-project documentation <Console-Project>` for more information.
imported. See the :doc:`consoleProject documentation <Console-Project>` for more information.
- ``doc`` Generates API documentation for Scala source files in
``src/main/scala`` using scaladoc. ``test:doc`` generates API
documentation for source files in ``src/test/scala``.
@ -70,13 +70,13 @@ equivalent in the ``test`` configuration that can be run using a
``src/main/scala``. ``test:package`` creates a jar containing the
files in ``src/test/resources`` and the class compiled from
``src/test/scala``.
- ``package-doc`` Creates a jar file containing API documentation
- ``packageDoc`` Creates a jar file containing API documentation
generated from Scala source files in ``src/main/scala``.
``test:package-doc`` creates a jar containing API documentation for
``test:packageDoc`` creates a jar containing API documentation for
test sources files in ``src/test/scala``.
- ``package-src``: Creates a jar file containing all main source files
- ``packageSrc``: Creates a jar file containing all main source files
and resources. The packaged paths are relative to ``src/main/scala``
and ``src/main/resources``. Similarly, ``test:package-src`` operates
and ``src/main/resources``. Similarly, ``test:packageSrc`` operates
on test source files and resources.
- ``run <argument>*`` Runs the main class for the project in the same
virtual machine as ``sbt``. The main class is passed the
@ -84,18 +84,18 @@ equivalent in the ``test`` configuration that can be run using a
details on the use of ``System.exit`` and multithreading (including
GUIs) in code run by this action. ``test:run`` runs a main class in
the test code.
- ``run-main <main-class> <argument>*`` Runs the specified main class
- ``runMain <main-class> <argument>*`` Runs the specified main class
for the project in the same virtual machine as ``sbt``. The main
class is passed the ``argument``\ s provided. Please see :doc:`Running-Project-Code`
for details on the use of ``System.exit`` and
multithreading (including GUIs) in code run by this action.
``test:run-main`` runs the specified main class in the test code.
``test:runMain`` runs the specified main class in the test code.
- ``test`` Runs all tests detected during test compilation. See
:doc:`Testing` for details.
- ``test-only <test>*`` Runs the tests provided as arguments. ``*``
- ``testOnly <test>*`` Runs the tests provided as arguments. ``*``
(will be) interpreted as a wildcard in the test name. See :doc:`Testing`
for details.
- ``test-quick <test>*`` Runs the tests specified as arguments (or all
- ``testQuick <test>*`` Runs the tests specified as arguments (or all
tests if no arguments are given) that:
1. have not been run yet OR
@ -130,7 +130,7 @@ General commands
should be on its own line. Empty lines and lines beginning with '#'
are ignored
- ``+ <command>`` Executes the project specified action or method for
all versions of Scala defined in the ``cross-scala-versions``
all versions of Scala defined in the ``crossScalaVersions``
setting.
- ``++ <version> <command>`` Temporarily changes the version of Scala
building the project and executes the provided command. ``<command>``

View File

@ -3,7 +3,7 @@ Compiler Plugin Support
=======================
There is some special support for using compiler plugins. You can set
``auto-compiler-plugins`` to ``true`` to enable this functionality.
``autoCompilerPlugins`` to ``true`` to enable this functionality.
::
@ -18,7 +18,7 @@ for specifying ``plugin`` as the configuration for a dependency:
addCompilerPlugin("org.scala-tools.sxr" %% "sxr" % "0.2.7")
The ``compile`` and ``test-compile`` actions will use any compiler
The ``compile`` and ``testCompile`` actions will use any compiler
plugins found in the ``lib`` directory or in the ``plugin``
configuration. You are responsible for configuring the plugins as
necessary. For example, Scala X-Ray requires the extra option:
@ -26,9 +26,8 @@ necessary. For example, Scala X-Ray requires the extra option:
::
// declare the main Scala source directory as the base directory
scalacOptions <<= (scalacOptions, scalaSource in Compile) { (options, base) =>
options :+ ("-Psxr:base-directory:" + base.getAbsolutePath)
}
scalacOptions :=
scalacOptions.value :+ ("-Psxr:base-directory:" + (scalaSource in Compile).value.getAbsolutePath)
You can still specify compiler plugins manually. For example:
@ -59,8 +58,7 @@ Adding a version-specific compiler plugin can be done as follows:
autoCompilerPlugins := true
libraryDependencies <<= (scalaVersion, libraryDependencies) { (ver, deps) =>
deps :+ compilerPlugin("org.scala-lang.plugins" % "continuations" % ver)
}
libraryDependencies +=
compilerPlugin("org.scala-lang.plugins" % "continuations" % scalaVersion.value)
scalacOptions += "-P:continuations:enable"

View File

@ -5,7 +5,7 @@ Console Project
Description
===========
The ``console-project`` task starts the Scala interpreter with access to
The ``consoleProject`` task starts the Scala interpreter with access to
your project definition and to ``sbt``. Specifically, the interpreter is
started up with these commands already executed:
@ -29,7 +29,7 @@ be included in the standard library in Scala 2.9):
> "grep -r null src" #|| "echo null-free" !
> uri("http://databinder.net/dispatch/About").toURL #> file("About.html") !
``console-project`` can be useful for creating and modifying your build
``consoleProject`` can be useful for creating and modifying your build
in the same way that the Scala interpreter is normally used to explore
writing code. Note that this gives you raw access to your build. Think
about what you pass to ``IO.delete``, for example.
@ -93,8 +93,8 @@ Show the classpaths used for compilation and testing:
> evalTask( fullClasspath in Test, currentState ).files foreach println
Show the remaining commands to be executed in the build (more
interesting if you invoke ``console-project`` like
``; console-project ; clean ; compile``):
interesting if you invoke ``consoleProject`` like
``; consoleProject ; clean ; compile``):
.. code-block:: scala

View File

@ -63,7 +63,7 @@ B. If a file cannot be
C. ``last update`` contains more information about the most recent
resolution and download. The amount of debugging output from Ivy is
high, so you may want to use ``last-grep`` (run ``help last-grep`` for
high, so you may want to use ``lastGrep`` (run ``help lastGrep`` for
usage).
D. Run ``clean`` and then ``update``. If this works, it could

View File

@ -19,8 +19,8 @@ The ``fork`` setting controls whether forking is enabled (true) or not
(false). It can be set in the ``run`` scope to only fork ``run``
commands or in the ``test`` scope to only fork ``test`` commands.
To fork all test tasks (``test``, ``test-only``, and ``test-quick``) and
run tasks (``run``, ``run-main``, ``test:run``, and ``test:run-main``),
To fork all test tasks (``test``, ``testOnly``, and ``testQuick``) and
run tasks (``run``, ``runMain``, ``test:run``, and ``test:runMain``),
::
@ -33,14 +33,14 @@ To enable forking ``run`` tasks only, set ``fork`` to ``true`` in the
fork in run := true
To only fork ``test:run`` and ``test:run-main``:
To only fork ``test:run`` and ``test:runMain``:
::
fork in (Test,run) := true
Similarly, set ``fork in (Compile,run) := true`` to only fork the main
``run`` tasks. ``run`` and ``run-main`` share the same configuration and
``run`` tasks. ``run`` and ``runMain`` share the same configuration and
cannot be configured separately.
To enable forking all ``test`` tasks only, set ``fork`` to ``true`` in
@ -64,13 +64,13 @@ To change the working directory when forked, set
// sets the working directory for all `run`-like tasks
baseDirectory in run := file("/path/to/working/directory/")
// sets the working directory for `run` and `run-main` only
// sets the working directory for `run` and `runMain` only
baseDirectory in (Compile,run) := file("/path/to/working/directory/")
// sets the working directory for `test:run` and `test:run-main` only
// sets the working directory for `test:run` and `test:runMain` only
baseDirectory in (Test,run) := file("/path/to/working/directory/")
// sets the working directory for `test`, `test-quick`, and `test-only`
// sets the working directory for `test`, `testQuick`, and `testOnly`
baseDirectory in test := file("/path/to/working/directory/")
Forked JVM options
@ -99,7 +99,7 @@ or only affect the ``test`` tasks:
Java Home
=========
Select the Java installation to use by setting the ``java-home``
Select the Java installation to use by setting the ``javaHome``
directory:
::
@ -122,7 +122,7 @@ Configuring output
By default, forked output is sent to the Logger, with standard output
logged at the ``Info`` level and standard error at the ``Error`` level.
This can be configured with the ``output-strategy`` setting, which is of
This can be configured with the ``outputStrategy`` setting, which is of
type
`OutputStrategy <../../api/sbt/OutputStrategy.html>`_.

View File

@ -59,7 +59,7 @@ like ``test:run``. Some other examples that require the explicit
.. code-block:: console
> test:console-quick
> test:consoleQuick
> test:console
> test:doc
> test:package
@ -68,8 +68,8 @@ Task-specific Settings
----------------------
Some settings are defined per-task. This is used when there are several
related tasks, such as ``package``, ``package-src``, and
``package-doc``, in the same configuration (such as ``compile`` or
related tasks, such as ``package``, ``packageSrc``, and
``packageDoc``, in the same configuration (such as ``compile`` or
``test``). For package tasks, their settings are the files to package,
the options to use, and the output file to produce. Each package task
should be able to have different values for these settings.
@ -80,16 +80,16 @@ different package tasks.
.. code-block:: console
> package::artifact-path
> package::artifactPath
[info] /home/user/sample/target/scala-2.8.1.final/demo_2.8.1-0.1.jar
> package-src::artifact-path
> packageSrc::artifactPath
[info] /home/user/sample/target/scala-2.8.1.final/demo_2.8.1-0.1-src.jar
> package-doc::artifact-path
> packageDoc::artifactPath
[info] /home/user/sample/target/scala-2.8.1.final/demo_2.8.1-0.1-doc.jar
> test:package::artifact-path
> test:package::artifactPath
[info] /home/user/sample/target/scala-2.8.1.final/root_2.8.1-0.1-test.jar
Note that a single colon ``:`` follows a configuration axis and a double
@ -113,13 +113,13 @@ is defined. For example,
.. code-block:: console
> inspect library-dependencies
> inspect libraryDependencies
[info] Setting: scala.collection.Seq[sbt.ModuleID] = List(org.scalaz:scalaz-core:6.0-SNAPSHOT, org.scala-tools.testing:scalacheck:1.8:test)
[info] Provided by:
[info] {file:/home/user/sample/}root/*:library-dependencies
[info] {file:/home/user/sample/}root/*:libraryDependencies
...
This shows that ``library-dependencies`` has been defined on the current
This shows that ``libraryDependencies`` has been defined on the current
project (``{file:/home/user/sample/}root``) in the global configuration
(``*:``). For a task like ``update``, the output looks like:
@ -168,23 +168,23 @@ As an example, we'll look at ``console``:
> inspect console
...
[info] Dependencies:
[info] compile:console::full-classpath
[info] compile:console::scalac-options
[info] compile:console::initial-commands
[info] compile:console::cleanup-commands
[info] compile:console::fullClasspath
[info] compile:console::scalacOptions
[info] compile:console::initialCommands
[info] compile:console::cleanupCommands
[info] compile:console::compilers
[info] compile:console::task-temporary-directory
[info] compile:console::scala-instance
[info] compile:console::taskTemporary-directory
[info] compile:console::scalaInstance
[info] compile:console::streams
...
This shows the inputs to the ``console`` task. We can see that it gets
its classpath and options from ``full-classpath`` and
``scalac-options(for console)``. The information provided by the
its classpath and options from ``fullClasspath`` and
``scalacOptions(for console)``. The information provided by the
``inspect`` command can thus assist in finding the right setting to
change. The convention for keys, like ``console`` and
``full-classpath``, is that the Scala identifier is camel case, while
``fullClasspath``, is that the Scala identifier is camel case, while
the String representation is lowercase and separated by dashes. The
Scala identifier for a configuration is uppercase to distinguish it from
tasks like ``compile`` and ``test``. For example, we can infer from the
@ -200,12 +200,12 @@ starts up:
...
``inspect`` showed that ``console`` used the setting
``compile:console::initial-commands``. Translating the
``initial-commands`` string to the Scala identifier gives us
``compile:console::initialCommands``. Translating the
``initialCommands`` string to the Scala identifier gives us
``initialCommands``. ``compile`` indicates that this is for the main
sources. ``console::`` indicates that the setting is specific to
``console``. Because of this, we can set the initial commands on the
``console`` task without affecting the ``console-quick`` task, for
``console`` task without affecting the ``consoleQuick`` task, for
example.
Actual Dependencies
@ -224,28 +224,28 @@ Dependencies,
> inspect actual console
...
[info] Dependencies:
[info] compile:scalac-options
[info] compile:full-classpath
[info] *:scala-instance
[info] */*:initial-commands
[info] */*:cleanup-commands
[info] */*:task-temporary-directory
[info] compile:scalacOptions
[info] compile:fullClasspath
[info] *:scalaInstance
[info] */*:initialCommands
[info] */*:cleanupCommands
[info] */*:taskTemporaryDirectory
[info] *:console::compilers
[info] compile:console::streams
...
For ``initial-commands``, we see that it comes from the global scope
For ``initialCommands``, we see that it comes from the global scope
(``*/*:``). Combining this with the relevant output from
``inspect console``:
.. code-block:: console
compile:console::initial-commands
compile:console::initialCommands
we know that we can set ``initial-commands`` as generally as the global
we know that we can set ``initialCommands`` as generally as the global
scope, as specific as the current project's ``console`` task scope, or
anything in between. This means that we can, for example, set
``initial-commands`` for the whole project and will affect ``console``:
``initialCommands`` for the whole project and will affect ``console``:
.. code-block:: console
@ -258,19 +258,19 @@ looking at the reverse dependencies output of ``inspect actual``:
.. code-block:: console
> inspect actual initial-commands
> inspect actual initialCommands
...
[info] Reverse dependencies:
[info] test:console
[info] compile:console-quick
[info] compile:consoleQuick
[info] compile:console
[info] test:console-quick
[info] *:console-project
[info] test:consoleQuick
[info] *:consoleProject
...
We now know that by setting ``initial-commands`` on the whole project,
We now know that by setting ``initialCommands`` on the whole project,
we affect all console tasks in all configurations in that project. If we
didn't want the initial commands to apply for ``console-project``, which
didn't want the initial commands to apply for ``consoleProject``, which
doesn't have our project's classpath available, we could use the more
specific task axis:
@ -299,17 +299,17 @@ As an example, consider the initial commands for ``console`` again:
.. code-block:: console
> inspect console::initial-commands
> inspect console::initialCommands
...
[info] Delegates:
[info] *:console::initial-commands
[info] *:initial-commands
[info] {.}/*:console::initial-commands
[info] {.}/*:initial-commands
[info] */*:console::initial-commands
[info] */*:initial-commands
[info] *:console::initialCommands
[info] *:initialCommands
[info] {.}/*:console::initialCommands
[info] {.}/*:initialCommands
[info] */*:console::initialCommands
[info] */*:initialCommands
...
This means that if there is no value specifically for
``*:console::initial-commands``, the scopes listed under Delegates will
``*:console::initialCommands``, the scopes listed under Delegates will
be searched in order until a defined value is found.

View File

@ -11,10 +11,10 @@ Usage
- ``compile`` will compile the sources under ``src/main/java`` by
default.
- ``test-compile`` will compile the sources under ``src/test/java`` by
- ``testCompile`` will compile the sources under ``src/test/java`` by
default.
Pass options to the Java compiler by setting ``javac-options``:
Pass options to the Java compiler by setting ``javacOptions``:
::
@ -28,7 +28,7 @@ sbt. Multi-element options, such as ``-source 1.5``, are specified like:
javacOptions ++= Seq("-source", "1.5")
You can specify the order in which Scala and Java sources are built with
the ``compile-order`` setting. Possible values are from the
the ``compileOrder`` setting. Possible values are from the
``CompileOrder`` enumeration: ``Mixed``, ``JavaThenScala``, and
``ScalaThenJava``. If you have circular dependencies between Scala and
Java sources, you need the default, ``Mixed``, which passes both Java
@ -68,10 +68,10 @@ unnecessary Scala directories can be ignored by modifying
::
// Include only src/main/java in the compile configuration
unmanagedSourceDirectories in Compile <<= Seq(javaSource in Compile).join
unmanagedSourceDirectories in Compile := (javaSource in Compile).value :: Nil
// Include only src/test/java in the test configuration
unmanagedSourceDirectories in Test <<= Seq(javaSource in Test).join
unmanagedSourceDirectories in Test := (javaSource in Test).value :: Nil
However, there should not be any harm in leaving the Scala directories
if they are empty.

View File

@ -307,7 +307,7 @@ definition would be:
libraryDependencies += "org.scala-sbt" % "launcher-interface" % "0.12.0" % "provided"
resolvers <+= sbtResolver
resolvers += sbtResolver.value
Make the entry point to your class implement 'xsbti.AppMain'. An example
that uses some of the information:
@ -363,7 +363,7 @@ it might look like:
[boot]
directory: ${user.home}/.myapp/boot
Then, ``publish-local`` or ``+publish-local`` the application to make it
Then, ``publishLocal`` or ``+publishLocal`` the application to make it
available.
Running an Application

View File

@ -30,27 +30,28 @@ project definition are required to use this method unless you would like
to change the location of the directory you store the jars in.
To change the directory jars are stored in, change the
``unmanaged-base`` setting in your project definition. For example, to
``unmanagedBase`` setting in your project definition. For example, to
use ``custom_lib/``:
::
unmanagedBase <<= baseDirectory { base => base / "custom_lib" }
unmanagedBase := baseDirectory.value / "custom_lib"
If you want more control and flexibility, override the
``unmanaged-jars`` task, which ultimately provides the manual
``unmanagedJars`` task, which ultimately provides the manual
dependencies to sbt. The default implementation is roughly:
::
unmanagedJars in Compile <<= baseDirectory map { base => (base ** "*.jar").classpath }
unmanagedJars in Compile := (baseDirectory.value ** "*.jar").classpath
If you want to add jars from multiple directories in addition to the
default directory, you can do:
::
unmanagedJars in Compile <++= baseDirectory map { base =>
unmanagedJars in Compile ++= {
val base = baseDirectory.value
val baseDirectories = (base / "libA") +++ (base / "b" / "lib") +++ (base / "libC")
val customJars = (baseDirectories ** "*.jar") +++ (base / "d" / "my.jar")
customJars.classpath
@ -162,8 +163,8 @@ Override default resolvers
``resolvers`` configures additional, inline user resolvers. By default,
``sbt`` combines these resolvers with default repositories (Maven
Central and the local Ivy repository) to form ``external-resolvers``. To
have more control over repositories, set ``external-resolvers``
Central and the local Ivy repository) to form ``externalResolvers``. To
have more control over repositories, set ``externalResolvers``
directly. To only specify repositories in addition to the usual
defaults, configure ``resolvers``.
@ -178,9 +179,8 @@ To use the local repository, but not the Maven Central repository:
::
externalResolvers <<= resolvers map { rs =>
Resolver.withDefaultResolvers(rs, mavenCentral = false)
}
externalResolvers :=
Resolver.withDefaultResolvers(resolvers.value, mavenCentral = false)
Override all resolvers for all builds
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -257,9 +257,9 @@ For multiple classifiers, use multiple ``classifier`` calls:
"org.lwjgl.lwjgl" % "lwjgl-platform" % lwjglVersion classifier "natives-windows" classifier "natives-linux" classifier "natives-osx"
To obtain particular classifiers for all dependencies transitively, run
the ``update-classifiers`` task. By default, this resolves all artifacts
the ``updateClassifiers`` task. By default, this resolves all artifacts
with the ``sources`` or ``javadoc`` classifier. Select the classifiers
to obtain by configuring the ``transitive-classifiers`` setting. For
to obtain by configuring the ``transitiveClassifiers`` setting. For
example, to only retrieve sources:
::
@ -300,8 +300,8 @@ Download Sources
~~~~~~~~~~~~~~~~
Downloading source and API documentation jars is usually handled by an
IDE plugin. These plugins use the ``update-classifiers`` and
``update-sbt-classifiers`` tasks, which produce an :doc:`Update-Report`
IDE plugin. These plugins use the ``updateClassifiers`` and
``updateSbtClassifiers`` tasks, which produce an :doc:`Update-Report`
referencing these jars.
To have sbt download the dependency's sources without using an IDE
@ -333,7 +333,7 @@ To define extra attributes on the current project:
::
projectID <<= projectID { id =>
projectID ~= { id =>
id extra("color" -> "blue", "component" -> "compiler-interface")
}

View File

@ -2,14 +2,14 @@
Local Scala
===========
To use a locally built Scala version, define the ``scala-home`` setting,
To use a locally built Scala version, define the ``scalaHome`` setting,
which is of type ``Option[File]``. This Scala version will only be used
for the build and not for sbt, which will still use the version it was
compiled against.
Example: ``scala scalaHome := Some(file("/path/to/scala"))``
Using a local Scala version will override the ``scala-version`` setting
Using a local Scala version will override the ``scalaVersion`` setting
and will not work with :doc:`cross building <Cross-Build>`.
sbt reuses the class loader for the local Scala version. If you

View File

@ -29,7 +29,7 @@ This configuration is shown in the following build definition:
object MacroBuild extends Build {
lazy val main = Project("main", file(".")) dependsOn(macroSub)
lazy val macroSub = Project("macro", file("macro")) settings(
libraryDependencies <+= scalaVersion("org.scala-lang" % "scala-compiler" % _)
libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value
)
}
@ -119,7 +119,7 @@ For example, the project definitions from above would look like:
lazy val main = Project("main", file(".")) dependsOn(macroSub, commonSub)
lazy val macroSub = Project("macro", file("macro")) dependsOn(commonSub) settings(
libraryDependencies <+= scalaVersion("org.scala-lang" % "scala-compiler" % _)
libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value
)
lazy val commonSub = Project("common", file("common"))

View File

@ -28,7 +28,7 @@ declaration of the tasks would be:
f
}
read <<= write map { f => IO.read(f) }
read := IO.read(write.value)
This establishes an ordering: ``read`` must run after ``write``. We've
also guaranteed that ``read`` will read from the same file that
@ -100,14 +100,18 @@ associates the ``CPU`` and ``Compile`` tags with the ``compile`` task
::
compile <<= myCompileTask tag(Tags.CPU, Tags.Compile)
def myCompileTask = Def.task { ... } tag(Tags.CPU, Tags.Compile)
compile := myCompileTask.value
Different weights may be specified by passing tag/weight pairs to
``tagw``:
::
download <<= downloadImpl.tagw(Tags.Network -> 3)
def downloadImpl = Def.task { ... } tagw(Tags.Network -> 3)
download := downloadImpl.value
Defining Restrictions
~~~~~~~~~~~~~~~~~~~~~
@ -222,7 +226,7 @@ The tasks that are currently tagged by default are:
- ``compile``: ``Compile``, ``CPU``
- ``test``: ``Test``
- ``update``: ``Update``, ``Network``
- ``publish``, ``publish-local``: ``Publish``, ``Network``
- ``publish``, ``publishLocal``: ``Publish``, ``Network``
Of additional note is that the default ``test`` task will propagate its
tags to each child task created for each test class.
@ -231,9 +235,9 @@ The default rules provide the same behavior as previous versions of sbt:
::
concurrentRestrictions in Global <<= parallelExecution { par =>
concurrentRestrictions in Global := {
val max = Runtime.getRuntime.availableProcessors
Tags.limitAll(if(par) max else 1) :: Nil
Tags.limitAll(if(parallelExecution.value) max else 1) :: Nil
}
As before, ``parallelExecution in Test`` controls whether tests are
@ -258,7 +262,9 @@ Then, use this tag as any other tag. For example:
::
aCustomTask <<= aCustomTask.tag(Custom)
def aImpl = Def.task { ... } tag(Custom)
aCustomTask := aImpl.value
concurrentRestrictions in Global +=
Tags.limit(Custom, 1)
@ -278,7 +284,9 @@ tags applied to it. Only the first computation is labeled.
::
compile <<= myCompileTask tag(Tags.CPU, Tags.Compile)
def myCompileTask = Def.task { ... } tag(Tags.CPU, Tags.Compile)
compile := myCompileTask.value
compile ~= { ... do some post processing ... }
@ -305,16 +313,8 @@ Adjustments to Defaults
Rules should be easier to remove or redefine, perhaps by giving them
names. As it is, rules must be appended or all rules must be completely
redefined.
Redefining the tags of a task looks like:
::
compile <<= compile.tag(Tags.Network)
This will overwrite the previous weight if the tag (Network) was already
defined.
redefined. Also, tags can only be defined for tasks at the original
definition site when using the ``:=`` syntax.
For removing tags, an implementation of ``removeTag`` should follow from
the implementation of ``tag`` in a straightforward manner.

View File

@ -53,13 +53,13 @@ to be the "custom\_lib" directory in a project's base directory:
::
unmanagedBase <<= baseDirectory( (base: File) => base /"custom_lib" )
unmanagedBase := baseDirectory.value /"custom_lib"
Or, more concisely:
::
unmanagedBase <<= baseDirectory( _ /"custom_lib" )
unmanagedBase := baseDirectory.value /"custom_lib"
This setting sets the location of the shell history to be in the base
directory of the build, irrespective of the project the setting is
@ -67,7 +67,7 @@ defined in:
::
historyPath <<= (baseDirectory in ThisBuild)(t => Some(t / ".history")),
historyPath := Some( (baseDirectory in ThisBuild).value / ".history"),
Path Finders
------------

View File

@ -7,7 +7,7 @@ Usage
``sbt`` includes a process library to simplify working with external
processes. The library is available without import in build definitions
and at the interpreter started by the :doc:`console-project <Console-Project>` task.
and at the interpreter started by the :doc:`consoleProject <Console-Project>` task.
To run an external command, follow it with an exclamation mark ``!``:

View File

@ -12,7 +12,7 @@ repository. To use publishing, you need to specify the repository to
publish to and the credentials to use. Once these are set up, you can
run ``publish``.
The ``publish-local`` action is used to publish your project to a local
The ``publishLocal`` action is used to publish your project to a local
Ivy repository. You can then use this project from other projects on the
same machine.
@ -48,9 +48,9 @@ repository. Doing this selection can be done by using the value of the
::
publishTo <<= version { (v: String) =>
publishTo := {
val nexus = "https://oss.sonatype.org/"
if (v.trim.endsWith("SNAPSHOT"))
if (version.value.trim.endsWith("SNAPSHOT"))
Some("snapshots" at nexus + "content/repositories/snapshots")
else
Some("releases" at nexus + "service/local/staging/deploy/maven2")
@ -100,10 +100,10 @@ for details.
Modifying the generated POM
---------------------------
When ``publish-maven-style`` is ``true``, a POM is generated by the
``make-pom`` action and published to the repository instead of an Ivy
When ``publishMavenStyle`` is ``true``, a POM is generated by the
``makePom`` action and published to the repository instead of an Ivy
file. This POM file may be altered by changing a few settings. Set
'pom-extra' to provide XML (``scala.xml.NodeSeq``) to insert directly
``pomExtra`` to provide XML (``scala.xml.NodeSeq``) to insert directly
into the generated pom. For example:
::
@ -117,8 +117,8 @@ into the generated pom. For example:
</license>
</licenses>
``make-pom`` adds to the POM any Maven-style repositories you have
declared. You can filter these by modifying ``pom-repository-filter``,
``makePom`` adds to the POM any Maven-style repositories you have
declared. You can filter these by modifying ``pomRepositoryFilter``,
which by default excludes local repositories. To instead only include
local repositories:
@ -128,7 +128,7 @@ local repositories:
repo.root.startsWith("file:")
}
There is also a ``pom-post-process`` setting that can be used to
There is also a ``pomPostProcess`` setting that can be used to
manipulate the final XML before it is written. It's type is
``Node => Node``.
@ -141,7 +141,7 @@ manipulate the final XML before it is written. It's type is
Publishing Locally
------------------
The ``publish-local`` command will publish to the local Ivy repository.
The ``publishLocal`` command will publish to the local Ivy repository.
By default, this is in ``${user.home}/.ivy2/local``. Other projects on
the same machine can then list the project as a dependency. For example,
if the SBT project you are publishing has configuration parameters like:

View File

@ -54,8 +54,7 @@ The first point is like declaring a task dependency, the second is like
two tasks modifying the same state (either project variables or files),
and the third is a consequence of unsynchronized, shared state.
In Scala, we have the built-in functionality to easily fix this:
``lazy val``.
In Scala, we have the built-in functionality to easily fix this: ``lazy val``.
::
@ -83,26 +82,21 @@ The general form of a task definition looks like:
::
myTask <<= (aTask, bTask) map { (a: A, b: B) =>
myTask := {
val a: A = aTask.value
val b: B = bTask.value
... do something with a, b and generate a result ...
}
(This is only intended to be a discussion of the ideas behind tasks, so
see the :doc:`sbt Tasks </Detailed-Topics/Tasks>` page
for details on usage.) Basically, ``myTask`` is defined by declaring
``aTask`` and ``bTask`` as inputs and by defining the function to apply
to the results of these tasks. Here, ``aTask`` is assumed to produce a
for details on usage.) Here, ``aTask`` is assumed to produce a
result of type ``A`` and ``bTask`` is assumed to produce a result of
type ``B``.
Application
-----------
Apply this in practice:
1. Determine the tasks that produce the values you need
2. ``map`` the tasks with the function that implements your task.
As an example, consider generating a zip file containing the binary jar,
source jar, and documentation jar for your project. First, determine
what tasks produce the jars. In this case, the input tasks are
@ -115,8 +109,11 @@ map on the zip task.
::
zip <<= (packageBin in Compile, packageSrc in Compile, packageDoc in Compile, zipPath) map {
(bin: File, src: File, doc: File, out: File) =>
zip := {
val bin: File = (packageBin in Compile).value
val src: File = (packageSrc in Compile).value
val doc: File = (packageDoc in Compile).value
val out: File = zipPath.value
val inputs: Seq[(File,String)] = Seq(bin, src, doc) x Path.flat
IO.zip(inputs, out)
out
@ -131,8 +128,6 @@ the zip file. For example:
::
zipPath <<= target map {
(t: File) =>
t / "out.zip"
}
zipPath :=
target.value / "out.zip"

View File

@ -21,7 +21,6 @@ differences between them:
demand, often in response to a command from the user.
2. At the beginning of project loading, settings and their dependencies
are fixed. Tasks can introduce new tasks during execution, however.
(Tasks have flatMap, but Settings do not.)
Features
========
@ -34,13 +33,11 @@ There are several features of the task system:
:doc:`parser combinators <Parsing-Input>` to define the syntax for their
arguments. This allows flexible syntax and tab-completions in the
same way as :doc:`/Extending/Commands`.
3. Tasks produce values. Other tasks can access a task's value with the
``map`` and ``flatMap`` methods.
4. The ``flatMap`` method allows dynamically changing the structure of
the task graph. Tasks can be injected into the execution graph based
on the result of another task.
5. There are ways to handle task failure, similar to
``try/catch/finally``.
3. Tasks produce values. Other tasks can access a task's value by calling
``value`` on it within a task definition.
4. Dynamically changing the structure of the task graph is possible.
Tasks can be injected into the execution graph based on the result of another task.
5. There are ways to handle task failure, similar to ``try/catch/finally``.
6. Each task has access to its own Logger that by default persists the
logging for that task at a more verbose level than is initially
printed to the screen.
@ -60,8 +57,9 @@ build.sbt
::
val hello = TaskKey[Unit]("hello", "Prints 'Hello World'")
TaskKey[Unit]("hello") := println("hello world!")
hello := println("hello world!")
Hello World example (scala)
---------------------------
@ -101,17 +99,16 @@ see this task listed.
Define the key
--------------
To declare a new task, define a ``TaskKey`` in your
:doc:`Full Configuration </Getting-Started/Full-Def>`:
To declare a new task, define a val of type ``TaskKey``, either in ``.sbt`` or ``.scala`:
::
val sampleTask = TaskKey[Int]("sample-task")
val sampleTask = TaskKey[Int]("sampleTask")
The name of the ``val`` is used when referring to the task in Scala
code. The string passed to the ``TaskKey`` method is used at runtime,
such as at the command line. By convention, the Scala identifier is
camelCase and the runtime identifier uses hyphens. The type parameter
such as at the command line. By convention, both the Scala identifier
and the runtime identifier are camelCase. The type parameter
passed to ``TaskKey`` (here, ``Int``) is the type of value produced by
the task.
@ -119,8 +116,8 @@ We'll define a couple of other of tasks for the examples:
::
val intTask = TaskKey[Int]("int-task")
val stringTask = TaskKey[String]("string-task")
val intTask = TaskKey[Int]("intTask")
val stringTask = TaskKey[String]("stringTask")
The examples themselves are valid entries in a ``build.sbt`` or can be
provided as part of a sequence to ``Project.settings`` (see
@ -134,15 +131,15 @@ defined:
1. Determine the settings and other tasks needed by the task. They are
the task's inputs.
2. Define a function that takes these inputs and produces a value.
2. Define the code that implements the task in terms of these inputs.
3. Determine the scope the task will go in.
These parts are then combined like the parts of a setting are combined.
Tasks without inputs
~~~~~~~~~~~~~~~~~~~~
Defining a basic task
~~~~~~~~~~~~~~~~~~~~~
A task that takes no arguments can be defined using ``:=``
A task is defined using ``:=``
::
@ -157,35 +154,29 @@ A task that takes no arguments can be defined using ``:=``
}
As mentioned in the introduction, a task is evaluated on demand.
Each time ``sample-task`` is invoked, for example, it will print the sum.
If the username changes between runs, ``string-task`` will take different values in those separate runs.
Each time ``sampleTask`` is invoked, for example, it will print the sum.
If the username changes between runs, ``stringTask`` will take different values in those separate runs.
(Within a run, each task is evaluated at most once.)
In contrast, settings are evaluated once on project load and are fixed until the next reload.
Tasks with inputs
~~~~~~~~~~~~~~~~~
Tasks with other tasks or settings as inputs are defined using ``<<=``.
The right hand side will typically call ``map`` or ``flatMap`` on other
settings or tasks. (Contrast this with the ``apply`` method that is used
for settings.) The function argument to ``map`` or ``flatMap`` is the
task body. The following are equivalent ways of defining a task that
adds one to value produced by ``int-task`` and returns the result.
Tasks with other tasks or settings as inputs are also defined using ``:=``.
The values of the inputs are referenced by the ``value`` method. This method
is special syntax and can only be called when defining a task, such as in the
argument to ``:=``. The following defines a task that adds one to the value
produced by ``intTask`` and returns the result.
::
sampleTask <<= intTask map { (count: Int) => count + 1 }
sampleTask := intTask.value + 1
sampleTask <<= intTask map { _ + 1 }
Multiple inputs are handled as with settings. The ``map`` and
``flatMap`` are done on a tuple of inputs:
Multiple settings are handled similarly:
::
stringTask <<= (sampleTask, intTask) map { (sample: Int, intValue: Int) =>
"Sample: " + sample + ", int: " + intValue
}
stringTask := "Sample: " + sampleTask.value + ", int: " + intValue.value
Task Scope
~~~~~~~~~~
@ -193,36 +184,16 @@ Task Scope
As with settings, tasks can be defined in a specific scope. For example,
there are separate ``compile`` tasks for the ``compile`` and ``test``
scopes. The scope of a task is defined the same as for a setting. In the
following example, ``test:sample-task`` uses the result of
``compile:int-task``.
following example, ``test:sampleTask`` uses the result of
``compile:intTask``.
::
sampleTask.in(Test) <<= intTask.in(Compile).map { (intValue: Int) =>
intValue * 3
}
sampleTask.in(Test) :=
intTask.in(Compile).value * 3
// more succinctly:
sampleTask in Test <<= intTask in Compile map { _ * 3 }
Inline task keys
~~~~~~~~~~~~~~~~
Although generally not recommended, it is possible to specify the task
key inline:
::
TaskKey[Int]("sample-task") in Test <<= TaskKey[Int]("int-task") in Compile map { _ * 3 }
The type argument to ``TaskKey`` must be explicitly specified because of
``SI-4653``. It is not recommended because:
1. Tasks are no longer referenced by Scala identifiers (like
``sampleTask``), but by Strings (like ``"sample-task"``)
2. The type information must be repeated.
3. Keys should come with a description, which would need to be repeated
as well.
// with a different punctuation style
sampleTask in Test := (intTask in Compile).value * 3
On precedence
~~~~~~~~~~~~~
@ -243,20 +214,19 @@ the following:
::
(sampleTask in Test) <<= (intTask in Compile map { _ * 3 })
(sampleTask in Test) := ( (intTask in Compile).value * 3 )
Modifying an Existing Task
==========================
The examples in this section use the following key definitions, which
would go in a ``Build`` object in a :doc:`Full Configuration </Getting-Started/Full-Def>`.
Alternatively, the keys may be specified inline, as discussed above.
would go in a ``Build`` object in a ``.scala`` file or directly in a ``.sbt`` file.
::
val unitTask = TaskKey[Unit]("unit-task")
val intTask = TaskKey[Int]("int-task")
val stringTask = TaskKey[String]("string-task")
val unitTask = TaskKey[Unit]("unitTask")
val intTask = TaskKey[Int]("intTask")
val stringTask = TaskKey[String]("stringTask")
The examples themselves are valid settings in a ``build.sbt`` file or as
part of a sequence provided to ``Project.settings``.
@ -270,11 +240,11 @@ input.
intTask := 3
// overriding definition that references the previous definition
intTask <<= intTask map { (value: Int) => value + 1 }
intTask := intTask.value + 1
Completely override a task by not declaring the previous task as an
input. Each of the definitions in the following example completely
overrides the previous one. That is, when ``int-task`` is run, it will
overrides the previous one. That is, when ``intTask`` is run, it will
only print ``#3``.
::
@ -289,9 +259,9 @@ only print ``#3``.
5
}
intTask <<= sampleTask map { (value: Int) =>
intTask := {
println("#3")
value - 3
sampleTask.value - 3
}
To apply a transformation to a single task, without using additional
@ -305,36 +275,63 @@ task's result:
// increment the value returned by intTask
intTask ~= { (x: Int) => x + 1 }
Task Operations
===============
Advanced Task Operations
========================
The previous sections used the ``map`` method to define a task in terms
of the results of other tasks. This is the most common method, but there
are several others. The examples in this section use the task keys
defined in the previous section.
The previous sections demonstrated the most common way to define a task.
Advanced task definitions require the implementation to be separate from the binding.
For example, a basic separate definition looks like:
::
// Define a new, standalone task implemention
val intTaskImpl: Initialize[Task[Int]] = Def.task { sampleTask.value - 3 }
// Bind the implementation to a specific key
intTask := intTaskImpl.value
Note that whenever ``.value`` is used, it must be within a task definition, such as
within ``Def.task`` above or as an argument to ``:=``.
The examples in this section use the task keys defined in the previous section.
Dependencies
------------
To depend on the side effect of some tasks without using their values
and without doing additional work, use ``dependOn`` on a sequence of
tasks. The defining task key (the part on the left side of ``<<=``) must
tasks. The defining task key (the part on the left side of ``:=``) must
be of type ``Unit``, since no value is returned.
::
unitTask <<= Seq(stringTask, sampleTask).dependOn
val unitTaskImpl: Initialize[Task[Unit]] = Seq(stringTask, sampleTask).dependOn
unitTask := unitTaskImpl.value
To add dependencies to an existing task without using their values, call
``dependsOn`` on the task and provide the tasks to depend on. For
example, the second task definition here modifies the original to
require that ``string-task`` and ``sample-task`` run first:
require that ``stringTask`` and ``sampleTask`` run first:
::
intTask := 4
intTask <<= intTask.dependsOn(stringTask, sampleTask)
val intTaskImpl = intTask.dependsOn(stringTask, sampleTask)
intTask := intTaskImpl.value
Note that you can sometimes use the usual syntax:
::
intTask := 4
intTask := {
val ignore = (stringTask.value, sampleTask.value)
intTask.value // use the original result
}
Streams: Per-task logging
-------------------------
@ -345,7 +342,7 @@ the verbosity of stack traces and logging individually for tasks as well
as recalling the last logging for a task. Tasks also have access to
their own persisted binary or text data.
To use Streams, ``map`` or ``flatMap`` the ``streams`` task. This is a
To use Streams, get the value of the ``streams`` task. This is a
special task that provides an instance of
`TaskStreams <../../api/sbt/std/TaskStreams.html>`_
for the defining task. This type provides access to named binary and
@ -356,7 +353,8 @@ method:
::
myTask <<= streams map { (s: TaskStreams) =>
myTask := {
val s: TaskStreams = streams.value
s.log.debug("Saying hi...")
s.log.info("Hello!")
}
@ -373,12 +371,12 @@ To obtain the last logging output from a task, use the ``last`` command:
.. code-block:: console
$ last my-task
$ last myTask
[debug] Saying hi...
[info] Hello!
The verbosity with which logging is persisted is controlled using the
``persist-log-level`` and ``persist-trace-level`` settings. The ``last``
``persistLogLevel`` and ``persistTraceLevel`` settings. The ``last``
command displays what was logged according to these levels. The levels
do not affect already logged information.
@ -400,7 +398,9 @@ For example:
intTask := error("I didn't succeed.")
intTask <<= intTask andFinally { println("andFinally") }
val intTaskImpl = intTask andFinally { println("andFinally") }
intTask := intTaskImpl.value
This modifies the original ``intTask`` to always print "andFinally" even
if the task fails.
@ -414,18 +414,20 @@ a task like in the previous example. For example, consider this code:
intTask := error("I didn't succeed.")
otherIntTask <<= intTask andFinally { println("andFinally") }
val intTaskImpl = intTask andFinally { println("andFinally") }
If ``int-task`` is run directly, ``other-int-task`` is never involved in
otherIntTask := intTaskImpl.value
If ``intTask`` is run directly, ``otherIntTask`` is never involved in
execution. This case is similar to the following plain Scala code:
::
def intTask: Int =
def intTask(): Int =
error("I didn't succeed.")
def otherIntTask: Int =
try { intTask }
def otherIntTask(): Int =
try { intTask() }
finally { println("finally") }
intTask()
@ -451,12 +453,14 @@ For example:
intTask := error("Failed.")
intTask <<= intTask mapFailure { (inc: Incomplete) =>
val intTaskImpl = intTask mapFailure { (inc: Incomplete) =>
println("Ignoring failure: " + inc)
3
}
This overrides the ``int-task`` so that the original exception is printed and the constant ``3`` is returned.
intTask := intTaskImpl.value
This overrides the ``intTask`` so that the original exception is printed and the constant ``3`` is returned.
``mapFailure`` does not prevent other tasks that depend on the target
from failing. Consider the following example:
@ -465,33 +469,37 @@ from failing. Consider the following example:
intTask := if(shouldSucceed) 5 else error("Failed.")
// return 3 if int-task fails. if it succeeds, this task will fail
aTask <<= intTask mapFailure { (inc: Incomplete) => 3 }
// a new task that increments the result of int-task
bTask <<= intTask map { \_ + 1 }
cTask <<= (aTask, bTask) map { (a,b) => a + b }
// return 3 if intTask fails. if it succeeds, this task will fail
val aTaskImpl = intTask mapFailure { (inc: Incomplete) => 3 }
aTask := aTaskImpl.value
// a new task that increments the result of intTask
bTask := intTask.value + 1
cTask := aTask.value + bTask.value
The following table lists the results of each task depending on the initially invoked task:
============== =============== ============= ============== ============== ==============
invoked task int-task result a-task result b-task result c-task result overall result
invoked task intTask result aTask result bTask result cTask result overall result
============== =============== ============= ============== ============== ==============
int-task failure not run not run not run failure
a-task failure success not run not run success
b-task failure not run failure not run failure
c-task failure success failure failure failure
int-task success not run not run not run success
a-task success failure not run not run failure
b-task success not run success not run success
c-task success failure success failure failure
intTask failure not run not run not run failure
aTask failure success not run not run success
bTask failure not run failure not run failure
cTask failure success failure failure failure
intTask success not run not run not run success
aTask success failure not run not run failure
bTask success not run success not run success
cTask success failure success failure failure
============== =============== ============= ============== ============== ==============
The overall result is always the same as the root task (the directly
invoked task). A ``mapFailure`` turns a success into a failure, and a
failure into whatever the result of evaluating the supplied function is.
A ``map`` fails when the input fails and applies the supplied function
A normal task definition fails when the input fails and applies the supplied function
to a successfully completed input.
In the case of more than one input, ``mapFailure`` fails if all inputs
@ -500,14 +508,16 @@ with the list of ``Incomplete``\ s. For example:
::
cTask <<= (aTask, bTask) mapFailure { (incs: Seq[Incomplete]) => 3 }
val cTaskImpl = (aTask, bTask) mapFailure { (incs: Seq[Incomplete]) => 3 }
The following table lists the results of invoking ``c-task``, depending
cTask := cTaskImpl.value
The following table lists the results of invoking ``cTask``, depending
on the success of ``aTask`` and ``bTask``:
============= ============= =============
a-task result b-task result c-task result
aTask result bTask result cTask result
============= ============= =============
failure failure success
failure success success
@ -538,7 +548,7 @@ For example:
intTask := error("Failed.")
intTask <<= intTask mapR {
val intTaskImpl = intTask mapR {
case Inc(inc: Incomplete) =>
println("Ignoring failure: " + inc)
3
@ -547,4 +557,6 @@ For example:
v
}
This overrides the original ``int-task`` definition so that if the original task fails, the exception is printed and the constant ``3`` is returned. If it succeeds, the value is printed and returned.
intTask := intTaskImpl.value
This overrides the original ``intTask`` definition so that if the original task fails, the exception is printed and the constant ``3`` is returned. If it succeeds, the value is printed and returned.

View File

@ -34,33 +34,33 @@ to use your library.
With the library dependency defined, you can then add test sources in
the locations listed above and compile and run tests. The tasks for
running tests are ``test`` and ``test-only``. The ``test`` task accepts
running tests are ``test`` and ``testOnly``. The ``test`` task accepts
no command line arguments and runs all tests:
.. code-block:: console
> test
test-only
testOnly
---------
The ``test-only`` task accepts a whitespace separated list of test names
The ``testOnly`` task accepts a whitespace separated list of test names
to run. For example:
.. code-block:: console
> test-only org.example.MyTest1 org.example.MyTest2
> testOnly org.example.MyTest1 org.example.MyTest2
It supports wildcards as well:
.. code-block:: console
> test-only org.example.*Slow org.example.MyTest1
> testOnly org.example.*Slow org.example.MyTest1
test-quick
testQuick
----------
The ``test-quick`` task, like ``test-only``, allows to filter the tests
The ``testQuick`` task, like ``testOnly``, allows to filter the tests
to run to specific tests or wildcards using the same syntax to indicate
the filters. In addition to the explicit filter, only the tests that
satisfy one of the following conditions are run:
@ -77,7 +77,7 @@ Tab completion is provided for test names based on the results of the
last ``test:compile``. This means that a new sources aren't available
for tab completion until they are compiled and deleted sources won't be
removed from tab completion until a recompile. A new test source can
still be manually written out and run using ``test-only``.
still be manually written out and run using ``testOnly``.
Other tasks
-----------
@ -88,9 +88,9 @@ are referenced in Scala code with ``in Test``. These tasks include:
- ``test:compile``
- ``test:console``
- ``test:console-quick``
- ``test:consoleQuick``
- ``test:run``
- ``test:run-main``
- ``test:runMain``
See :doc:`Running </Getting-Started/Running>` for details on these tasks.
@ -111,11 +111,11 @@ Test Framework Arguments
------------------------
Arguments to the test framework may be provided on the command line to
the ``test-only`` tasks following a ``--`` separator. For example:
the ``testOnly`` tasks following a ``--`` separator. For example:
.. code-block:: console
> test-only org.example.MyTest -- -d -S
> testOnly org.example.MyTest -- -d -S
To specify test framework arguments as part of the build, add options
constructed by ``Tests.Argument``:
@ -196,7 +196,7 @@ available with ``testGrouping`` key. For example:
tests groupBy (_.name(0)) map {
case (letter, tests) => new Group(letter.toString, tests, SubProcess(Seq("-Dfirst.letter"+letter)))
} toSeq;
testGrouping <<= definedTests in Test map groupByFirst
testGrouping := groupByFirst( (definedTests in Test).value )
}
The tests in a single group are run sequentially. Controlling the number
@ -266,7 +266,7 @@ The standard testing tasks are available, but must be prefixed with
.. code-block:: console
> it:test-only org.example.AnIntegrationTest
> it:testOnly org.example.AnIntegrationTest
Similarly the standard settings may be configured for the
``IntegrationTest`` configuration. If not specified directly, most
@ -400,7 +400,7 @@ with the configuration name as before:
.. code-block:: console
> fun:test
> fun:test-only org.example.AFunTest
> fun:testOnly org.example.AFunTest
Application to parallel execution
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -5,16 +5,16 @@ Triggered Execution
You can make a command run when certain files change by prefixing the
command with ``~``. Monitoring is terminated when ``enter`` is pressed.
This triggered execution is configured by the ``watch`` setting, but
typically the basic settings ``watch-sources`` and ``poll-interval`` are
typically the basic settings ``watchSources`` and ``pollInterval`` are
modified.
- ``watch-sources`` defines the files for a single project that are
- ``watchSources`` defines the files for a single project that are
monitored for changes. By default, a project watches resources and
Scala and Java sources.
- ``watch-transitive-sources`` then combines the ``watch-sources`` for
- ``watchTransitiveSources`` then combines the ``watchSources`` for
the current project and all execution and classpath dependencies (see
:doc:`Full Configuration </Getting-Started/Full-Def>` for details on inter-project dependencies).
- ``poll-interval`` selects the interval between polling for changes in
:doc:`Full Configuration </Getting-Started/Full-Def>` for details on interProject dependencies).
- ``pollInterval`` selects the interval between polling for changes in
milliseconds. The default value is ``500 ms``.
Some example usages are described below.
@ -38,11 +38,11 @@ One use is for test driven development, as suggested by Erick on the
mailing list.
The following will poll for changes to your source code (main or test)
and run ``test-only`` for the specified test.
and run ``testOnly`` for the specified test.
.. code-block:: console
> ~ test-only example.TestA
> ~ testOnly example.TestA
Running Multiple Commands
=========================

View File

@ -13,8 +13,8 @@ configuration. Finally, a ``ModuleReport`` lists each successfully
retrieved ``Artifact`` and the ``File`` it was retrieved to as well as
the ``Artifact``\ s that couldn't be downloaded. This missing
``Arifact`` list is never empty for ``update``, which will fail if it is
non-empty. However, it may be non-empty for ``update-classifiers`` and
``update-sbt-classifers``.
non-empty. However, it may be non-empty for ``updateClassifiers`` and
``updateSbtClassifers``.
Filtering a Report and Getting Artifacts
========================================

View File

@ -1,268 +0,0 @@
*Wiki Maintenance Note:* This page has been replaced most recently by :doc:`/Getting-Started/Basic-Def` and :doc:`/Getting-Started/More-About-Settings/`. It has some obsolete terminology:
- we now avoid referring to build definition as "configuration" to
avoid confusion with compile configurations
- we now avoid referring to basic/light/quick vs. full configuration,
in favor of ".sbt build definition files" and ".scala build
definition files"
However, it may still be worth combing this page for examples or points
that are not made in new pages. After doing so, this page could simply
be a redirect (delete the content, link to the new pages about build
definition).
Configuration
=============
A build definition is written in Scala. There are two types of
definitions: light and full. A light definition is a quick way of
configuring a build. It consists of a list of Scala expressions
describing project settings in one or more ".sbt" files located in the
base directory of the project. This also applies to sub-projects.
A full definition is made up of one or more Scala source files that
describe relationships between projects, introduce new configurations
and settings, and define more complex aspects of the build. The
capabilities of a light definition are a proper subset of those of a
full definition.
Light configuration and full configuration can co-exist. Settings
defined in the light configuration are appended to the settings defined
in the full configuration for the corresponding project.
Light Configuration
===================
By Example
----------
Create a file with extension ``.sbt`` in your root project directory
(such as ``<your-project>/build.sbt``). This file contains Scala
expressions of type ``Setting[T]`` that are separated by blank lines.
Built-in settings typically have reasonable defaults (an exception is
``publishTo``). A project typically redefines at least ``name`` and
``version`` and often ``libraryDependencies``. All built-in settings are
listed in
`Keys <../../sxr/Keys.scala.html>`_.
A sample ``build.sbt``:
::
// Set the project name to the string 'My Project'
name := "My Project"
// The := method used in Name and Version is one of two fundamental methods.
// The other method is <<=
// All other initialization methods are implemented in terms of these.
version := "1.0"
// Add a single dependency
libraryDependencies += "junit" % "junit" % "4.8" % "test"
// Add multiple dependencies
libraryDependencies ++= Seq(
"net.databinder" %% "dispatch-google" % "0.7.8",
"net.databinder" %% "dispatch-meetup" % "0.7.8"
)
// Exclude backup files by default. This uses ~=, which accepts a function of
// type T => T (here T = FileFilter) that is applied to the existing value.
// A similar idea is overriding a member and applying a function to the super value:
// override lazy val defaultExcludes = f(super.defaultExcludes)
//
defaultExcludes ~= (filter => filter || "*~")
/* Some equivalent ways of writing this:
defaultExcludes ~= (_ || "*~")
defaultExcludes ~= ( (_: FileFilter) || "*~")
defaultExcludes ~= ( (filter: FileFilter) => filter || "*~")
*/
// Use the project version to determine the repository to publish to.
publishTo <<= version { (v: String) =>
if(v endsWith "-SNAPSHOT")
Some(ScalaToolsSnapshots)
else
Some(ScalaToolsReleases)
}
Notes
-----
- Because everything is parsed as an expression, no semicolons are
allowed at the ends of lines.
- All initialization methods end with ``=`` so that they have the
lowest possible precedence. Except when passing a function literal to
``~=``, you do not need to use parentheses for either side of the
method. Ok:
::
libraryDependencies += "junit" % "junit" % "4.8" % "test"
libraryDependencies.+=("junit" % "junit" % "4.8" % "test")
defaultExcludes ~= (_ || "*~")
defaultExcludes ~= (filter => filter || "*~")
Error:
.. code-block:: console
error: missing parameter type for expanded function ((x$1) => defaultExcludes.colon$tilde(x$1).$bar("*~"))
defaultExcludes ~= _ || "*~"
^
error: value | is not a member of sbt.Project.Setting[sbt.FileFilter]
defaultExcludes ~= _ || "*~"
^
* A block is an expression, with the last statement in the block being the result. For example, the following is an expression:
::
{
val x = 3
def y = 2
x + y
}
An example of using a block to construct a Setting:
::
version := {
// Define a regular expression to match the current branch
val current = """\*\s+(\w+)""".r
// Process the output of 'git branch' to get the current branch
val branch = "git branch --no-color".lines_!.collect { case current(name) => "-" + name }
// Append the current branch to the version.
"1.0" + branch.mkString
}
- Remember that blank lines are used to clearly delineate expressions. This happens before the expression is sent to the Scala compiler, so no blank lines are allowed within a block.
More Information
----------------
- A ``Setting[T]`` describes how to initialize a value of type T. The
expressions shown in the example are expressions, not statements. In
particular, there is no hidden mutable map that is being modified.
Each ``Setting[T]`` describes an update to a map. The actual map is
rarely directly referenced by user code. It is not the final map that
is important, but the operations on the map.
- There are fundamentally two types of initializations, ``:=`` and
``<<=``. The methods ``+=``, ``++=``, and ``~=`` are defined in terms
of these. ``:=`` assigns a value, overwriting any existing value.
``<<=`` uses existing values to initialize a setting.
- ``key ~= f`` is equivalent to ``key <<= key(f)``
- ``key += value`` is equivalent to ``key ~= (_ :+ value)`` or
``key <<= key(_ :+ value)``
- ``key ++= value`` is equivalent to ``key ~= (_ ++ value)`` or
``key <<= key(_ ++ value)``
- There can be multiple ``.sbt`` files per project. This feature can be
used, for example, to put user-specific configurations in a separate
file.
- Import clauses are allowed at the beginning of a ``.sbt`` file. Since
they are clauses, no semicolons are allowed. They need not be
separated by blank lines, but each import must be on one line. For
example,
::
import scala.xml.NodeSeq
import math.{abs, pow}
- These imports are defined by default in a ``.sbt`` file:
::
import sbt._
import Process._
import Keys._
In addition, the contents of all public ``Build`` and ``Plugin``
objects from the full definition are imported.
sbt uses the blank lines to separate the expressions and then it sends
them off to the Scala compiler. Each expression is parsed, compiled, and
loaded independently. The settings are combined into a
``Seq[Setting[_]]`` and passed to the settings engine. The engine groups
the settings by key, preserving order per key though, and then computes
the order in which each setting needs to be evaluated. Cycles and
references to uninitialized settings are detected here and dead settings
are dropped. Finally, the settings are transformed into a function that
is applied to an initially empty map.
Because the expressions can be separated before the compiler, sbt only
needs to recompile expressions that change. So, the work to respond to
changes is proportional to the number of settings that changed and not
the number of settings defined in the build. If imports change, all
expression in the ``.sbt`` file need to be recompiled.
Implementation Details (even more information)
----------------------------------------------
Each expression describes an initialization operation. The simplest
operation is context-free assignment using ``:=``. That is, no outside
information is used to determine the setting value. Operations other
than ``:=`` are implemented in terms of ``<<=``. The ``<<=`` method
specifies an operation that requires other settings to be initialized
and uses their values to define a new setting.
The target (left side value) of a method like ``:=`` identifies one of
the constructs in sbt: settings, tasks, and input tasks. It is not an
actual setting or task, but a key representing a setting or task. A
setting is a value assigned when a project is loaded. A task is a unit
of work that is run on-demand zero or more times after a project is
loaded and also produces a value. An input task, previously known as a
Method Task in 0.7 and earlier, accepts an input string and produces a
task to be run. The renaming is because it can accept arbitrary input in
0.10 and not just a space-delimited sequence of arguments like in 0.7.
A construct (setting, task, or input task) is identified by a scoped
key, which is a pair ``(Scope, AttributeKey[T])``. An ``AttributeKey``
associates a name with a type and is a typesafe key for use in an
``AttributeMap``. Attributes are best illustrated by the ``get`` and
``put`` methods on ``AttributeMap``:
::
def get[T](key: AttributeKey[T]): Option[T]
def put[T](key: AttributeKey[T], value: T): AttributeMap
For example, given a value ``k: AttributeKey[String]`` and a value
``m: AttributeMap``, ``m.get(k)`` has type ``Option[String]``.
In sbt, a Scope is mainly defined by a project reference and a
configuration (such as 'test' or 'compile'). Project data is stored in a
Map[Scope, AttributeMap]. Each Scope identifies a map. You can sort of
compare a Scope to a reference to an object and an AttributeMap to the
object's data.
In order to provide appropriate convenience methods for constructing an
initialization operation for each construct, an AttributeKey is
constructed through either a SettingKey, TaskKey, or InputKey:
::
// underlying key: AttributeKey[String]
val name = SettingKey[String]("name")
// underlying key: AttributeKey[Task[String]]
val hello = TaskKey[String]("hello")
// underlying key: AttributeKey[InputTask[String]]
val helloArgs = InputKey[String]("hello-with-args")
In the basic expression ``name := "asdf"``, the ``:=`` method is
implicitly available for a ``SettingKey`` and accepts an argument that
conforms to the type parameter of name, which is String.
The high-level API for constructing settings is defined in
`Scoped <../../api/sbt/Scoped$.html>`_. Scopes are defined in `Scope <../../api/sbt/Scope$.html>`_.
The underlying engine is in `Settings <../../sxr/Settings.scala.html>`_
and the heterogeneous map is in `Attributes <../../sxr/Attributes.scala.html>`_.
Built-in keys are in `Keys <../../sxr/Keys.scala.html>`_ and
default settings are defined in `Defaults <../../sxr/Defaults.scala.html>`_.

View File

@ -61,9 +61,7 @@ it in your jar by modifying ``resources``. For example:
libraryDependencies += "jquery" % "jquery" % "1.3.2" % "js->default" from "http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js"
resources <<= (resources, update) { (rs, report) =>
rs ++ report.select( configurationFilter("js") )
}
resources ++= update.value.select( configurationFilter("js") )
The ``config`` method defines a new configuration with name ``"js"`` and
makes it private to the project so that it is not used for publishing.

View File

@ -52,7 +52,7 @@ use ``custom_lib/``:
::
unmanagedBase <<= baseDirectory { base => base / "custom_lib" }
unmanagedBase := baseDirectory.value / "custom_lib"
If you want more control and flexibility, override the
``unmanaged-jars`` task, which ultimately provides the manual
@ -60,14 +60,15 @@ dependencies to sbt. The default implementation is roughly:
::
unmanagedJars in Compile <<= baseDirectory map { base => (base ** "*.jar").classpath }
unmanagedJars in Compile := (baseDirectory.value ** "*.jar").classpath
If you want to add jars from multiple directories in addition to the
default directory, you can do:
::
unmanagedJars in Compile <++= baseDirectory map { base =>
unmanagedJars in Compile ++= {
val base = baseDirectory.value
val baseDirectories = (base / "libA") +++ (base / "b" / "lib") +++ (base / "libC")
val customJars = (baseDirectories ** "*.jar") +++ (base / "d" / "my.jar")
customJars.classpath
@ -83,9 +84,8 @@ releases repository:
::
externalResolvers <<= resolvers map { rs =>
Resolver.withDefaultResolvers(rs, mavenCentral = true, scalaTools = false)
}
externalResolvers :=
Resolver.withDefaultResolvers(resolvers.value, mavenCentral = true, scalaTools = false)
Explicit URL
~~~~~~~~~~~~
@ -153,7 +153,7 @@ To define extra attributes on the current project:
::
projectID <<= projectID { id =>
projectID ~= { id =>
id extra("color" -> "blue", "component" -> "compiler-interface")
}

View File

@ -24,10 +24,10 @@ setting is otherwise a normal Scala expression with expected type
scalaVersion := "2.9.0-SNAPSHOT"
// set the main Scala source directory to be <base>/src
scalaSource in Compile <<= baseDirectory(_ / "src")
scalaSource in Compile := baseDirectory.value / "src"
// set the Scala test source directory to be <base>/test
scalaSource in Test <<= baseDirectory(_ / "test")
scalaSource in Test := baseDirectory.value / "test"
// add a test dependency on ScalaCheck
libraryDependencies += "org.scala-tools.testing" %% "scalacheck" % "1.8" % "test"
@ -56,7 +56,7 @@ setting is otherwise a normal Scala expression with expected type
// append -deprecation to the options passed to the Scala compiler
scalacOptions += "-deprecation"
// define the statements initially evaluated when entering 'console', 'console-quick', or 'console-project'
// define the statements initially evaluated when entering 'console', 'consoleQuick', or 'consoleProject'
initialCommands := """
import System.{currentTimeMillis => now}
def time[T](f: => T): T = {
@ -65,7 +65,7 @@ setting is otherwise a normal Scala expression with expected type
}
"""
// set the initial commands when entering 'console' or 'console-quick', but not 'console-project'
// set the initial commands when entering 'console' or 'consoleQuick', but not 'consoleProject'
initialCommands in console := "import myproject._"
// set the main class for packaging the main jar
@ -78,7 +78,7 @@ setting is otherwise a normal Scala expression with expected type
mainClass in (Compile, run) := Some("myproject.MyMain")
// add <base>/input to the files that '~' triggers on
watchSources <+= baseDirectory map { _ / "input" }
watchSources += baseDirectory.value / "input"
// add a maven-style repository
resolvers += "name" at "url"

View File

@ -123,7 +123,7 @@ other parts of the settings interface are defined. Some examples:
// get name of current project
val nameOpt: Option[String] = name in currentRef get structure.data
// get the package options for the `test:package-src` task or Nil if none are defined
// get the package options for the `test:packageSrc` task or Nil if none are defined
val pkgOpts: Seq[PackageOption] = packageOptions in (currentRef, Test, packageSrc) get structure.data getOrElse Nil
`BuildStructure <../../api/sbt/Load$$BuildStructure.html>`_ contains

View File

@ -27,7 +27,7 @@ There are three files in this example:
To try out this example:
1. Put the first two files in a new directory
2. Run ``sbt publish-local`` in that directory
2. Run ``sbt publishLocal`` in that directory
3. Run ``sbt @path/to/hello.build.properties`` to run the application.
Like for sbt itself, you can specify commands from the command line

View File

@ -109,8 +109,8 @@ commands to a project. To try it out:
1. Copy the following build definition into ``project/Build.scala`` for
a new project.
2. Run sbt on the project.
3. Try out the ``hello``, ``hello-all``, ``fail-if-true``, ``color``,
and ``print-state`` commands.
3. Try out the ``hello``, ``helloAll``, ``failIfTrue``, ``color``,
and ``printState`` commands.
4. Use tab-completion and the code below as guidance.
::
@ -139,14 +139,14 @@ commands to a project. To try it out:
// A simple, multiple-argument command that prints "Hi" followed by the arguments.
// Again, it leaves the current state unchanged.
def helloAll = Command.args("hello-all", "<name>") { (state, args) =>
def helloAll = Command.args("helloAll", "<name>") { (state, args) =>
println("Hi " + args.mkString(" "))
state
}
// A command that demonstrates failing or succeeding based on the input
def failIfTrue = Command.single("fail-if-true") {
def failIfTrue = Command.single("failIfTrue") {
case (state, "true") => state.fail
case (state, _) => state
}
@ -168,7 +168,7 @@ commands to a project. To try it out:
// A command that demonstrates getting information out of State.
def printState = Command.command("print-state") { state =>
def printState = Command.command("printState") { state =>
import state._
println(definedCommands.size + " registered commands")
println("commands to run: " + show(remainingCommands))

View File

@ -18,88 +18,95 @@ represents a task. Define a new input task key using the
::
// goes in <base>/project/Build.scala
// goes in <base>/project/Build.scala or in <base>/build.sbt
val demo = InputKey[Unit]("demo")
The definition of an input task is similar to that of a normal task, but it can
also use the result of a `Parser </Detailed-Topics/Parsing-Input>`_ applied to
user input. Just as the special ``value`` method gets the value of a
setting or task, the special ``parsed`` method gets the result of a ``Parser``.
Basic Input Task Definition
===========================
The simplest input task accepts a space-delimited sequence of arguments.
It does not provide useful tab completion and parsing is basic. Such a
task may be defined using the ``inputTask`` method, which accepts a
single function of type ``TaskKey[Seq[String]] => Initialize[Task[O]]``
for some parse result type ``O``. The input to this function is a
``TaskKey`` for a task that will provide the parsed ``Seq[String]``. The
function should return a task that uses that parsed input. For example:
It does not provide useful tab completion and parsing is basic. The built-in
parser for space-delimited arguments is constructed via the ``spaceDelimited``
method, which accepts as its only argument the label to present to the user
during tab completion.
For example, the following task prints the current Scala version and then echoes
the arguments passed to it on their own line.
::
demo <<= inputTask { (argTask: TaskKey[Seq[String]]) =>
// Here, we map the argument task `argTask`
// and a normal setting `scalaVersion`
(argTask, scalaVersion) map { (args: Seq[String], sv: String) =>
println("The current Scala version is " + sv)
println("The arguments to demo were:")
args foreach println
}
demo := {
// get the result of parsing
val args: Seq[String] = spaceDelimited("<arg>").parsed
// Here, we also use the value of the `scalaVersion` setting
println("The current Scala version is " + scalaVersion.value)
println("The arguments to demo were:")
args foreach println
}
Input Task using Parsers
========================
The ``inputTask`` method does not provide any flexibility in defining
the input syntax. To use an arbitrary ``Parser`` described on the
:doc:`/Detailed-Topics/Parsing-Input` page for parsing your input
task's command line, use the more advanced
`InputTask.apply <../../api/sbt/InputTask$.html>`_ factory method. This
method accepts two arguments, which will be described in the following
two sections.
The Parser provided by the ``spaceDelimited`` method does not provide
any flexibility in defining the input syntax. , but using a custom parser
is just a matter of defining your own ``Parser`` as described on the
:doc:`/Detailed-Topics/Parsing-Input` page.
Constructing the Parser
-----------------------
The first step is to construct the actual ``Parser`` by defining a value
of type ``Initialize[State => Parser[I]]`` for some parse result type
``I`` that you decide on. ``Initialize`` is the type that results from
using other settings and the ``State => Parser[I]`` function provides
access to the :doc:`Build-State` when constructing the parser. As an
example, the following defines a contrived ``Parser`` that uses the
project's Scala and sbt version settings as well as the state.
of one of the following types:
* ``Parser[I]``: a basic parser that does not use any settings
* ``Initialize[Parser[I]]``: a parser whose definition depends on one or more settings
* ``Initialize[State => Parser[I]]``: a parser that is defined using both settings and the current :doc:`state <Build-State>`
We already saw an example of the first case with ``spaceDelimited``, which doesn't use any settings in its definition.
As an example of the third case, the following defines a contrived ``Parser`` that uses the
project's Scala and sbt version settings as well as the state. To use these settings, we
need to wrap the Parser construction in ``Def.setting`` and get the setting values with the
special ``value`` method:
::
import complete.DefaultParsers._
val parser: Initialize[State => Parser[(String,String)]] =
(scalaVersion, sbtVersion) { (scalaV: String, sbtV: String) =>
Def.setting {
(state: State) =>
( token("scala" <~ Space) ~ token(scalaV) ) |
( token("sbt" <~ Space) ~ token(sbtV) ) |
( token("scala" <~ Space) ~ token(scalaVersion.value) ) |
( token("sbt" <~ Space) ~ token(sbtVersion.value) ) |
( token("commands" <~ Space) ~
token(state.remainingCommands.size.toString) )
}
}
This Parser definition will produce a value of type ``(String,String)``.
The input syntax isn't very flexible; it is just a demonstration. It
The input syntax defined isn't very flexible; it is just a demonstration. It
will produce one of the following values for a successful parse
(assuming the current Scala version is 2.9.2, the current sbt version is
0.12.0, and there are 3 commands left to run):
(assuming the current Scala version is 2.10.0, the current sbt version is
0.13.0, and there are 3 commands left to run):
.. code-block:: text
("scala", "2.9.2")
("sbt", "0.12.0")
("scala", "2.10.0")
("sbt", "0.13.0")
("commands", "3")
Again, we were able to access the current Scala and sbt version for the project because
they are settings. Tasks cannot be used to define the parser.
Constructing the Task
---------------------
Next, we construct the actual task to execute from the result of the
``Parser``. For this, we construct a value of type
``TaskKey[I] => Initialize[Task[O]]``, where ``I`` is the type returned
by the ``Parser`` we just defined and ``O`` is the type of the ``Task``
we will produce. The ``TaskKey[I]`` provides a task that will provide
the result of parsing.
``Parser``. For this, we define a task as usual, but we can access the
result of parsing via the special ``parsed`` method on ``Parser``.
The following contrived example uses the previous example's output (of
type ``(String,String)``) and the result of the ``package`` task to
@ -107,23 +114,9 @@ print some information to the screen.
::
val taskDef = (parsedTask: TaskKey[(String,String)]) => {
// we are making a task, so use 'map'
(parsedTask, packageBin) map { case ( (tpe: String, value: String), pkg: File) =>
demo := {
val (tpe, value) = parser.parsed
println("Type: " + tpe)
println("Value: " + value)
println("Packaged: " + pkg.getAbsolutePath)
}
println("Packaged: " + packageBin.value.getAbsolutePath)
}
Putting it together
-------------------
To construct the input task, combine the key, the parser, and the task
definition in a setting that goes in ``build.sbt`` or in the
``settings`` member of a ``Project`` in ``project/Build.scala``:
::
demo <<= InputTask(parser)(taskDef)

View File

@ -39,7 +39,7 @@ Where possible, reuse them in your plugin. For instance, don't define:
::
val sourceFiles = SettingKey[Seq[File]]("source-files")
val sourceFiles = SettingKey[Seq[File]]("sourceFiles")
Instead, simply reuse SBT's existing ``sources`` key.
@ -58,7 +58,7 @@ Just use a ``val`` prefix
package sbtobfuscate
object Plugin extends sbt.Plugin {
val obfuscateStylesheet = SettingKey[File]("obfuscate-stylesheet")
val obfuscateStylesheet = SettingKey[File]("obfuscateStylesheet")
}
In this approach, every ``val`` starts with ``obfuscate``. A user of the
@ -66,7 +66,7 @@ plugin would refer to the settings like this:
::
obfuscateStylesheet <<= ...
obfuscateStylesheet := ...
Use a nested object
~~~~~~~~~~~~~~~~~~~
@ -76,7 +76,7 @@ Use a nested object
package sbtobfuscate
object Plugin extends sbt.Plugin {
object ObfuscateKeys {
val stylesheet = SettingKey[File]("obfuscate-stylesheet")
val stylesheet = SettingKey[File]("obfuscateStylesheet")
}
}
@ -87,7 +87,7 @@ of the plugin would refer to the settings like this:
import ObfuscateKeys._ // place this at the top of build.sbt
stylesheet <<= ...
stylesheet := ...
Configuration Advice
--------------------
@ -118,15 +118,15 @@ the same *key*, but they represent distinct *values*. So, in a user's
::
target in PDFPlugin <<= baseDirectory(_ / "mytarget" / "pdf")
target in Compile <<= baseDirectory(_ / "mytarget")
target in PDFPlugin := baseDirectory.value / "mytarget" / "pdf"
target in Compile := baseDirectory.value / "mytarget"
In the PDF plugin, this is achieved with an ``inConfig`` definition:
::
val settings: Seq[sbt.Project.Setting[_]] = inConfig(LWM)(Seq(
target <<= baseDirectory(_ / "target" / "docs") # the default value
target := baseDirectory.value / "target" / "docs" # the default value
))
When *not* to define your own configuration.
@ -139,10 +139,10 @@ task (see below).
::
val akka = config("akka") // This isn't needed.
val akkaStartCluster = TaskKey[Unit]("akka-start-cluster")
val akkaStartCluster = TaskKey[Unit]("akkaStartCluster")
target in akkaStartCluster <<= ... // This is ok.
akkaStartCluster in akka <<= ... // BAD. No need for a Config for plugin-specific task.
target in akkaStartCluster := ... // This is ok.
akkaStartCluster in akka := ... // BAD. No need for a Config for plugin-specific task.
Configuration Cat says "Configuration is for configuration"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -168,8 +168,8 @@ Configurations should *not* be used to namespace keys for a plugin. e.g.
::
val Config = config("my-plugin")
val pluginKey = SettingKey[String]("plugin-specific-key")
val settings = plugin-key in Config // DON'T DO THIS!
val pluginKey = SettingKey[String]("pluginSpecificKey")
val settings = pluginKey in Config // DON'T DO THIS!
Playing nice with configurations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -191,8 +191,8 @@ Split your settings by the configuration axis like so:
val obfuscate = TaskKey[Seq[File]]("obfuscate")
val obfuscateSettings = inConfig(Compile)(baseObfuscateSettings)
val baseObfuscateSettings: Seq[Setting[_]] = Seq(
obfuscate <<= (sources in obfuscate) map { s => ... },
sources in obfuscate <<= (sources).identity
obfuscate := ... (sources in obfuscate).value ...,
sources in obfuscate := sources.value
)
The ``baseObfuscateSettings`` value provides base configuration for the
@ -232,8 +232,8 @@ task itself.
val obfuscate = TaskKey[Seq[File]]("obfuscate")
val obfuscateSettings = inConfig(Compile)(baseObfuscateSettings)
val baseObfuscateSettings: Seq[Setting[_]] = Seq(
obfuscate <<= (sources in obfuscate) map { s => ... },
sources in obfuscate <<= (sources).identity
obfuscate := ... (sources in obfuscate).value ...,
sources in obfuscate := sources.value
)
In the above example, ``sources in obfuscate`` is scoped under the main
@ -245,7 +245,7 @@ Mucking with Global build state
There may be times when you need to muck with global build state. The
general rule is *be careful what you touch*.
First, make sure your user do not include global build configuration in
First, make sure your user does not include global build configuration in
*every* project but rather in the build itself. e.g.
::
@ -266,8 +266,8 @@ removed.
object MyPlugin extends Plugin {
val globalSettigns: Seq[Setting[_]] = Seq(
onLoad in Global <<= onLoad in Global apply (_ andThen { state =>
onLoad in Global := (onLoad in Global).value andThen { state =>
... return new state ...
})
}
)
}

View File

@ -177,7 +177,7 @@ If sbt is running, run ``reload``.
Note that this approach can be useful used when developing a plugin. A
project that uses the plugin will rebuild the plugin on ``reload``. This
saves the intermediate steps of ``publish-local`` and ``clean-plugins``
saves the intermediate steps of ``publishLocal`` and ``cleanPlugins``
required in 0.7. It can also be used to work with the development
version of a plugin from its repository.
@ -269,14 +269,14 @@ An example of a typical plugin:
{
// configuration points, like the built in `version`, `libraryDependencies`, or `compile`
// by implementing Plugin, these are automatically imported in a user's `build.sbt`
val newTask = TaskKey[Unit]("new-task")
val newSetting = SettingKey[String]("new-setting")
val newTask = TaskKey[Unit]("newTask")
val newSetting = SettingKey[String]("newSetting")
// a group of settings ready to be added to a Project
// to automatically add them, do
val newSettings = Seq(
newSetting := "test",
newTask <<= newSetting map { str => println(str) }
newTask := println(newSetting.value)
)
// alternatively, by overriding `settings`, they could be automatically added to a Project
@ -382,7 +382,7 @@ In addition:
3. sbt will rebuild the plugin and use it for the project.
Additionally, the plugin will be available in other projects on
the machine without recompiling again. This approach skips the
overhead of ``publish-local`` and cleaning the plugins directory
overhead of ``publishLocal`` and cleaning the plugins directory
of the project using the plugin.
These are all consequences of ``~/.sbt/plugins/`` being a standard

View File

@ -1,170 +0,0 @@
[Global]: ../../api/sbt/Global$.html
[This]: ../../api/sbt/This$.html
[Select]: ../../api/sbt/Select.html
[main/Structure.scala]: https://github.com/harrah/xsbt/blob/0.12/main/Structure.scala
# Settings Core
This page describes the core settings engine a bit. This may be useful for using it outside of sbt. It may also be useful for understanding how sbt works internally.
The documentation is comprised of two parts. The first part shows an example settings system built on top of the settings engine. The second part comments on how sbt's settings system is built on top of the settings engine. This may help illuminate what exactly the core settings engine provides and what is needed to build something like the sbt settings system.
## Example
### Setting up
To run this example, first create a new project with the following build.sbt file:
```scala
libraryDependencies <+= sbtVersion("org.scala-sbt" %% "collections" % _)
resolvers <+= sbtResolver
```
Then, put the following examples in source files `SettingsExample.scala` and `SettingsUsage.scala`. Finally, run sbt and enter the REPL using `console`. To see the output described below, enter `SettingsUsage`.
### Example Settings System
The first part of the example defines the custom settings system. There are three main parts:
1. Define the Scope type.
2. Define a function that converts that Scope (plus an AttributeKey) to a String.
3. Define a delegation function that defines the sequence of Scopes in which to look up a value.
There is also a fourth, but its usage is likely to be specific to sbt at this time. The example uses a trivial implementation for this part.
`SettingsExample.scala`
```scala
import sbt._
/** Define our settings system */
// A basic scope indexed by an integer.
final case class Scope(index: Int)
// Extend the Init trait.
// (It is done this way because the Scope type parameter is used everywhere in Init.
// Lots of type constructors would become binary, which as you may know requires lots of type lambdas
// when you want a type function with only one parameter.
// That would be a general pain.)
object SettingsExample extends Init[Scope]
{
// Provides a way of showing a Scope+AttributeKey[_]
val showFullKey: Show[ScopedKey[_]] = new Show[ScopedKey[_]] {
def apply(key: ScopedKey[_]) = key.scope.index + "/" + key.key.label
}
// A sample delegation function that delegates to a Scope with a lower index.
val delegates: Scope => Seq[Scope] = { case s @ Scope(index) =>
s +: (if(index <= 0) Nil else delegates(Scope(index-1)) )
}
// Not using this feature in this example.
val scopeLocal: ScopeLocal = _ => Nil
// These three functions + a scope (here, Scope) are sufficient for defining our settings system.
}
```
### Example Usage
This part shows how to use the system we just defined. The end result is a `Settings[Scope]` value. This type is basically a mapping `Scope -> AttributeKey[T] -> Option[T]`. See the [Settings API documentation](../../api/sbt/Settings.html) for details.
`SettingsUsage.scala`
```scala
/** Usage Example **/
import sbt._
import SettingsExample._
import Types._
object SettingsUsage
{
// Define some keys
val a = AttributeKey[Int]("a")
val b = AttributeKey[Int]("b")
// Scope these keys
val a3 = ScopedKey(Scope(3), a)
val a4 = ScopedKey(Scope(4), a)
val a5 = ScopedKey(Scope(5), a)
val b4 = ScopedKey(Scope(4), b)
// Define some settings
val mySettings: Seq[Setting[_]] = Seq(
setting( a3, value( 3 ) ),
setting( b4, app(a4 :^: KNil) { case av :+: HNil => av * 3 } ),
update(a5)(_ + 1)
)
// "compiles" and applies the settings.
// This can be split into multiple steps to access intermediate results if desired.
// The 'inspect' command operates on the output of 'compile', for example.
val applied: Settings[Scope] = make(mySettings)(delegates, scopeLocal, showFullKey)
// Show results.
for(i <- 0 to 5; k <- Seq(a, b)) {
println( k.label + i + " = " + applied.get( Scope(i), k) )
}
```
This produces the following output when run:
```
a0 = None
b0 = None
a1 = None
b1 = None
a2 = None
b2 = None
a3 = Some(3)
b3 = None
a4 = Some(3)
b4 = Some(9)
a5 = Some(4)
b5 = Some(9)
```
* For the None results, we never defined the value and there was no value to delegate to.
* For a3, we explicitly defined it to be 3.
* a4 wasn't defined, so it delegates to a3 according to our delegates function.
* b4 gets the value for a4 (which delegates to a3, so it is 3) and multiplies by 3
* a5 is defined as the previous value of a5 + 1 and
since no previous value of a5 was defined, it delegates to a4, resulting in 3+1=4.
* b5 isn't defined explicitly, so it delegates to b4 and is therefore equal to 9 as well
## sbt Settings Discussion
### Scopes
sbt defines a more complicated scope than the one shown here for the standard usage of settings in a build. This scope has four components: the project axis, the configuration axis, the task axis, and the extra axis. Each component may be [Global] (no specific value), [This] (current context), or [Select] (containing a specific value). sbt resolves This to either [Global] or [Select] depending on the context.
For example, in a project, a [This] project axis becomes a [Select] referring to the defining project. All other axes that are [This] are translated to [Global]. Functions like inConfig and inTask transform This into a [Select] for a specific value. For example, `inConfig(Compile)(someSettings)` translates the configuration axis for all settings in _someSettings_ to be `Select(Compile)` if the axis value is [This].
So, from the example and from sbt's scopes, you can see that the core settings engine does not impose much on the structure of a scope. All it requires is a delegates function `Scope => Seq[Scope]` and a `display` function. You can choose a scope type that makes sense for your situation.
### Constructing settings
The _app_, _value_, _update_, and related methods are the core methods for constructing settings.
This example obviously looks rather different from sbt's interface because these methods are not typically used directly, but are wrapped in a higher-level abstraction.
With the core settings engine, you work with HLists to access other settings. In sbt's higher-level system, there are wrappers around HList for TupleN and FunctionN for N = 1-9 (except Tuple1 isn't actually used). When working with arbitrary arity, it is useful to make these wrappers at the highest level possible. This is because once wrappers are defined, code must be duplicated for every N. By making the wrappers at the top-level, this requires only one level of duplication.
Additionally, sbt uniformly integrates its task engine into the settings system.
The underlying settings engine has no notion of tasks.
This is why sbt uses a `SettingKey` type and a `TaskKey` type.
Methods on an underlying `TaskKey[T]` are basically translated to operating on an underlying `SettingKey[Task[T]]` (and they both wrap an underlying `AttributeKey`).
For example, `a := 3` for a SettingKey _a_ will very roughly translate to `setting(a, value(3))`.
For a TaskKey _a_, it will roughly translate to `setting(a, value( task { 3 } ) )`.
See [main/Structure.scala] for details.
### Settings definitions
sbt also provides a way to define these settings in a file (build.sbt and Build.scala).
This is done for build.sbt using basic parsing and then passing the resulting chunks of code to `compile/Eval.scala`.
For all definitions, sbt manages the classpaths and recompilation process to obtain the settings.
It also provides a way for users to define project, task, and configuration delegation, which ends up being used by the delegates function.

View File

@ -24,9 +24,9 @@ build.sbt file:
::
libraryDependencies <+= sbtVersion("org.scala-sbt" %% "collections" % _)
libraryDependencies += "org.scala-sbt" %% "collections" % sbtVersion.value
resolvers <+= sbtResolver
resolvers += sbtResolver.value
Then, put the following examples in source files
``SettingsExample.scala`` and ``SettingsUsage.scala``. Finally, run sbt

View File

@ -15,10 +15,7 @@ the base directory, and files ending in ``.scala``, located in the
You can use either one exclusively, or use both. A good approach is to
use ``.sbt`` files for most purposes, and use ``.scala`` files only to
contain what can't be done in ``.sbt``:
- to customize sbt (add new settings or tasks)
- to define nested sub-projects
contain what can't be done in ``.sbt``.
This page discusses ``.sbt`` files. See :doc:`.scala build definition <Full-Def>` (later in Getting Started) for
more on ``.scala`` files and how they relate to ``.sbt`` files.
@ -87,11 +84,10 @@ Here's an example:
A ``build.sbt`` file is a list of ``Setting``, separated by blank lines.
Each ``Setting`` is defined with a Scala expression.
The expressions in ``build.sbt`` are independent of one another, and
they are expressions, rather than complete Scala statements. An
implication of this is that you can't define a top-level ``val``,
``object``, class, or method in ``build.sbt``.
they are expressions, rather than complete Scala statements. These
expressions may be interspersed with ``val``s, ``lazy val``s, and ``def``s,
but top-level ``object``s and classes are not allowed in ``build.sbt``.
On the left, ``name``, ``version``, and ``scalaVersion`` are *keys*. A
key is an instance of ``SettingKey[T]``, ``TaskKey[T]``, or
@ -116,8 +112,11 @@ key in sbt's map, giving it the value ``"hello"``.
If you use the wrong value type, the build definition will not compile:
``scala name := 42 // will not compile`` ### Settings are separated by
blank lines
::
name := 42 // will not compile
### Settings are separated by blank lines
You can't write a ``build.sbt`` like this:
@ -225,20 +224,8 @@ If you type the name of a setting key rather than a task key, the value
of the setting key will be displayed. Typing a task key name executes
the task but doesn't display the resulting value; to see a task's
result, use ``show <task name>`` rather than plain ``<task name>``.
In build definition files, keys are named with ``camelCase`` following
Scala convention, but the sbt command line uses
``hyphen-separated-words`` instead. The hyphen-separated string used in
sbt comes from the definition of the key (see
`Keys <../../sxr/Keys.scala.html>`_). For
example, in ``Keys.scala``, there's this key:
::
val scalacOptions = TaskKey[Seq[String]]("scalac-options", "Options for the Scala compiler.")
In sbt you type ``scalac-options`` but in a build definition file you
use ``scalacOptions``.
The convention for keys names is to use ``camelCase`` so that the
command line name and the Scala identifiers are the same.
To learn more about any key, type ``inspect <keyname>`` at the sbt
interactive prompt. Some of the information ``inspect`` displays won't

View File

@ -24,11 +24,11 @@ Some examples from `Keys <../../sxr/Keys.scala.html>`_:
::
val scalaVersion = SettingKey[String]("scala-version", "The version of Scala used for building.")
val scalaVersion = SettingKey[String]("scalaVersion", "The version of Scala used for building.")
val clean = TaskKey[Unit]("clean", "Deletes files produced by the build, such as generated sources, compiled classes, and task caches.")
The key constructors have two string parameters: the name of the key
(``"scala-version"``) and a documentation string
(``"scalaVersion"``) and a documentation string
(``"The version of scala used for building."``).
Remember from :doc:`.sbt build definition <Basic-Def>` that
@ -66,8 +66,8 @@ code with the task key:
sum
}
If the task has dependencies, you'd use ``<<=`` instead of course, as
discussed in :doc:`more about settings <More-About-Settings>`.
If the task has dependencies, you'd reference their value using
`value`, as discussed in :doc:`more about settings <More-About-Settings>`.
The hardest part about implementing tasks is often not sbt-specific;
tasks are just Scala code. The hard part could be writing the "meat" of
@ -78,21 +78,20 @@ and write code based on the HTML library, perhaps).
sbt has some utility libraries and convenience functions, in particular
you can often use the convenient APIs in
`IO <../../api/index.html#sbt.IO$>`_ to
manipulate files and directories.
`IO <../../api/index.html#sbt.IO$>`_ to manipulate files and directories.
Extending but not replacing a task
----------------------------------
If you want to run an existing task while also taking another action,
use ``~=`` or ``<<=`` to take the existing task as input (which will
use ``:=`` or ``~=`` to take the existing task as input (which will
imply running that task), and then do whatever else you like after the
previous implementation completes.
::
// These two settings are equivalent
intTask <<= intTask map { (value: Int) => value + 1 }
intTask := intTask.value + 1
intTask ~= { (value: Int) => value + 1 }
Use plugins!

View File

@ -103,10 +103,10 @@ The following two files illustrate. First, if your project is in
object HelloBuild extends Build {
val sampleKeyA = SettingKey[String]("sample-a", "demo key A")
val sampleKeyB = SettingKey[String]("sample-b", "demo key B")
val sampleKeyC = SettingKey[String]("sample-c", "demo key C")
val sampleKeyD = SettingKey[String]("sample-d", "demo key D")
val sampleKeyA = SettingKey[String]("sampleKeyA", "demo key A")
val sampleKeyB = SettingKey[String]("sampleKeyB", "demo key B")
val sampleKeyC = SettingKey[String]("sampleKeyC", "demo key C")
val sampleKeyD = SettingKey[String]("sampleKeyD", "demo key D")
override lazy val settings = super.settings ++
Seq(sampleKeyA := "A: in Build.settings in Build.scala", resolvers := Seq())
@ -124,22 +124,22 @@ Now, create ``hello/build.sbt`` as follows:
sampleKeyD := "D: in build.sbt"
Start up the sbt interactive prompt. Type ``inspect sample-a`` and you
Start up the sbt interactive prompt. Type ``inspect sampleKeyA`` and you
should see (among other things):
.. code-block:: text
[info] Setting: java.lang.String = A: in Build.settings in Build.scala
[info] Provided by:
[info] {file:/home/hp/checkout/hello/}/*:sample-a
[info] {file:/home/hp/checkout/hello/}/*:sampleKeyA
and then ``inspect sample-c`` and you should see:
and then ``inspect sampleKeyC`` and you should see:
.. code-block:: text
[info] Setting: java.lang.String = C: in build.sbt scoped to ThisBuild
[info] Provided by:
[info] {file:/home/hp/checkout/hello/}/*:sample-c
[info] {file:/home/hp/checkout/hello/}/*:sampleKeyC
Note that the "Provided by" shows the same scope for the two values.
That is, ``sampleKeyC in ThisBuild`` in a ``.sbt`` file is equivalent to
@ -147,30 +147,30 @@ placing a setting in the ``Build.settings`` list in a ``.scala`` file.
sbt takes build-scoped settings from both places to create the build
definition.
Now, ``inspect sample-b``:
Now, ``inspect sampleKeyB``:
.. code-block:: text
[info] Setting: java.lang.String = B: in the root project settings in Build.scala
[info] Provided by:
[info] {file:/home/hp/checkout/hello/}hello/*:sample-b
[info] {file:/home/hp/checkout/hello/}hello/*:sampleKeyB
Note that ``sample-b`` is scoped to the project
Note that ``sampleKeyB`` is scoped to the project
(``{file:/home/hp/checkout/hello/}hello``) rather than the entire build
(``{file:/home/hp/checkout/hello/}``).
As you've probably guessed, ``inspect sample-d`` matches ``sample-b``:
As you've probably guessed, ``inspect sampleKeyD`` matches ``sampleKeyB``:
.. code-block:: text
[info] Setting: java.lang.String = D: in build.sbt
[info] Provided by:
[info] {file:/home/hp/checkout/hello/}hello/*:sample-d
[info] {file:/home/hp/checkout/hello/}hello/*:sampleKeyD
sbt *appends* the settings from ``.sbt`` files to the settings from
``Build.settings`` and ``Project.settings`` which means ``.sbt``
settings take precedence. Try changing ``Build.scala`` so it sets key
``sample-c`` or ``sample-d``, which are also set in ``build.sbt``. The
``sampleC`` or ``sampleD``, which are also set in ``build.sbt``. The
setting in ``build.sbt`` should "win" over the one in ``Build.scala``.
One other thing you may have noticed: ``sampleKeyC`` and ``sampleKeyD``
@ -194,19 +194,13 @@ In summary:
When to use ``.scala`` files
----------------------------
In ``.scala`` files, you are not limited to a series of settings
expressions. You can write any Scala code including ``val``, ``object``,
In ``.scala`` files, you can write any Scala code including ``val``, ``object``,
and method definitions.
*One recommended approach is to define settings in ``.sbt`` files, using
``.scala`` files when you need to factor out a ``val`` or ``object`` or
method definition.*
Because the ``.sbt`` format allows only single expressions, it doesn't
give you a way to share code among expressions. When you need to share
code, you need a ``.scala`` file so you can set common variables or
define methods.
There's one build definition, which is a nested project inside your main
project. ``.sbt`` and ``.scala`` files are compiled together to create
that single definition.

View File

@ -81,7 +81,7 @@ You can force a particular version of sbt by creating a file
.. code-block:: text
sbt.version=0.12.0
sbt.version=0.13.0
sbt is 99% source compatible from release to release.
Still, setting the sbt version in ``project/build.properties`` avoids

View File

@ -35,23 +35,23 @@ filter some entries out, and return a new classpath value. See :doc:`more about
for details of ``~=``.
There's nothing to add to ``build.sbt`` to use unmanaged dependencies,
though you could change the ``unmanaged-base`` key if you'd like to use
though you could change the ``unmanagedBase`` key if you'd like to use
a different directory rather than ``lib``.
To use ``custom_lib`` instead of ``lib``:
::
unmanagedBase <<= baseDirectory { base => base / "custom_lib" }
unmanagedBase := baseDirectory.value / "custom_lib"
``baseDirectory`` is the project's root directory, so here you're
changing ``unmanagedBase`` depending on ``baseDirectory``, using ``<<=``
as explained in :doc:`more about settings <More-About-Settings>`.
changing ``unmanagedBase`` depending on ``baseDirectory`` using the
special ``value`` method as explained in :doc:`more about settings <More-About-Settings>`.
There's also an ``unmanaged-jars`` task which lists the jars from the
``unmanaged-base`` directory. If you wanted to use multiple directories
There's also an ``unmanagedJars`` task which lists the jars from the
``unmanagedBase`` directory. If you wanted to use multiple directories
or do something else complex, you might need to replace the whole
``unmanaged-jars`` task with one that does something else.
``unmanagedJars`` task with one that does something else.
Managed Dependencies
--------------------
@ -114,8 +114,7 @@ once:
groupID % otherID % otherRevision
)
And in rare cases you might find reasons to use ``:=``, ``<<=``,
``<+=``, etc. with ``libraryDependencies`` as well.
In rare cases you might find reasons to use ``:=`` with ``libraryDependencies`` as well.
Getting the right Scala version with ``%%``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -206,10 +205,10 @@ Overriding default resolvers
ones added by your build definition.
``sbt`` combines ``resolvers`` with some default repositories to form
``external-resolvers``.
``externalResolvers``.
Therefore, to change or remove the default resolvers, you would need to
override ``external-resolvers`` instead of ``resolvers``.
override ``externalResolvers`` instead of ``resolvers``.
Per-configuration dependencies
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -225,9 +224,9 @@ If you want a dependency to show up in the classpath only for the
libraryDependencies += "org.apache.derby" % "derby" % "10.4.1.3" % "test"
Now, if you type ``show compile:dependency-classpath`` at the sbt
Now, if you type ``show compile:dependencyClasspath`` at the sbt
interactive prompt, you should not see derby. But if you type
``show test:dependency-classpath``, you should see the derby jar in the
``show test:dependencyClasspath``, you should see the derby jar in the
list.
Typically, test-related dependencies such as

View File

@ -15,8 +15,7 @@ transformation with sbt's earlier map as input and a new map as output.
The new map becomes sbt's new state.
Different settings transform the map in different ways.
:doc:`Earlier <Basic-Def>`, you read about the ``:=``
method.
:doc:`Earlier <Basic-Def>`, you read about the ``:=`` method.
The ``Setting`` which ``:=`` creates puts a fixed, constant value in the
new, transformed map. For example, if you transform a map with the
@ -110,75 +109,44 @@ The function you pass to the ``~=`` method will always have type
``T => T``, if the key has type ``SettingKey[T]`` or ``TaskKey[T]``. The
function transforms the key's value into another value of the same type.
Computing a value based on other keys' values: ``<<=``
------------------------------------------------------
Computing a value based on other keys' values
---------------------------------------------
``~=`` defines a new value in terms of a key's previously-associated
value. But what if you want to define a value in terms of *other* keys'
values?
values? Reference the value of another task or setting by calling ``value``
on the key for the task or setting. The ``value`` method is special and may
only be called in the argument to ``:=``, ``+=``, or ``++=``.
- ``<<=`` lets you compute a new value using the value(s) of arbitrary
other keys.
``<<=`` has one argument, of type ``Initialize[T]``. An
``Initialize[T]`` instance is a computation which takes the values
associated with a set of keys as input, and returns a value of type
``T`` based on those other values. It initializes a value of type ``T``.
Given an ``Initialize[T]``, ``<<=`` returns a ``Setting[T]``, of course
(just like ``:=``, ``+=``, ``~=``, etc.).
Trivial ``Initialize[T]``: depending on one other key with ``<<=``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
All keys extend the ``Initialize`` trait already. So the simplest
``Initialize`` is just a key:
::
// useless but valid
name <<= name
When treated as an ``Initialize[T]``, a ``SettingKey[T]`` computes its
current value. So ``name <<= name`` sets the value of ``name`` to the
value that ``name`` already had.
It gets a little more useful if you set a key to a *different* key. The
keys must have identical value types, though.
As a first example, consider defining the project organization to be the same as the project name.
::
// name our organization after our project (both are SettingKey[String])
organization <<= name
organization := name.value
(Note: this is how you alias one key to another.)
If the value types are not identical, you'll need to convert from
``Initialize[T]`` to another type, like ``Initialize[S]``. This is done
with the ``apply`` method on ``Initialize``, like this:
Or, set the name to the name of the project's directory:
::
// name is a Key[String], baseDirectory is a Key[File]
// name the project after the directory it's inside
name <<= baseDirectory.apply(_.getName)
name := baseDirectory.value.getName
``apply`` is special in Scala and means you can invoke the object with
function syntax; so you could also write this:
This transforms the value of ``baseDirectory`` using the standard ``getName`` method of ``java.io.File``.
Using multiple inputs is similar. For example,
::
name <<= baseDirectory(_.getName)
name := "project " + name.value + " from " + organization.value + " version " + version.value
That transforms the value of ``baseDirectory`` using the function
``_.getName``, where the function ``_.getName`` takes a ``File`` and
returns a ``String``. ``getName`` is a method on the standard
``java.io.File`` object.
This sets the name in terms of its previous value as well as the organization and version settings.
Settings with dependencies
~~~~~~~~~~~~~~~~~~~~~~~~~~
In the setting ``name <<= baseDirectory(_.getName)``, ``name`` will have
In the setting ``name := baseDirectory.value.getName``, ``name`` will have
a *dependency* on ``baseDirectory``. If you place the above in
``build.sbt`` and run the sbt interactive console, then type
``inspect name``, you should see (in part):
@ -186,14 +154,14 @@ a *dependency* on ``baseDirectory``. If you place the above in
.. code-block:: text
[info] Dependencies:
[info] *:base-directory
[info] *:baseDirectory
This is how sbt knows which settings depend on which other settings.
Remember that some settings describe tasks, so this approach also
creates dependencies between tasks.
For example, if you ``inspect compile`` you'll see it depends on another
key ``compile-inputs``, and if you inspect ``compile-inputs`` it in turn
key ``compileInputs``, and if you inspect ``compileInputs`` it in turn
depends on other keys. Keep following the dependency chains and magic
happens. When you type ``compile`` sbt automatically performs an
``update``, for example. It Just Works because the values required as
@ -204,83 +172,11 @@ In this way, all build dependencies in sbt are *automatic* rather than
explicitly declared. If you use a key's value in another computation,
then the computation depends on that key. It just works!
Complex ``Initialize[T]``: depending on multiple keys with ``<<=``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To support dependencies on multiple other keys, sbt adds ``apply`` and
``identity`` methods to tuples of ``Initialize`` objects. In Scala, you
write a tuple like ``(1, "a")`` (that one has type ``(Int, String)``).
So say you have a tuple of three ``Initialize`` objects; its type would
be ``(Initialize[A], Initialize[B], Initialize[C])``. The ``Initialize``
objects could be keys, since all ``SettingKey[T]`` are also instances of
``Initialize[T]``.
Here's a simple example, in this case all three keys are strings:
::
// a tuple of three SettingKey[String], also a tuple of three Initialize[String]
(name, organization, version)
The ``apply`` method on a tuple of ``Initialize`` takes a function as
its argument. Using each ``Initialize`` in the tuple, sbt computes a
corresponding value (the current value of the key). These values are
passed in to the function. The function then returns *one* value, which
is wrapped up in a new ``Initialize``. If you wrote it out with explicit
types (Scala does not require this), it would look like:
::
val tuple: (Initialize[String], Initialize[String], Initialize[String]) = (name, organization, version)
val combined: Initialize[String] = tuple.apply({ (n, o, v) =>
"project " + n + " from " + o + " version " + v })
val setting: Setting[String] = name <<= combined
So each key is already an ``Initialize``; but you can combine up to nine
simple ``Initialize`` (such as keys) into one composite ``Initialize``
by placing them in tuples, and invoking the ``apply`` method.
The ``<<=`` method on ``SettingKey[T]`` is expecting an
``Initialize[T]``, so you can use this technique to create an
``Initialize[T]`` with multiple dependencies on arbitrary keys.
Because function syntax in Scala just calls the ``apply`` method, you
could write the code like this, omitting the explicit ``.apply`` and
just treating ``tuple`` as a function:
::
val tuple: (Initialize[String], Initialize[String], Initialize[String]) = (name, organization, version)
val combined: Initialize[String] = tuple({ (n, o, v) =>
"project " + n + " from " + o + " version " + v })
val setting: Setting[String] = name <<= combined
In a ``build.sbt``, this code using intermediate ``val`` will not work,
since you can only write single expressions in a ``.sbt`` file, not
multiple statements.
You can use a more concise syntax in ``build.sbt``, like this:
::
name <<= (name, organization, version) { (n, o, v) => "project " + n + " from " + o + " version " + v }
Here the tuple of ``Initialize`` (also a tuple of ``SettingKey``) works
as a function, taking the anonymous function delimited by ``{}`` as its
argument, and returning an ``Initialize[T]`` where ``T`` is the result
type of the anonymous function.
Tuples of ``Initialize`` have one other method, ``identity``, which
simply returns an ``Initialize`` with a tuple value.
``(a: Initialize[A], b: Initialize[B]).identity`` would result in a
value of type ``Initialize[(A, B)]``. ``identity`` combines two
``Initialize`` into one, without losing or modifying any of the values.
When settings are undefined
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Whenever a setting uses ``~=`` or ``<<=`` to create a dependency on
Whenever a setting uses ``~=`` or ``:=`` to create a dependency on
itself or another key's value, the value it depends on must exist. If it
does not, sbt will complain. It might say *"Reference to undefined
setting"*, for example. When this happens, be sure you're using the key
@ -294,12 +190,8 @@ Tasks with dependencies
As noted in :doc:`.sbt build definition <Basic-Def>`, task
keys create a ``Setting[Task[T]]`` rather than a ``Setting[T]`` when you
build a setting with ``:=``, ``<<=``, etc. Similarly, task keys are
instances of ``Initialize[Task[T]]`` rather than ``Initialize[T]``, and
``<<=`` on a task key takes an ``Initialize[Task[T]]`` parameter.
The practical importance of this is that you can't have tasks as
dependencies for a non-task setting.
build a setting with ``:=``, etc. Tasks can use settings as inputs, but
settings cannot use tasks as inputs.
Take these two keys (from `Keys <../../sxr/Keys.scala.html>`_):
@ -311,122 +203,35 @@ Take these two keys (from `Keys <../../sxr/Keys.scala.html>`_):
(``scalacOptions`` and ``checksums`` have nothing to do with each other,
they are just two keys with the same value type, where one is a task.)
You cannot compile a ``build.sbt`` that tries to alias one of these to
the other like this:
It is possible to compile a ``build.sbt`` that aliases ``scalacOptions`` to ``checksums``, but not the other way.
For example, this is allowed:
::
// The scalacOptions task may be defined in terms of the checksums setting
scalacOptions := checksums.value
scalacOptions <<= checksums
checksums <<= scalacOptions
The issue is that ``scalacOptions.<<=`` expects an
``Initialize[Task[Seq[String]]]`` and ``checksums.<<=`` expects an
``Initialize[Seq[String]]``. There is, however, a way to convert an
``Initialize[T]`` to an ``Initialize[Task[T]]``, called ``map``:
::
scalacOptions <<= checksums map identity
(``identity`` is a standard Scala function that returns its input as its
result.)
There is no way to go the *other* direction, that is, a setting key
There is no way to go the *other* direction. That is, a setting key
can't depend on a task key. That's because a setting key is only
computed once on project load, so the task would not be re-run every
time, and tasks expect to re-run every time.
A task can depend on both settings and other tasks, though, just use
``map`` rather than ``apply`` to build an ``Initialize[Task[T]]`` rather
than an ``Initialize[T]``. Remember the usage of ``apply`` with a
non-task setting looks like this:
::
name <<= (name, organization, version) { (n, o, v) => "project " + n + " from " + o + " version " + v }
// The checksums setting may not be defined in terms of the scalacOptions task
checksums := scalacOptions.value
(``(name, organization, version)`` has an apply method and is thus a
function, taking the anonymous function in ``{}`` braces as a
parameter.)
To create an ``Initialize[Task[T]]`` you need a ``map`` in there rather
than ``apply``:
::
// this WON'T compile because name (on the left of <<=) is not a task and we used map
name <<= (name, organization, version) map { (n, o, v) => "project " + n + " from " + o + " version " + v }
// this WILL compile because packageBin is a task and we used map
packageBin in Compile <<= (name, organization, version) map { (n, o, v) => file(o + "-" + n + "-" + v + ".jar") }
// this WILL compile because name is not a task and we used apply
name <<= (name, organization, version) { (n, o, v) => "project " + n + " from " + o + " version " + v }
// this WON'T compile because packageBin is a task and we used apply
packageBin in Compile <<= (name, organization, version) { (n, o, v) => file(o + "-" + n + "-" + v + ".jar") }
*Bottom line:* when converting a tuple of keys into an
``Initialize[Task[T]]``, use ``map``; when converting a tuple of keys
into an ``Initialize[T]`` use ``apply``; and you need the
``Initialize[Task[T]]`` if the key on the left side of ``<<=`` is a
``TaskKey[T]`` rather than a ``SettingKey[T]``.
Remember, aliases use ``<<=`` not ``:=``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you want one key to be an alias for another, you might be tempted to
use ``:=`` to create the following nonsense alias:
::
// doesn't work, and not useful
packageBin in Compile := packageDoc in Compile
The problem is that ``:=``'s argument must be a value (or for tasks, a
function returning a value). For ``packageBin`` which is a
``TaskKey[File]``, it must be a ``File`` or a function ``=> File``.
``packageDoc`` is not a ``File``, it's a key.
The proper way to do this is with ``<<=``, which takes a key (really an
``Initialize``, but keys are instances of ``Initialize``):
::
// works, still not useful
packageBin in Compile <<= packageDoc in Compile
Here, ``<<=`` expects an ``Initialize[Task[File]]``, which is a
computation that will return a file later, when sbt runs the task. Which
is what you want: you want to alias a task by making it run another
task, not by setting it one time when sbt loads the project.
(By the way: the ``in Compile`` scope is needed to avoid "undefined"
errors, because the packaging tasks like ``packageBin`` are
per-configuration, not global.)
Appending with dependencies: ``<+=`` and ``<++=``
Appending with dependencies: ``+=`` and ``++=``
-------------------------------------------------
There are a couple more methods for appending to lists, which combine
``+=`` and ``++=`` with ``<<=``. That is, they let you compute a new
list element or new list to concatenate, using dependencies on other
keys in order to do so.
These methods work exactly like ``<<=``, but for ``<++=``, the function
you write to convert the dependencies' values into a new value should
create a ``Seq[T]`` instead of a ``T``.
Unlike ``<<=`` of course, ``<+=`` and ``<++=`` will append to the
previous value of the key on the left, rather than replacing it.
Other keys can be used when appending to an existing setting or task, just like they can for assigning with ``:=``.
For example, say you have a coverage report named after the project, and
you want to add it to the files removed by ``clean``:
::
cleanFiles <+= (name) { n => file("coverage-report-" + n + ".txt") }
cleanFiles += file("coverage-report-" + name.value + ".txt")
Next
----

View File

@ -43,7 +43,7 @@ in quotes. For example,
.. code-block:: console
$ sbt clean compile "test-only TestA TestB"
$ sbt clean compile "testOnly TestA TestB"
In this example, ``test-only`` has arguments, ``TestA`` and ``TestB``.
The commands will be run in sequence (``clean``, ``compile``, then

View File

@ -21,9 +21,9 @@ Some concrete examples:
have a different value in each project.
- the ``compile`` key may have a different value for your main sources
and your test sources, if you want to compile them differently.
- the ``package-options`` key (which contains options for creating jar
- the ``packageOptions`` key (which contains options for creating jar
packages) may have different values when packaging class files
(``package-bin``) or packaging source code (``package-src``).
(``packageBin``) or packaging source code (``packageSrc``).
*There is no single value for a given key name*, because the value may
differ according to scope.
@ -81,21 +81,21 @@ By default, all the keys associated with compiling, packaging, and
running are scoped to a configuration and therefore may work differently
in each configuration. The most obvious examples are the task keys
``compile``, ``package``, and ``run``; but all the keys which *affect*
those keys (such as ``source-directories`` or ``scalac-options`` or
``full-classpath``) are also scoped to the configuration.
those keys (such as ``sourceDirectories`` or ``scalacOptions`` or
``fullClasspath``) are also scoped to the configuration.
Scoping by task axis
~~~~~~~~~~~~~~~~~~~~
Settings can affect how a task works. For example, the ``package-src``
task is affected by the ``package-options`` setting.
Settings can affect how a task works. For example, the ``packageSrc``
task is affected by the ``packageOptions`` setting.
To support this, a task key (such as ``package-src``) can be a scope for
another key (such as ``package-options``).
To support this, a task key (such as ``packageSrc``) can be a scope for
another key (such as ``packageOptions``).
The various tasks that build a package (``package-src``,
``package-bin``, ``package-doc``) can share keys related to packaging,
such as ``artifact-name`` and ``package-options``. Those keys can have
The various tasks that build a package (``packageSrc``,
``packageBin``, ``packageDoc``) can share keys related to packaging,
such as ``artifactName`` and ``packageOptions``. Those keys can have
distinct values for each packaging task.
Global scope
@ -156,73 +156,73 @@ For more details, see :doc:`/Detailed-Topics/Inspecting-Settings`.
Examples of scoped key notation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ``full-classpath``: just a key, so the default scopes are used:
- ``fullClasspath``: just a key, so the default scopes are used:
current project, a key-dependent configuration, and global task
scope.
- ``test:full-classpath``: specifies the configuration, so this is
``full-classpath`` in the ``test`` configuration, with defaults for
- ``test:fullClasspath``: specifies the configuration, so this is
``fullClasspath`` in the ``test`` configuration, with defaults for
the other two scope axes.
- ``*:full-classpath``: specifies ``Global`` for the configuration,
- ``*:fullClasspath``: specifies ``Global`` for the configuration,
rather than the default configuration.
- ``doc::full-classpath``: specifies the ``full-classpath`` key scoped
- ``doc::fullClasspath``: specifies the ``fullClasspath`` key scoped
to the ``doc`` task, with the defaults for the project and
configuration axes.
- ``{file:/home/hp/checkout/hello/}default-aea33a/test:full-classpath``
- ``{file:/home/hp/checkout/hello/}default-aea33a/test:fullClasspath``
specifies a project,
``{file:/home/hp/checkout/hello/}default-aea33a``, where the project
is identified with the build ``{file:/home/hp/checkout/hello/}`` and
then a project id inside that build ``default-aea33a``. Also
specifies configuration ``test``, but leaves the default task axis.
- ``{file:/home/hp/checkout/hello/}/test:full-classpath`` sets the
- ``{file:/home/hp/checkout/hello/}/test:fullClasspath`` sets the
project axis to "entire build" where the build is
``{file:/home/hp/checkout/hello/}``
- ``{.}/test:full-classpath`` sets the project axis to "entire build"
- ``{.}/test:fullClasspath`` sets the project axis to "entire build"
where the build is ``{.}``. ``{.}`` can be written ``ThisBuild`` in
Scala code.
- ``{file:/home/hp/checkout/hello/}/compile:doc::full-classpath`` sets
- ``{file:/home/hp/checkout/hello/}/compile:doc::fullClasspath`` sets
all three scope axes.
Inspecting scopes
-----------------
In sbt's interactive mode, you can use the ``inspect`` command to
understand keys and their scopes. Try ``inspect test:full-classpath``:
understand keys and their scopes. Try ``inspect test:fullClasspath``:
.. code-block:: text
$ sbt
> inspect test:full-classpath
> inspect test:fullClasspath
[info] Task: scala.collection.Seq[sbt.Attributed[java.io.File]]
[info] Description:
[info] The exported classpath, consisting of build products and unmanaged and managed, internal and external dependencies.
[info] Provided by:
[info] {file:/home/hp/checkout/hello/}default-aea33a/test:full-classpath
[info] {file:/home/hp/checkout/hello/}default-aea33a/test:fullClasspath
[info] Dependencies:
[info] test:exported-products
[info] test:dependency-classpath
[info] test:exportedProducts
[info] test:dependencyClasspath
[info] Reverse dependencies:
[info] test:run-main
[info] test:runMain
[info] test:run
[info] test:test-loader
[info] test:testLoader
[info] test:console
[info] Delegates:
[info] test:full-classpath
[info] runtime:full-classpath
[info] compile:full-classpath
[info] *:full-classpath
[info] {.}/test:full-classpath
[info] {.}/runtime:full-classpath
[info] {.}/compile:full-classpath
[info] {.}/*:full-classpath
[info] */test:full-classpath
[info] */runtime:full-classpath
[info] */compile:full-classpath
[info] */*:full-classpath
[info] test:fullClasspath
[info] runtime:fullClasspath
[info] compile:fullClasspath
[info] *:fullClasspath
[info] {.}/test:fullClasspath
[info] {.}/runtime:fullClasspath
[info] {.}/compile:fullClasspath
[info] {.}/*:fullClasspath
[info] */test:fullClasspath
[info] */runtime:fullClasspath
[info] */compile:fullClasspath
[info] */*:fullClasspath
[info] Related:
[info] compile:full-classpath
[info] compile:full-classpath(for doc)
[info] test:full-classpath(for doc)
[info] runtime:full-classpath
[info] compile:fullClasspath
[info] compile:fullClasspath(for doc)
[info] test:fullClasspath(for doc)
[info] runtime:fullClasspath
On the first line, you can see this is a task (as opposed to a setting,
as explained in :doc:`.sbt build definition <Basic-Def>`).
@ -231,8 +231,8 @@ The value resulting from the task will have type
"Provided by" points you to the scoped key that defines the value, in
this case
``{file:/home/hp/checkout/hello/}default-aea33a/test:full-classpath``
(which is the ``full-classpath`` key scoped to the ``test``
``{file:/home/hp/checkout/hello/}default-aea33a/test:fullClasspath``
(which is the ``fullClasspath`` key scoped to the ``test``
configuration and the ``{file:/home/hp/checkout/hello/}default-aea33a``
project).
@ -241,33 +241,33 @@ project).
You can also see the delegates; if the value were not defined, sbt would
search through:
- two other configurations (``runtime:full-classpath``,
``compile:full-classpath``). In these scoped keys, the project is
- two other configurations (``runtime:fullClasspath``,
``compile:fullClasspath``). In these scoped keys, the project is
unspecified meaning "current project" and the task is unspecified
meaning ``Global``
- configuration set to ``Global`` (``*:full-classpath``), since project
- configuration set to ``Global`` (``*:fullClasspath``), since project
is still unspecified it's "current project" and task is still
unspecified so ``Global``
- project set to ``{.}`` or ``ThisBuild`` (meaning the entire build, no
specific project)
- project axis set to ``Global`` (``*/test:full-classpath``) (remember,
- project axis set to ``Global`` (``*/test:fullClasspath``) (remember,
an unspecified project means current, so searching ``Global`` here is
new; i.e. ``*`` and "no project shown" are different for the project
axis; i.e. ``*/test:full-classpath`` is not the same as
``test:full-classpath``)
axis; i.e. ``*/test:fullClasspath`` is not the same as
``test:fullClasspath``)
- both project and configuration set to ``Global``
(``*/*:full-classpath``) (remember that unspecified task means
``Global`` already, so ``*/*:full-classpath`` uses ``Global`` for all
(``*/*:fullClasspath``) (remember that unspecified task means
``Global`` already, so ``*/*:fullClasspath`` uses ``Global`` for all
three axes)
Try ``inspect full-classpath`` (as opposed to the above example,
``inspect test:full-classpath``) to get a sense of the difference.
Try ``inspect fullClasspath`` (as opposed to the above example,
``inspect test:fullClasspath``) to get a sense of the difference.
Because the configuration is omitted, it is autodetected as ``compile``.
``inspect compile:full-classpath`` should therefore look the same as
``inspect full-classpath``.
``inspect compile:fullClasspath`` should therefore look the same as
``inspect fullClasspath``.
Try ``inspect *:full-classpath`` for another contrast.
``full-classpath`` is not defined in the ``Global`` configuration by
Try ``inspect *:fullClasspath`` for another contrast.
``fullClasspath`` is not defined in the ``Global`` configuration by
default.
Again, for more details, see :doc:`/Detailed-Topics/Inspecting-Settings`.
@ -302,7 +302,7 @@ name scoped to the ``Compile`` configuration:
name in Compile := "hello"
or you could set the name scoped to the ``package-bin`` task (pointless!
or you could set the name scoped to the ``packageBin`` task (pointless!
just an example):
::

View File

@ -23,8 +23,7 @@ sbt: The Core Concepts
- your build definition is one big list of ``Setting`` objects, where a
``Setting`` transforms the set of key-value pairs sbt uses to perform
tasks.
- to create a ``Setting``, call one of a few methods on a key (the
``:=`` and ``<<=`` methods are particularly important).
- to create a ``Setting``, call one of a few methods on a key: ``:=``, ``+=``, ``++=``, or ``~=``.
- there is no mutable state, only transformation; for example, a
``Setting`` transforms sbt's collection of key-value pairs into a new
collection. It doesn't change anything in-place.

View File

@ -89,7 +89,7 @@ You could add this in ``hello/build.sbt``:
libraryDependencies += "org.apache.derby" % "derby" % "10.4.1.3" % "test"
If you add that and start up the sbt interactive mode and type
``show dependency-classpath``, you should see the derby jar on your
``show dependencyClasspath``, you should see the derby jar on your
classpath.
To add a plugin, do the same thing but recursed one level. We want the
@ -109,7 +109,7 @@ For example, edit ``hello/project/build.sbt`` and add this line:
libraryDependencies += "net.liftweb" % "lift-json" % "2.0"
Now, at the sbt interactive prompt, ``reload plugins`` to enter the
build definition project, and try ``show dependency-classpath``. You
build definition project, and try ``show dependencyClasspath``. You
should see the lift-json jar on the classpath. This means: you could use
classes from lift-json in your ``Build.scala`` or ``build.sbt`` to
implement a task. You could parse a JSON file and generate other files
@ -130,14 +130,10 @@ which you'll have to clean up.)
::
def addSbtPlugin(dependency: ModuleID): Setting[Seq[ModuleID]] =
libraryDependencies <+= (sbtVersion in update,scalaVersion) { (sbtV, scalaV) =>
sbtPluginExtra(dependency, sbtV, scalaV)
}
libraryDependencies +=
sbtPluginExtra(dependency, (sbtVersion in update).value, scalaVersion.value)
Remember from :doc:`more about settings <More-About-Settings>` that
``<+=`` combines ``<<=`` and ``+=``, so this builds a
value based on other settings, and then appends it to
``libraryDependencies``. The value is based on ``sbtVersion in update``
The appended dependency is based on ``sbtVersion in update``
(sbt's version scoped to the ``update`` task) and ``scalaVersion`` (the
version of scala used to compile the project, in this case used to
compile the build definition). ``sbtPluginExtra`` adds the sbt and Scala

View File

@ -9,28 +9,28 @@ sbt provides standard hooks for adding source or resource generation tasks.
:title: Generate sources
:type: setting
sourceGenerators in Compile <+= <your Task[Seq[File]] here>
sourceGenerators in Compile += <your Task[Seq[File]] here>
A source generation task should generate sources in a subdirectory of ``sourceManaged`` and return a sequence of files generated. The key to add the task to is called ``sourceGenerators``. It should be scoped according to whether the generated files are main (``Compile``) or test (``Test``) sources. This basic structure looks like:
::
sourceGenerators in Compile <+= <your Task[Seq[File]] here>
sourceGenerators in Compile += <your Task[Seq[File]] here>
For example, assuming a method ``def makeSomeSources(base: File): Seq[File]``,
::
sourceGenerators in Compile <+= sourceManaged in Compile map { outDir: File =>
makeSomeSources(outDir / "demo")
}
sourceGenerators in Compile +=
Def.task { makeSomeSources( (sourceManaged in Compile).value / "demo" ) }
As a specific example, the following generates a hello world source file:
::
sourceGenerators in Compile <+= sourceManaged in Compile map { dir =>
val file = dir / "demo" / "Test.scala"
sourceGenerators in Compile += Def.task {
val file = (sourceManaged in Compile).value / "demo" / "Test.scala"
IO.write(file, """object Test extends App { println("Hi") }""")
Seq(file)
}
@ -44,33 +44,31 @@ By default, generated sources are not included in the packaged source artifact.
:title: Generate resources
:type: setting
resourceGenerators in Compile <+= <your Task[Seq[File]] here>
resourceGenerators in Compile += <your Task[Seq[File]] here>
A resource generation task should generate resources in a subdirectory of ``resourceManaged`` and return a sequence of files generated. The key to add the task to is called ``resourceGenerators``. It should be scoped according to whether the generated files are main (``Compile``) or test (``Test``) resources. This basic structure looks like:
::
resourceGenerators in Compile <+= <your Task[Seq[File]] here>
resourceGenerators in Compile += <your Task[Seq[File]] here>
For example, assuming a method ``def makeSomeResources(base: File): Seq[File]``,
::
resourceGenerators in Compile <+= resourceManaged in Compile map { outDir: File =>
makeSomeResources(outDir / "demo")
resourceGenerators in Compile += Def.task {
makeSomeResources( (resourceManaged in Compile).value / "demo")
}
As a specific example, the following generates a properties file containing the application name and version:
::
resourceGenerators in Compile <+=
(resourceManaged in Compile, name, version) map { (dir, n, v) =>
val file = dir / "demo" / "myapp.properties"
val contents = "name=%s\nversion=%s".format(n,v)
resourceGenerators in Compile += {
val file = (resourceManaged in Compile).value / "demo" / "myapp.properties"
val contents = "name=%s\nversion=%s".format(name.value,version.value)
IO.write(file, contents)
Seq(file)
}
}
Change ``Compile`` to ``Test`` to make it a test resource. Normally, you would only want to generate resources when necessary and not every run.

View File

@ -75,15 +75,15 @@ the dependencies of a task/setting as well as the tasks/settings that depend on
> inspect test:compile
...
[info] Dependencies:
[info] test:compile::compile-inputs
[info] test:compile::compileInputs
[info] test:compile::streams
[info] Reverse dependencies:
[info] test:defined-test-names
[info] test:defined-sbt-plugins
[info] test:print-warnings
[info] test:discovered-main-classes
[info] test:defined-tests
[info] test:exported-products
[info] test:definedTestNames
[info] test:definedSbtPlugins
[info] test:printWarnings
[info] test:discoveredMainClasses
[info] test:definedTests
[info] test:exportedProducts
[info] test:products
...
@ -104,13 +104,13 @@ For example,
> inspect tree clean
[info] *:clean = Task[Unit]
[info] +-*:clean-files = List(<project>/lib_managed, <project>/target)
[info] | +-{.}/*:managed-directory = lib_managed
[info] +-*:cleanFiles = List(<project>/lib_managed, <project>/target)
[info] | +-{.}/*:managedDirectory = lib_managed
[info] | +-*:target = target
[info] | +-*:base-directory = <project>
[info] | +-*:this-project = Project(id: demo, base: <project>, ...
[info] | +-*:baseDirectory = <project>
[info] | +-*:thisProject = Project(id: demo, base: <project>, ...
[info] |
[info] +-*:clean-keep-files = List(<project>/target/.history)
[info] +-*:cleanKeepFiles = List(<project>/target/.history)
[info] +-*:history = Some(<project>/target/.history)
...
@ -140,7 +140,7 @@ For example:
.. code-block:: console
> inspect scala-version
> inspect scalaVersion
[info] Setting: java.lang.String = 2.9.2
[info] Description:
[info] The version of Scala used for building.
@ -170,13 +170,13 @@ for testing and API documentation generation.
.. code-block:: console
> inspect scalac-options
> inspect scalacOptions
...
[info] Related:
[info] compile:doc::scalac-options
[info] test:scalac-options
[info] */*:scalac-options
[info] test:doc::scalac-options
[info] compile:doc::scalacOptions
[info] test:scalacOptions
[info] */*:scalacOptions
[info] test:doc::scalacOptions
See the :doc:`/Detailed-Topics/Inspecting-Settings` page for details.
@ -277,11 +277,11 @@ which does not execute a task and thus can only display its type and not its gen
:title: Show the classpath used for compilation or testing
:type: command
show compile:dependency-classpath
show compile:dependencyClasspath
.. code-block:: console
> show compile:dependency-classpath
> show compile:dependencyClasspath
...
[info] ArrayBuffer(Attributed(~/.sbt/0.12.0/boot/scala-2.9.2/lib/scala-library.jar))
@ -289,7 +289,7 @@ For the test classpath,
.. code-block:: console
> show test:dependency-classpath
> show test:dependencyClasspath
...
[info] ArrayBuffer(Attributed(~/code/sbt.github.com/target/scala-2.9.2/classes), Attributed(~/.sbt/0.12.0/boot/scala-2.9.2/lib/scala-library.jar), Attributed(~/.ivy2/cache/junit/junit/jars/junit-4.8.2.jar))
@ -298,15 +298,15 @@ For the test classpath,
:title: Show the main classes detected in a project
:type: command
show compile:discovered-main-classes
show compile:discoveredMainClasses
sbt detects the classes with public, static main methods for use by the ``run`` method and to tab-complete the ``run-main`` method.
The ``discovered-main-classes`` task does this discovery and provides as its result the list of class names.
sbt detects the classes with public, static main methods for use by the ``run`` method and to tab-complete the ``runMain`` method.
The ``discoveredMainClasses`` task does this discovery and provides as its result the list of class names.
For example, the following shows the main classes discovered in the main sources:
.. code-block:: console
> show compile:discovered-main-classes
> show compile:discoveredMainClasses
... <runs compile if out of date> ...
[info] List(org.example.Main)
@ -315,14 +315,14 @@ For example, the following shows the main classes discovered in the main sources
:title: Show the test classes detected in a project
:type: command
show defined-test-names
show definedTestNames
sbt detects tests according to fingerprints provided by test frameworks.
The ``defined-test-names`` task provides as its result the list of test names detected in this way.
The ``definedTestNames`` task provides as its result the list of test names detected in this way.
For example,
.. code-block:: console
> show test:defined-test-names
> show test:definedTestNames
... < runs test:compile if out of date > ...
[info] List(org.example.TestA, org.example.TestB)

View File

@ -9,7 +9,7 @@ By default, sbt's interactive mode is started when no commands are provided on t
:title: Use tab completion
:type: command
test-only <TAB>
testOnly <TAB>
As the name suggests, tab completion is invoked by hitting the tab key.
Suggestions are provided that can complete the text entered to the left of the current cursor position.
@ -33,14 +33,14 @@ To get further completions, hit tab again:
.. code-block:: console
> test<TAB>
test-frameworks test-listeners test-loader test-only test-options test:
testFrameworks testListeners testLoader testOnly testOptions test:
Now, there is more than one possibility for the next character, so sbt prints the available options.
We will select ``test-only`` and get more suggestions by entering the rest of the command and hitting tab twice:
We will select ``testOnly`` and get more suggestions by entering the rest of the command and hitting tab twice:
.. code-block:: console
> test-only<TAB><TAB>
> testOnly<TAB><TAB>
-- sbt.DagSpecification sbt.EmptyRelationTest sbt.KeyTest sbt.RelationTest sbt.SettingsTest
The first tab inserts an unambiguous space and the second suggests names of tests to run.
@ -64,14 +64,14 @@ Some commands have different levels of completion. Hitting tab multiple times i
:title: Show JLine keybindings
:type: commands
> console-quick
> consoleQuick
scala> :keybindings
Both the Scala and sbt command prompts use JLine for interaction. The Scala REPL contains a ``:keybindings`` command to show many of the keybindings used for JLine. For sbt, this can be used by running one of the ``console`` commands (``console``, ``console-quick``, or ``console-project``) and then running ``:keybindings``. For example:
Both the Scala and sbt command prompts use JLine for interaction. The Scala REPL contains a ``:keybindings`` command to show many of the keybindings used for JLine. For sbt, this can be used by running one of the ``console`` commands (``console``, ``consoleQuick``, or ``consoleProject``) and then running ``:keybindings``. For example:
.. code-block:: console
> console-project
> consoleProject
[info] Starting scala interpreter...
...
scala> :keybindings
@ -140,7 +140,7 @@ search history backwards. The following commands are supported:
:title: Change the location of the interactive history file
:type: setting
historyPath <<= baseDirectory(t => Some(t / ".history"))
historyPath := Some( baseDirectory.value / ".history" )
By default, interactive history is stored in the ``target/`` directory for the current project (but is not removed by a ``clean``).
History is thus separate for each subproject.
@ -149,7 +149,7 @@ For example, history can be stored in the root directory for the project instead
::
historyPath <<= baseDirectory(t => Some(t / ".history"))
historyPath := Some(baseDirectory.value / ".history")
The history path needs to be set for each project, since sbt will use the value of ``historyPath`` for the current project (as selected by the ``project`` command).
@ -159,7 +159,7 @@ The history path needs to be set for each project, since sbt will use the value
:title: Use the same history for all projects
:type: setting
historyPath <<= (target in LocalRootProject) { t => Some(t / ".history") }
historyPath := Some( (target in LocalRootProject).value / ".history" )
The previous section describes how to configure the location of the history file.
This setting can be used to share the interactive history among all projects in a build instead of using a different history for each project.
@ -167,10 +167,8 @@ The way this is done is to set ``historyPath`` to be the same file, such as a fi
::
historyPath <<=
(target in LocalRootProject) { t =>
Some(t / ".history")
}
historyPath :=
Some( (target in LocalRootProject).value / ".history")
The ``in LocalRootProject`` part means to get the output directory for the root project for the build.

View File

@ -51,8 +51,8 @@ The details of this execution can be recalled by running ``last``:
[debug] Classpath:
[debug] /tmp/e/target/scala-2.9.2/classes
[debug] /tmp/e/.sbt/0.12.0/boot/scala-2.9.2/lib/scala-library.jar
[debug] Waiting for thread run-main to exit
[debug] Thread run-main exited.
[debug] Waiting for thread runMain to exit
[debug] Thread runMain exited.
[debug] Interrupting remaining threads (should be all daemons).
[debug] Sandboxed run complete..
[debug] Exited with code 0
@ -113,7 +113,7 @@ and:
:title: Show warnings from the previous compilation
:type: command
print-warnings
printWarnings
The Scala compiler does not print the full details of warnings by default.
Compiling code that uses the deprecated ``error`` method from Predef might generate the following output:
@ -126,13 +126,13 @@ Compiling code that uses the deprecated ``error`` method from Predef might gener
[warn] one warning found
The details aren't provided, so it is necessary to add ``-deprecation`` to the options passed to the compiler (``scalacOptions``) and recompile.
An alternative when using Scala 2.10 and later is to run ``print-warnings``.
An alternative when using Scala 2.10 and later is to run ``printWarnings``.
This task will display all warnings from the previous compilation.
For example,
.. code-block:: console
> print-warnings
> printWarnings
[warn] A.scala:2: method error in object Predef is deprecated: Use sys.error(message) instead
[warn] def x = error("Failed.")
[warn] ^
@ -176,9 +176,9 @@ To enable debug logging for all tasks in the current project,
A common scenario is that after running a task, you notice that you need more information than was shown by default.
A ``logLevel`` based solution typically requires changing the logging level and running a task again.
However, there are two cases where this is unnecessary.
First, warnings from a previous compilation may be displayed using ``print-warnings`` for the main sources or ``test:print-warnings`` for test sources.
First, warnings from a previous compilation may be displayed using ``printWarnings`` for the main sources or ``test:printWarnings`` for test sources.
Second, output from the previous execution is available either for a single task or for in its entirety.
See the section on `print-warnings <#printwarnings>`_ and the sections on `previous output <#last>`_.
See the section on `printWarnings <#printwarnings>`_ and the sections on `previous output <#last>`_.
.. howto::
@ -252,10 +252,11 @@ The new function prepends our custom logger to the ones provided by the old func
:title: Log messages in a task
The special task ``streams`` provides per-task logging and I/O via a `Streams <../../api/#sbt.std.Streams>`_ instance.
To log, a task maps the ``streams`` task and uses its ``log`` member:
To log, a task uses the ``log`` member from the ``streams`` task:
::
myTask <<= (..., streams) map { (..., s) =>
s.log.warn("A warning.")
myTask := {
val log = streams.value.log
log.warn("A warning.")
}

View File

@ -68,15 +68,15 @@ The ``artifactName`` setting controls the name of generated packages. See the :
:title: Modify the contents of the package
:type: setting
mappings in (Compile, packageBin) <+=
baseDirectory { dir => ( dir / "example.txt") -> "out/example.txt" }
mappings in (Compile, packageBin) +=
{ ( baseDirectory.value / "example.txt") -> "out/example.txt" }
The contents of a package are defined by the ``mappings`` task, of type ``Seq[(File,String)]``. The ``mappings`` task is a sequence of mappings from a file to include in the package to the path in the package. See :doc:`/Detailed-Topics/Mapping-Files` for convenience functions for generating these mappings. For example, to add the file ``in/example.txt`` to the main binary jar with the path "out/example.txt",
::
mappings in (Compile, packageBin) <+= baseDirectory { base =>
(base / "in" / "example.txt") -> "out/example.txt"
mappings in (Compile, packageBin) += {
(baseDirectory.value / "in" / "example.txt") -> "out/example.txt"
}
Note that ``mappings`` is scoped by the configuration and the specific package task. For example, the mappings for the test source package are defined by the ``mappings in (Test, packageSrc)`` task.

View File

@ -7,7 +7,7 @@
:title: Pass arguments to a command or task in batch mode
:type: batch
clean "test-only org.example.Test" "run-main demo.Main a b c"
clean "testOnly org.example.Test" "runMain demo.Main a b c"
sbt interprets each command line argument provided to it as a command together with the command's arguments.
Therefore, to run a command that takes arguments in batch mode, quote the command and its arguments.

View File

@ -67,13 +67,13 @@ Defining the ``scalaHome`` setting with the path to the Scala home directory wil
See :doc:`cross building </Detailed-Topics/Cross-Build>`.
.. howto::
:id: console-quick
:id: consoleQuick
:title: Enter the Scala REPL with a project's dependencies on the classpath, but not the compiled project classes
:type: command
console-quick
consoleQuick
The ``console-quick`` action retrieves dependencies and puts them on the classpath of the Scala REPL. The project's sources are not compiled, but sources of any source dependencies are compiled. To enter the REPL with test dependencies on the classpath but without compiling test sources, run ``test:console-quick``. This will force compilation of main sources.
The ``consoleQuick`` action retrieves dependencies and puts them on the classpath of the Scala REPL. The project's sources are not compiled, but sources of any source dependencies are compiled. To enter the REPL with test dependencies on the classpath but without compiling test sources, run ``test:consoleQuick``. This will force compilation of main sources.
.. howto::
:id: console
@ -85,17 +85,17 @@ The ``console-quick`` action retrieves dependencies and puts them on the classpa
The ``console`` action retrieves dependencies and compiles sources and puts them on the classpath of the Scala REPL. To enter the REPL with test dependencies and compiled test sources on the classpath, run ``test:console``.
.. howto::
:id: console-project
:id: consoleProject
:title: Enter the Scala REPL with plugins and the build definition on the classpath
:type: command
console-project
consoleProject
.. code-block:: console
> console-project
> consoleProject
For details, see the :doc:`console-project </Detailed-Topics/Console-Project>` page.
For details, see the :doc:`consoleProject </Detailed-Topics/Console-Project>` page.
.. howto::
:id: initial
@ -104,20 +104,20 @@ For details, see the :doc:`console-project </Detailed-Topics/Console-Project>` p
initialCommands in console := """println("Hi!")"""
Set ``initialCommands in console`` to set the initial statements to evaluate when ``console`` and ``console-quick`` are run. To configure ``console-quick`` separately, use ``initialCommands in consoleQuick``.
Set ``initialCommands in console`` to set the initial statements to evaluate when ``console`` and ``consoleQuick`` are run. To configure ``consoleQuick`` separately, use ``initialCommands in consoleQuick``.
For example,
::
initialCommands in console := """println("Hello from console")"""
initialCommands in consoleQuick := """println("Hello from console-quick")"""
initialCommands in consoleQuick := """println("Hello from consoleQuick")"""
The ``console-project`` command is configured separately by ``initialCommands in consoleProject``. It does not use the value from ``initialCommands in console`` by default. For example,
The ``consoleProject`` command is configured separately by ``initialCommands in consoleProject``. It does not use the value from ``initialCommands in console`` by default. For example,
::
initialCommands in consoleProject := """println("Hello from console-project")"""
initialCommands in consoleProject := """println("Hello from consoleProject")"""
.. howto::

View File

@ -9,7 +9,7 @@
~ test
You can make a command run when certain files change by prefixing the command with ``~``. Monitoring is terminated when ``enter`` is pressed. This triggered execution is configured by the ``watch`` setting, but typically the basic settings ``watch-sources`` and ``poll-interval`` are modified as described in later sections.
You can make a command run when certain files change by prefixing the command with ``~``. Monitoring is terminated when ``enter`` is pressed. This triggered execution is configured by the ``watch`` setting, but typically the basic settings ``watchSources`` and ``pollInterval`` are modified as described in later sections.
The original use-case for triggered execution was continuous compilation:
@ -19,11 +19,11 @@ The original use-case for triggered execution was continuous compilation:
> ~ compile
You can use the triggered execution feature to run any command or task, however. The following will poll for changes to your source code (main or test) and run ``test-only`` for the specified test.
You can use the triggered execution feature to run any command or task, however. The following will poll for changes to your source code (main or test) and run ``testOnly`` for the specified test.
::
> ~ test-only example.TestA
> ~ testOnly example.TestA
.. howto::
:id: multi
@ -45,7 +45,7 @@ This runs ``a`` and then ``b`` when sources change.
:title: Configure the sources that are checked for changes
:type: setting
watchSources <+= baseDirectory { _ / "examples.txt" }
watchSources += baseDirectory.value / "examples.txt"
* ``watchSources`` defines the files for a single project that are monitored for changes. By default, a project watches resources and Scala and Java sources.
* ``watchTransitiveSources`` then combines the ``watchSources`` for the current project and all execution and classpath dependencies (see :doc:`/Getting-Started/Full-Def` for details on inter-project dependencies).
@ -54,7 +54,7 @@ To add the file ``demo/example.txt`` to the files to watch,
::
watchSources <+= baseDirectory { _ / "demo" / "examples.txt" }
watchSources += baseDirectory.value / "demo" / "examples.txt"
.. howto::
:id: interval

View File

@ -98,16 +98,13 @@ Settings and Tasks
See the :doc:`Getting Started Guide </Getting-Started/Basic-Def>` for
details.
- ``:=``, ``<<=``, ``+=``, ``++=``, ``~=``, ``<+=``, ``<++=`` These
construct a
`Setting <../api/sbt/Init$Setting.html>`_,
- ``:=``, ``+=``, ``++=``, ``~=`` These
construct a `Setting <../api/sbt/Init$Setting.html>`_,
which is the fundamental type in the :doc:`settings </Getting-Started/Basic-Def>` system.
- ``map`` This defines a task initialization that uses other tasks or
settings. See :doc:`more about settings </Getting-Started/More-About-Settings>`.
It is a common name used for many other types in Scala, such as collections.
- ``apply`` This defines a setting initialization using other settings.
It is not typically written out. See :doc:`more about settings </Getting-Started/More-About-Settings>`.
This is a common name in Scala.
- ``value`` This uses the value of another setting or task in the definition of a new setting or task.
This method is special (it is a macro) and cannot be used except in the argument of one of the setting
definition methods above (``:=``, ...) or in the standalone construction methods ``Def.setting`` and ``Def.task``.
See :doc:`more about settings </Getting-Started/More-About-Settings>` for details.
- ``in`` specifies the `Scope <../api/sbt/Scope.html>`_ or part of the
`Scope <../api/sbt/Scope.html>`_ of a setting being referenced. See :doc:`scopes </Getting-Started/Scopes>`.

View File

@ -88,8 +88,8 @@ The following commands work pretty much as in 0.7 out of the box:
update
compile
test
test-only
publish-local
testOnly
publishLocal
exit
Why have the resolved dependencies in a multi-module project changed since 0.7?
@ -233,7 +233,7 @@ You may run ``sbt console``.
Build definitions
-----------------
What are the ``:=``, ``~=``, ``<<=``, ``+=``, ``++=``, ``<+=``, and ``<++=`` methods?
What are the ``:=``, ``+=``, ``++=```, and ``~=`` methods?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
These are methods on keys used to construct a ``Setting``. The Getting
@ -256,34 +256,6 @@ Also try the :doc:`index </Name-Index>` of commonly used methods, values, and ty
the `API Documentation <../api/index>`_ and the
`hyperlinked sources <../sxr/index>`_.
How can one key depend on multiple other keys?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
See :doc:`More About Settings </Getting-Started/More-About-Settings/>` in the
Getting Started Guide, scroll down to the discussion of ``<<=`` with
multiple keys.
Briefly: You need to use a tuple rather than a single key by itself.
Scala's syntax for a tuple is with parentheses, like ``(a, b, c)``.
If you're creating a value for a task key, then you'll use ``map``:
::
packageBin in Compile <<= (name, organization, version) map { (n, o, v) => file(o + "-" + n + "-" + v + ".jar") }
If you're creating a value for a setting key, then you'll use ``apply``:
::
name <<= (name, organization, version) apply { (n, o, v) => "project " + n + " from " + o + " version " + v }
Typing ``apply`` is optional in that code, since Scala treats any object
with an ``apply`` method as a function. See :doc:`More About Settings </Getting-Started/More-About-Settings>`
for a longer explanation.
To learn about task keys vs. setting keys, read :doc:`.sbt build definition </Getting-Started/Basic-Def>`.
How do I add files to a jar package?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -326,15 +298,15 @@ basic structure looks like:
::
sourceGenerators in Compile <+= <your Task[Seq[File]] here>
sourceGenerators in Compile += <your Task[Seq[File]] here>
For example, assuming a method
``def makeSomeSources(base: File): Seq[File]``,
::
sourceGenerators in Compile <+= sourceManaged in Compile map { outDir: File =>
makeSomeSources(outDir / "demo")
sourceGenerators in Compile += Def.task {
makeSomeSources( (sourceManaged in Compile).value / "demo")
}
As a specific example, the following generates a hello world source
@ -342,8 +314,8 @@ file:
::
sourceGenerators in Compile <+= sourceManaged in Compile map { dir =>
val file = dir / "demo" / "Test.scala"
sourceGenerators in Compile += Def.task {
val file = (sourceManaged in Compile) / "demo" / "Test.scala"
IO.write(file, """object Test extends App { println("Hi") }""")
Seq(file)
}
@ -374,16 +346,15 @@ is:
// define a task that takes some inputs
// and generates files in an output directory
myTask <<= (cacheDirectory, inputs, target) map {
(cache: File, inFiles: Seq[File], outDir: File) =>
myTask := {
// wraps a function taskImpl in an uptodate check
// taskImpl takes the input files, the output directory,
// generates the output files and returns the set of generated files
val cachedFun = FileFunction.cached(cache / "my-task") { (in: Set[File]) =>
taskImpl(in, outDir) : Set[File]
val cachedFun = FileFunction.cached(cacheDirectory.value / "my-task") { (in: Set[File]) =>
taskImpl(in, target.value) : Set[File]
}
// Applies the cached function to the inputs files
cachedFun(inFiles)
cachedFun(inputs.value)
}
There are two additional arguments for the first parameter list that
@ -435,50 +406,16 @@ to ``samples``:
::
samples:run
samples:run-main
samples:runMain
samples:compile
samples:console
samples:console-quick
samples:scalac-options
samples:full-classpath
samples:consoleQuick
samples:scalacOptions
samples:fullClasspath
samples:package
samples:package-src
samples:packageSrc
...
Example of adding a new configuration
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
``project/Sample.scala``
::
import sbt._
import Keys._
object Sample extends Build {
// defines a new configuration "samples" that will delegate to "compile"
lazy val Samples = config("samples") extend(Compile)
// defines the project to have the "samples" configuration
lazy val p = Project("p", file("."))
.configs(Samples)
.settings(sampleSettings : _*)
def sampleSettings =
// adds the default compile/run/... tasks in "samples"
inConfig(Samples)(Defaults.configSettings) ++
Seq(
// (optional) makes "test:compile" depend on "samples:compile"
compile in Test <<= compile in Test dependsOn (compile in Samples)
) ++
// (optional) declare that the samples binary and
// source jars should be published
publishArtifact(packageBin) ++
publishArtifact(packageSrc)
def publishArtifact(task: TaskKey[File]): Seq[Setting[_]] =
addArtifact(artifact in (Samples, task), task in Samples).settings
}
How do I add a test configuration?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -498,7 +435,7 @@ A basic run task is created by:
::
// this lazy val has to go in a full configuration
lazy val myRunTask = TaskKey[Unit]("my-run-task")
lazy val myRunTask = TaskKey[Unit]("myRunTask")
// this can go either in a `build.sbt` or the settings member
// of a Project in a full configuration
@ -509,7 +446,7 @@ file):
::
fullRunTask(TaskKey[Unit]("my-run-task"), Test, "foo.Foo", "arg1", "arg2")
fullRunTask(TaskKey[Unit]("myRunTask"), Test, "foo.Foo", "arg1", "arg2")
If you want to be able to supply arguments on the command line, replace
``TaskKey`` with ``InputKey`` and ``fullRunTask`` with
@ -537,10 +474,10 @@ delegate to ``aRun``
::
val aRun = TaskKey[Unit]("a-run", "A run task.")
val aRun = TaskKey[Unit]("aRun", "A run task.")
// The last parameter to TaskKey.apply here is a repeated one
val myRun = TaskKey[Unit]("my-run", "Custom run task.", aRun)
val myRun = TaskKey[Unit]("myRun", "Custom run task.", aRun)
In use, this looks like:
@ -593,16 +530,16 @@ the following are settings that implement #2-#4:
"net.sf.proguard" % "proguard" % "4.4" % ProguardConfig.name
// Extract the dependencies from the UpdateReport.
managedClasspath in proguard <<=
(classpathTypes in proguard, update) map { (ct, report) =>
Classpaths.managedJars(proguardConfig, ct, report)
}
managedClasspath in proguard :=
Classpaths.managedJars(proguardConfig, (classpathTypes in proguard).value, update.value)
}
// Use the dependencies in a task, typically by putting them
// in a ClassLoader and reflectively calling an appropriate
// method.
proguard <<= managedClasspath in proguard { (cp: Seq[File] =>
// ... do something with 'cp', which includes proguard ...
proguard := {
val cp: Seq[File] = (managedClasspath in proguard).value
// ... do something with , which includes proguard ...
}
How would I change sbt's classpath dynamically?
@ -684,7 +621,7 @@ has been loaded and prints that number:
{
// the key for the current count
val key = AttributeKey[Int]("load-count")
val key = AttributeKey[Int]("loadCount")
// the State transformer
val f = (s: State) => {
val previous = s get key getOrElse 0
@ -697,113 +634,12 @@ has been loaded and prints that number:
Errors
------
Type error, found: ``Initialize[Task[String]]``, required: ``Initialize[String]`` or found: ``TaskKey[String]`` required: ``Initialize[String]``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This means that you are trying to supply a task when defining a setting
key. See :doc:`.sbt build definition </Getting-Started/Basic-Def>` for the
difference between task and setting keys, and
:doc:`more about settings </Getting-Started/More-About-Settings>`
for more on how to define one key in terms of other keys.
Setting keys are only evaluated once, on project load, while tasks are
evaluated repeatedly. Defining a setting in terms of a task does not
make sense because tasks must be re-evaluated every time.
One way to get a task when you didn't want one is to use the ``map``
method instead of the ``apply`` method.
:doc:`More about settings </Getting-Started/More-About-Settings>` covers this topic as well.
Suppose we define these keys, in ``./project/Build.scala`` (For details,
see :doc:/`.scala build definition </Getting-Started/Full-Def>`).
::
val baseSetting = SettingKey[String]("base-setting")
val derivedSetting = SettingKey[String]("derived-setting")
val baseTask = TaskKey[Long]("base-task")
val derivedTask = TaskKey[String]("derived-task")
Let's define an initialization for ``base-setting`` and ``base-task``.
We will then use these as inputs to other setting and task
initializations.
::
baseSetting := "base setting"
baseTask := { System.currentTimeMillis() }
Then this will not work:
::
// error: found: Initialize[Task[String]], required: Initialize[String]
derivedSetting <<= baseSetting.map(_.toString),
derivedSetting <<= baseTask.map(_.toString),
derivedSetting <<= (baseSetting, baseTask).map((a, b) => a.toString + b.toString),
One or more settings can be used as inputs to initialize another
setting, using the ``apply`` method.
::
derivedSetting <<= baseSetting.apply(_.toString)
derivedSetting <<= baseSetting(_.toString)
derivedSetting <<= (baseSetting, baseSetting)((a, b) => a.toString + b.toString)
Both settings and tasks can be used to initialize a task, using the
``map`` method.
::
derivedTask <<= baseSetting.map(_.toString)
derivedTask <<= baseTask.map(_.toString)
derivedTask <<= (baseSetting, baseTask).map((a, b) => a.toString + b.toString)
But, it is a compile time error to use ``map`` to initialize a setting:
::
// error: found: Initialize[Task[String]], required: Initialize[String]
derivedSetting <<= baseSetting.map(_.toString),
derivedSetting <<= baseTask.map(_.toString),
derivedSetting <<= (baseSetting, baseTask).map((a, b) => a.toString + b.toString),
It is not allowed to use a task as input to a settings initialization
with ``apply``:
::
// error: value apply is not a member of TaskKey[Long]
derivedSetting <<= baseTask.apply(_.toString)
// error: value apply is not a member of TaskKey[Long]
derivedTask <<= baseTask.apply(_.toString)
// error: value apply is not a member of (sbt.SettingKey[String], sbt.TaskKey[Long])
derivedTask <<= (baseSetting, baseTask).apply((a, b) => a.toString + b.toString)
Finally, it is not directly possible to use ``apply`` to initialize a
task.
::
// error: found String, required Task[String]
derivedTask <<= baseSetting.apply(_.toString)
On project load, "Reference to uninitialized setting"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Setting initializers are executed in order. If the initialization of a
setting depends on other settings that has not been initialized, sbt
will stop loading. This can happen using ``+=``, ``++=``, ``<<=``,
``<+=``, ``<++=``, and ``~=``. (To understand those methods,
:doc:`read this </Getting-Started/More-About-Settings>`.)
will stop loading.
In this example, we try to append a library to ``libraryDependencies``
before it is initialized with an empty sequence.
@ -837,13 +673,13 @@ A more subtle variation of this error occurs when using :doc:`scoped settings </
fullClasspath ~= (_.filterNot(_.data.name.contains("commons-io")))
)
Generally, all of the update operators can be expressed in terms of
``<<=``. To better understand the error, we can rewrite the setting as:
Generally, all of the setting definition methods can be expressed in terms of
``:=``. To better understand the error, we can rewrite the setting as:
::
// error: Reference to uninitialized setting
fullClasspath <<= (fullClasspath).map(_.filterNot(_.data.name.contains("commons-io")))
fullClasspath := fullClasspath.value.filterNot(_.data.name.contains("commons-io"))
This setting varies between the test and compile scopes. The solution is
use the scoped setting, both as the input to the initializer, and the
@ -851,7 +687,7 @@ setting that we update.
::
fullClasspath in Compile <<= (fullClasspath in Compile).map(_.filterNot(_.data.name.contains("commons-io")))
fullClasspath in Compile := (fullClasspath in Compile).value.filterNot(_.data.name.contains("commons-io"))
// or equivalently
fullClasspath in Compile ~= (_.filterNot(_.data.name.contains("commons-io")))