mirror of https://github.com/sbt/sbt.git
Very rough first "Getting Started" draft
parent
a4ecf18f20
commit
2de2a8d99f
|
|
@ -0,0 +1,213 @@
|
||||||
|
[Keys]: http://harrah.github.com/xsbt/latest/sxr/Keys.scala.html
|
||||||
|
|
||||||
|
# Basic Build Definition
|
||||||
|
|
||||||
|
This page describes sbt build definitions, including some "theory" and the
|
||||||
|
syntax of `build.sbt`. It assumes you know how to [[use sbt|Running]] and
|
||||||
|
have read the previous pages in the Getting Started category.
|
||||||
|
|
||||||
|
## Basic vs. Full Definition
|
||||||
|
|
||||||
|
An sbt build definition can contain "basic" files, ending in `.sbt`, and
|
||||||
|
"full" files, ending in `.scala`. You can use either one exclusively, or use
|
||||||
|
both. A good approach is to use basic `.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
|
||||||
|
|
||||||
|
This page discusses "basic" build definition, that is, `.sbt` files. See
|
||||||
|
[[Full Build Definition]] (later in Getting Started) for more on full build
|
||||||
|
files and how they relate to basic build files.
|
||||||
|
|
||||||
|
## What is a build definition?
|
||||||
|
|
||||||
|
** PLEASE READ THIS SECTION **
|
||||||
|
|
||||||
|
After examining a project and processing any build definition files, sbt
|
||||||
|
will end up with an immutable map (set of key-value pairs) describing the
|
||||||
|
build.
|
||||||
|
|
||||||
|
For example, one key is `name` and it maps to a string value, the name of
|
||||||
|
your project.
|
||||||
|
|
||||||
|
_Build definition files do not affect sbt's map directly._
|
||||||
|
|
||||||
|
Instead, the build definition creates a huge list of objects with type
|
||||||
|
`Setting[T]` where `T` is the type of the value in the map. (Scala's
|
||||||
|
`Setting[T]` is like `Setting<T>` in Java.) A `Setting` describes a
|
||||||
|
_transformation to the map_, such as adding a new key-value pair or
|
||||||
|
appending to an existing value. (In the spirit of functional programming, a
|
||||||
|
transformation returns a new map, it does not update the old map in-place.)
|
||||||
|
|
||||||
|
In `build.sbt`, you might create a `Setting[String]` for the name of your
|
||||||
|
project like this:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
name := "hello"
|
||||||
|
```
|
||||||
|
|
||||||
|
This `Setting[String]` transforms the map by adding (or replacing) the
|
||||||
|
`name` key, giving it the value `"hello"`. The transformed map becomes sbt's
|
||||||
|
new map.
|
||||||
|
|
||||||
|
To create its map, sbt first sorts the list of settings so that
|
||||||
|
all changes to the same key are made together, and values that depend on
|
||||||
|
other keys are processed after the keys they depend on. Then sbt walks over
|
||||||
|
the sorted list of `Setting` and applies each one to the map in turn.
|
||||||
|
|
||||||
|
Summary: _A build definition defines a list of `Setting[T]`, where a
|
||||||
|
`Setting[T]` is a transformation affecting sbt's map of key-value pairs and
|
||||||
|
`T` is the type of each value_.
|
||||||
|
|
||||||
|
## How `build.sbt` defines settings
|
||||||
|
|
||||||
|
Here's an example:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
name := "hello"
|
||||||
|
|
||||||
|
version := "1.0"
|
||||||
|
|
||||||
|
scalaVersion := "2.9.1"
|
||||||
|
```
|
||||||
|
|
||||||
|
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 lines of Scala code. An implication of
|
||||||
|
this is that you can't define a `val` or `object` in `build.sbt`.
|
||||||
|
|
||||||
|
On the left, `name`, `version`, and `scalaVersion` are _keys_. A key is an
|
||||||
|
instance of `Key[T]` where `T` is the expected value type.
|
||||||
|
|
||||||
|
Keys have a method called `:=`, which returns a `Setting[T]`. You could
|
||||||
|
use a Java-like syntax to call the method:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
name.:=("hello")
|
||||||
|
```
|
||||||
|
|
||||||
|
But Scala allows `name := "hello"` instead (in Scala, any method can use either syntax).
|
||||||
|
|
||||||
|
The `:=` method on key `name` returns a `Setting`, specifically a
|
||||||
|
`Setting[String]`. `String` also appears in the type of `name` itself, which
|
||||||
|
is `Key[String]`. In this case, the returned `Setting[String]` is
|
||||||
|
a transformation to add or replace the `name` 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
|
||||||
|
```
|
||||||
|
|
||||||
|
## Keys are defined in the Keys object
|
||||||
|
|
||||||
|
Keys are just fields in an object called [Keys]. A `build.sbt` implicitly
|
||||||
|
has an `import sbt.Keys._`, so `sbt.Keys.name` can be referred to as `name`.
|
||||||
|
|
||||||
|
Custom keys could also be defined in a
|
||||||
|
[[full build definition|Full Build Definition]] or a [[plugin|Using Plugins]].
|
||||||
|
|
||||||
|
## Other ways to transform settings
|
||||||
|
|
||||||
|
Replacement with `:=` is the simplest transformation, but there are several
|
||||||
|
others. For example you can append to a list value with `+=`.
|
||||||
|
|
||||||
|
The other transformations require an understanding of [[scopes|Scopes]], so the
|
||||||
|
[[next section|Scopes]] is about scopes and the
|
||||||
|
[[section after that|More About Settings]] goes into more detail about settings.
|
||||||
|
|
||||||
|
## Task Keys
|
||||||
|
|
||||||
|
While all keys extend the `Key[T]` trait, there are two important
|
||||||
|
subclasses of `Key`.
|
||||||
|
|
||||||
|
- `SettingKey[T]`: a key with a value that never changes (the value is
|
||||||
|
computed one time when loading the project, and kept around).
|
||||||
|
- `TaskKey[T]`: a key with a value that has to be recomputed each time,
|
||||||
|
potentially creating side effects.
|
||||||
|
- (We're ignoring a third subclass, `InputKey[T]`, for now. Check out
|
||||||
|
[[Input Tasks]] for more about it.)
|
||||||
|
|
||||||
|
A `TaskKey[T]` is said to define a _task_. Tasks are operations such as
|
||||||
|
`compile` or `package`. They may return `Unit` (`Unit` is Scala for `void`),
|
||||||
|
or they may return a value related to the task, for example `package` is a
|
||||||
|
`TaskKey[File]` and its value is the jar file it creates.
|
||||||
|
|
||||||
|
Each time you start a task execution, for example by typing `compile` at the
|
||||||
|
interactive sbt prompt, sbt will re-run any tasks involved exactly once.
|
||||||
|
|
||||||
|
sbt's map describing the project can cache a string value for a setting such
|
||||||
|
as `name`, but it has to keep around some executable code for a task such as
|
||||||
|
`compile` -- even if that executable code eventually returns a string, it
|
||||||
|
has to be re-run every time.
|
||||||
|
|
||||||
|
_A given key always refers to either a task or a plain setting._ That is,
|
||||||
|
"taskiness" (whether to re-run each time) is a property of the key, not the
|
||||||
|
value.
|
||||||
|
|
||||||
|
Using `:=`, you can assign a function to a task, and that function will be
|
||||||
|
re-run each time:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
hello := { println("Hello!") }
|
||||||
|
```
|
||||||
|
|
||||||
|
From a type-system perspective, the `Setting` created from a task key is
|
||||||
|
slightly different from the one created from a setting key. `taskKey := 42`
|
||||||
|
results in a `Setting[Task[T]]` while `settingKey := 42` results in a
|
||||||
|
`Setting[T]`. For most purposes this makes no difference; the task key still
|
||||||
|
creates a value of type `T` when the task executes.
|
||||||
|
|
||||||
|
The `T` vs. `Task[T]` type difference has this implication: a setting key
|
||||||
|
can't depend on a task key, because a setting key is cached, and not
|
||||||
|
re-run. More on this in [[More About Settings]], coming up soon.
|
||||||
|
|
||||||
|
## Keys in sbt interactive mode
|
||||||
|
|
||||||
|
In sbt's interactive mode, you can type the name of any key to retrieve
|
||||||
|
the value of that key. If the key represents a task, then the task will be
|
||||||
|
executed.
|
||||||
|
|
||||||
|
This is why typing `compile` runs the compile task. `compile` is a task key.
|
||||||
|
|
||||||
|
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]). For example, in `Keys.scala`, there's this key:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
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`.
|
||||||
|
|
||||||
|
To learn more about any key, type `inspect <keyname>` at the sbt interactive
|
||||||
|
prompt. Some of the information `inspect` displays won't make sense yet, but
|
||||||
|
at the top it shows you the setting's value type and a brief description of
|
||||||
|
the setting.
|
||||||
|
|
||||||
|
## Imports in `build.sbt`
|
||||||
|
|
||||||
|
You can place import statements at the top of `build.sbt`; they need not be
|
||||||
|
separated by blank lines.
|
||||||
|
|
||||||
|
There are some implied default imports, as follows:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
import sbt._
|
||||||
|
import Process._
|
||||||
|
import Keys._
|
||||||
|
```
|
||||||
|
|
||||||
|
(In addition, if you have a [[full build definition|Full Build Definition]],
|
||||||
|
the contents of any `Build` or `Plugin` objects in that definition will be
|
||||||
|
imported. More on that when we get to
|
||||||
|
[[full build definitions|Full Build Definition]].)
|
||||||
|
|
||||||
|
## Next
|
||||||
|
|
||||||
|
Move on to [[learn about scopes|Scopes]].
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
[Keys]: http://harrah.github.com/xsbt/latest/sxr/Keys.scala.html "Keys.scala"
|
||||||
|
[Defaults]: http://harrah.github.com/xsbt/latest/sxr/Defaults.scala.html "Defaults.scala"
|
||||||
|
[IO]: http://harrah.github.com/xsbt/latest/api/index.html#sbt.IO$ "IO object"
|
||||||
|
|
||||||
|
# Custom Settings and Tasks
|
||||||
|
|
||||||
|
This page gets you started creating your own settings and tasks.
|
||||||
|
|
||||||
|
Be sure you've read earlier pages in the Getting Started series, especially
|
||||||
|
[[build.sbt|Basic Build Definition]] and [[More About Settings]], before
|
||||||
|
reading this page.
|
||||||
|
|
||||||
|
## Defining a key
|
||||||
|
|
||||||
|
[Keys] is packed with examples illustrating how to define
|
||||||
|
keys. Most of the keys are implemented in [Defaults].
|
||||||
|
|
||||||
|
Keys have one of three types. `SettingKey` and `TaskKey` are described in
|
||||||
|
[[Basic Build Definition]]. Read about `InputKey` on the [[Input Tasks]]
|
||||||
|
page.
|
||||||
|
|
||||||
|
Some examples from [Keys]:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
val scalaVersion = SettingKey[String]("scala-version", "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 (`"The version of scala used for
|
||||||
|
building."`).
|
||||||
|
|
||||||
|
Remember from [[Basic Build Definition]] that the type parameter `T` in `SettingKey[T]`
|
||||||
|
indicates the type of value a setting has. `T` in `TaskKey[T]` indicates the
|
||||||
|
type of the task's result. Also remember from [[Basic Build Definition]]
|
||||||
|
that a setting has a fixed value cached forever, while a task is re-computed
|
||||||
|
for every "task execution" (every time someone types a command at the sbt
|
||||||
|
interactive prompt or in batch mode).
|
||||||
|
|
||||||
|
Keys may be defined in a `.scala` file (as described in
|
||||||
|
[[Full Build Definition]]), or in a plugin (as described in
|
||||||
|
[[Using Plugins]]).
|
||||||
|
|
||||||
|
## Implementing a task
|
||||||
|
|
||||||
|
Once you've defined a key, you'll need to use it in some task. You could be
|
||||||
|
defining your own task, or you could be planning to redefine an existing
|
||||||
|
task. Either way looks the same; if the task has no dependencies on other
|
||||||
|
settings or tasks, use `:=` to associate a function with the task key:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
sampleStringTask := System.getProperty("user.home)
|
||||||
|
|
||||||
|
sampleIntTask := {
|
||||||
|
val sum = 1 + 2
|
||||||
|
println("sum: " + sum)
|
||||||
|
sum
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If the task has dependencies, you'd use `<<=` instead of course, as
|
||||||
|
discussed in [[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 your task
|
||||||
|
that does whatever you're trying to do. For example, maybe you're trying to
|
||||||
|
format HTML in which case you might want to use an HTML library (you would
|
||||||
|
[[add a library dependency to your build definition|Using Plugins]] 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] 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 imply running
|
||||||
|
that task), and then do whatever else you like after the previous
|
||||||
|
implementation completes.
|
||||||
|
|
||||||
|
```scala
|
||||||
|
// These two settings are equivalent
|
||||||
|
intTask <<= intTask map { (value: Int) => value + 1 }
|
||||||
|
intTask ~= { (value: Int) => value + 1 }
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use plugins!
|
||||||
|
|
||||||
|
If you find you have a lot of custom code in `.scala` files, consider moving
|
||||||
|
it to a plugin for re-use across multiple projects.
|
||||||
|
|
||||||
|
It's very easy to create a plugin, as [[teased earlier|Using Plugins]] and
|
||||||
|
[[discussed at more length here|Plugins]].
|
||||||
|
|
||||||
|
## Next
|
||||||
|
|
||||||
|
This page has been a quick taste; there's much much more about custom tasks
|
||||||
|
on the [[Tasks]] page.
|
||||||
|
|
||||||
|
You're at the end of Getting Started! There's a [[brief recap|Summary]].
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
[Maven]: http://maven.apache.org/
|
||||||
|
|
||||||
|
# Directory structure
|
||||||
|
|
||||||
|
This page assumes you've [[installed sbt|Setup]] and seen the [[Hello, World|Hello World]].
|
||||||
|
|
||||||
|
## Base directory
|
||||||
|
|
||||||
|
In sbt's terminology, the "base directory" is the directory containing the
|
||||||
|
project. So if you created a project `hello` containing `hello/build.sbt`
|
||||||
|
and `hello/hw.scala` as in the [[Hello, World|Hello World]] example, `hello`
|
||||||
|
is your base directory.
|
||||||
|
|
||||||
|
## Source code
|
||||||
|
|
||||||
|
Source code can be placed in the project's base directory as with
|
||||||
|
`hello/hw.scala`. However, most people don't do this for real projects; too
|
||||||
|
much clutter.
|
||||||
|
|
||||||
|
sbt uses the same directory structure as [Maven] for source files by default
|
||||||
|
(all paths are relative to the base directory):
|
||||||
|
|
||||||
|
```text
|
||||||
|
src/
|
||||||
|
main/
|
||||||
|
resources/
|
||||||
|
<files to include in main jar here>
|
||||||
|
scala/
|
||||||
|
<main Scala sources>
|
||||||
|
java/
|
||||||
|
<main Java sources>
|
||||||
|
test/
|
||||||
|
resources
|
||||||
|
<files to include in test jar here>
|
||||||
|
scala/
|
||||||
|
<test Scala sources>
|
||||||
|
java/
|
||||||
|
<test Java sources>
|
||||||
|
```
|
||||||
|
|
||||||
|
Other directories in `src/` will be ignored. Additionally, all hidden directories will be ignored.
|
||||||
|
|
||||||
|
## sbt build definition files
|
||||||
|
|
||||||
|
You've already seen `build.sbt` in the project's base directory. Other sbt
|
||||||
|
files appear in a `project` subdirectory.
|
||||||
|
|
||||||
|
`project` can contain `.scala` files, also called
|
||||||
|
[[full build definitions|Full Build Definition]], when you're doing
|
||||||
|
something too complex for a `.sbt` file.
|
||||||
|
|
||||||
|
sbt-launch.jar automatically downloads the Scala compiler, sbt itself, and
|
||||||
|
any dependencies to the `project/boot` directory. These tools are used to
|
||||||
|
compile the build definition. If you've configured a shared `~/.sbt/boot`
|
||||||
|
directory in your sbt script, [[as suggested|Setup Notes]], then you may not
|
||||||
|
have much in `project/boot`.
|
||||||
|
|
||||||
|
```text
|
||||||
|
build.sbt
|
||||||
|
project/
|
||||||
|
Build.scala
|
||||||
|
boot/
|
||||||
|
```
|
||||||
|
|
||||||
|
You may see `.sbt` files inside `project/` but they are not equivalent to
|
||||||
|
`.sbt` files in the project's base directory. Explaining this will
|
||||||
|
[[come later|Full Build Definition]], since you'll need some background
|
||||||
|
information first.
|
||||||
|
|
||||||
|
## Build products
|
||||||
|
|
||||||
|
Generated files (compiled classes, packaged jars, managed files, caches, and documentation) will be written to the `target` directory by default.
|
||||||
|
|
||||||
|
## Configuring version control
|
||||||
|
|
||||||
|
Your `.gitignore` (or equivalent for other version control systems) should contain:
|
||||||
|
|
||||||
|
```text
|
||||||
|
target/
|
||||||
|
project/boot/
|
||||||
|
```
|
||||||
|
|
||||||
|
These directories are automatically created and managed by sbt and need not be kept in version control.
|
||||||
|
|
||||||
|
# Next
|
||||||
|
|
||||||
|
Learn about [[running sbt|Running]].
|
||||||
|
|
@ -0,0 +1,259 @@
|
||||||
|
# Full Build Definition
|
||||||
|
|
||||||
|
This page is part of a Getting Started series, and it assumes you've read
|
||||||
|
previous pages in the series, _especially_ [[Basic Build Definition]] and
|
||||||
|
[[More About Settings]].
|
||||||
|
|
||||||
|
## sbt is recursive
|
||||||
|
|
||||||
|
`build.sbt` is so simple, it conceals how sbt really works. sbt builds are
|
||||||
|
defined with Scala code. That code, itself, has to be built. What better way
|
||||||
|
than with sbt?
|
||||||
|
|
||||||
|
The `project` directory _is another project inside your project_ which knows
|
||||||
|
how to build your project. The project inside `project` can (in theory) do
|
||||||
|
anything any other project can do. _Your build definition is an sbt
|
||||||
|
project._
|
||||||
|
|
||||||
|
And the turtles go all the way down. If you like, you can tweak the build
|
||||||
|
definition of the build definition project, by creating a `project/project/`
|
||||||
|
directory.
|
||||||
|
|
||||||
|
Here's an illustration.
|
||||||
|
|
||||||
|
```text
|
||||||
|
|
||||||
|
hello/ # your project's base directory
|
||||||
|
|
||||||
|
Hello.scala # a source file in your project (could be in
|
||||||
|
# src/main/scala too)
|
||||||
|
|
||||||
|
build.sbt # build.sbt is part of the source code for the
|
||||||
|
# build definition project inside project/
|
||||||
|
|
||||||
|
project/ # base directory of the build definition project
|
||||||
|
|
||||||
|
Build.scala # a source file in the project/ project,
|
||||||
|
# that is, a source file in the build definition
|
||||||
|
|
||||||
|
build.sbt # this is part of a build definition for a project
|
||||||
|
# in project/project ; build definition's build
|
||||||
|
# definition
|
||||||
|
|
||||||
|
|
||||||
|
project/ # base directory of the build definition project
|
||||||
|
# for the build definition
|
||||||
|
|
||||||
|
Build.scala # source file in the project/project/ project
|
||||||
|
```
|
||||||
|
|
||||||
|
_Don't worry!_ Most of the time you are not going to need all that. But
|
||||||
|
understanding the principle can be helpful.
|
||||||
|
|
||||||
|
By the way: any files ending in `.scala` or `.sbt` are used, naming them
|
||||||
|
`build.sbt` and `Build.scala` are conventions only. This also means that
|
||||||
|
multiple files are allowed.
|
||||||
|
|
||||||
|
## "full build definition" means a `.scala` file in the build definition project
|
||||||
|
|
||||||
|
`.sbt` files are merged into their sibling `project`
|
||||||
|
directory. Looking back at the project layout:
|
||||||
|
|
||||||
|
```text
|
||||||
|
|
||||||
|
hello/ # your project's base directory
|
||||||
|
|
||||||
|
build.sbt # build.sbt is part of the source code for the
|
||||||
|
# build definition project inside project/
|
||||||
|
|
||||||
|
project/ # base directory of the build definition project
|
||||||
|
|
||||||
|
Build.scala # a source file in the project/ project,
|
||||||
|
# that is, a source file in the build definition
|
||||||
|
```
|
||||||
|
|
||||||
|
The Scala expressions in `build.sbt` are compiled alongside and merged with
|
||||||
|
`Build.scala` (or any other `.scala` files in the `project/` directory).
|
||||||
|
|
||||||
|
_`.sbt` files in the base directory for a project become part of the
|
||||||
|
`project` build definition project also located in that base directory._
|
||||||
|
|
||||||
|
`build.sbt`, also known as a
|
||||||
|
[[basic build definition|Basic Build Definition]], is a convenient shorthand
|
||||||
|
for adding settings to the build definition project.
|
||||||
|
|
||||||
|
A _full build definition_ is a build definition that includes `.scala` files
|
||||||
|
underneath `project/`.
|
||||||
|
|
||||||
|
## Relating `build.sbt` to `Build.scala`
|
||||||
|
|
||||||
|
To mix `.sbt` and `.scala` files in your build definition, you need to
|
||||||
|
understand how they relate.
|
||||||
|
|
||||||
|
The following two files illustrate. First, if your project is in `hello`,
|
||||||
|
create `hello/project/Build.scala` as follows:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
import sbt._
|
||||||
|
import Keys._
|
||||||
|
|
||||||
|
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")
|
||||||
|
|
||||||
|
override lazy val settings = super.settings ++
|
||||||
|
Seq(sampleKeyA := "A: in Build.settings in Build.scala", resolvers := Seq())
|
||||||
|
|
||||||
|
lazy val root = Project(id = "hello",
|
||||||
|
base = file("."),
|
||||||
|
settings = Project.defaultSettings ++ Seq(sampleKeyB := "B: in the root project settings in Build.scala"))
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, create `hello/build.sbt` as follows:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
sampleKeyC in ThisBuild := "C: in build.sbt scoped to ThisBuild"
|
||||||
|
|
||||||
|
sampleKeyD := "D: in build.sbt"
|
||||||
|
```
|
||||||
|
|
||||||
|
Start up the sbt interactive prompt. Type `inspect sample-a` and you should
|
||||||
|
see (among other things):
|
||||||
|
|
||||||
|
```text
|
||||||
|
[info] Setting: java.lang.String = A: in Build.settings in Build.scala
|
||||||
|
[info] Provided by:
|
||||||
|
[info] {file:/home/hp/checkout/hello/}/*:sample-a
|
||||||
|
```
|
||||||
|
|
||||||
|
and then `inspect sample-c` and you should see:
|
||||||
|
|
||||||
|
```text
|
||||||
|
[info] Setting: java.lang.String = C: in build.sbt scoped to ThisBuild
|
||||||
|
[info] Provided by:
|
||||||
|
[info] {file:/home/hp/checkout/hello/}/*:sample-c
|
||||||
|
```
|
||||||
|
|
||||||
|
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 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`:
|
||||||
|
|
||||||
|
```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
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that `sample-b` 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`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
[info] Setting: java.lang.String = D: in build.sbt
|
||||||
|
[info] Provided by:
|
||||||
|
[info] {file:/home/hp/checkout/hello/}hello/*:sample-d
|
||||||
|
```
|
||||||
|
|
||||||
|
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 setting in `build.sbt`
|
||||||
|
should "win" over the one in `Build.scala`.
|
||||||
|
|
||||||
|
One other thing you may have noticed: `sampleKeyC` and `sampleKeyD` were
|
||||||
|
available inside `build.sbt`. That's because sbt imports the contents of
|
||||||
|
your `Build` object into your `.sbt` files. In this case `import
|
||||||
|
HelloBuild._` was implicitly done for the `build.sbt` file.
|
||||||
|
|
||||||
|
In summary:
|
||||||
|
|
||||||
|
- In `.scala` files, you can add settings to `Build.settings` for sbt to
|
||||||
|
find, and they are automatically build-scoped.
|
||||||
|
- In `.scala` files, you can add settings to `Project.settings` for sbt to
|
||||||
|
find, and they are automatically project-scoped.
|
||||||
|
- Any `Build` object you write in a `.scala` file will have its contents
|
||||||
|
imported and available to `.sbt` files.
|
||||||
|
- The settings in `.sbt` files are _appended_ to the settings in `.scala`
|
||||||
|
files.
|
||||||
|
- The settings in `.sbt` files are project-scoped unless you explicitly
|
||||||
|
specify another scope.
|
||||||
|
|
||||||
|
## 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`, and
|
||||||
|
method definitions.
|
||||||
|
|
||||||
|
_The 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.
|
||||||
|
|
||||||
|
You could think of it this way: there's one build definition, which is a
|
||||||
|
nested project inside your main project. `.sbt` ("basic") and `.scala`
|
||||||
|
("full") files are compiled together to create that single definition.
|
||||||
|
|
||||||
|
`.scala` files are also required to define multiple projects in a single
|
||||||
|
build. More on that is coming up in [[Multi-Project Builds]].
|
||||||
|
|
||||||
|
## The build definition project in interactive mode
|
||||||
|
|
||||||
|
You can switch the sbt interactive prompt to have the build definition
|
||||||
|
project in `project/` as the current project. To do so, type `reload
|
||||||
|
plugins`.
|
||||||
|
|
||||||
|
```text
|
||||||
|
> reload plugins
|
||||||
|
[info] Set current project to default-a0e8e4 (in build file:/home/hp/checkout/hello/project/)
|
||||||
|
> show sources
|
||||||
|
[info] ArrayBuffer(/home/hp/checkout/hello/project/Build.scala)
|
||||||
|
> reload return
|
||||||
|
[info] Loading project definition from /home/hp/checkout/hello/project
|
||||||
|
[info] Set current project to hello (in build file:/home/hp/checkout/hello/)
|
||||||
|
> show sources
|
||||||
|
[info] ArrayBuffer(/home/hp/checkout/hello/hw.scala)
|
||||||
|
>
|
||||||
|
```
|
||||||
|
|
||||||
|
As shown above, you use `reload return` to leave the build definition
|
||||||
|
project and return to your regular project.
|
||||||
|
|
||||||
|
## Reminder: it's all immutable
|
||||||
|
|
||||||
|
It would be wrong to think that the settings in `build.sbt` are added to the
|
||||||
|
`settings` fields in `Build` and `Project` objects. Instead, the settings
|
||||||
|
list from `Build` and `Project`, and the settings from `build.sbt`, are
|
||||||
|
concatenated into another immutable list which is then used by sbt. The
|
||||||
|
`Build` and `Project` objects are "immutable configuration" forming only
|
||||||
|
part of the complete build definition.
|
||||||
|
|
||||||
|
In fact, there are other sources of settings as well. They are appended in
|
||||||
|
this order:
|
||||||
|
|
||||||
|
- Settings from `Build.settings` and `Project.settings` in your `.scala` files.
|
||||||
|
- Your user-global settings; for example in `~/.sbt/build.sbt` you can
|
||||||
|
define settings affecting _all_ your projects.
|
||||||
|
- Settings injected by plugins, see [[Using Plugins]] coming up next.
|
||||||
|
- Settings from `.sbt` files in the project.
|
||||||
|
- FIXME parse this: "settings that configure the global plugin definition for a
|
||||||
|
project-level plugin definition as if it were declared locally"
|
||||||
|
|
||||||
|
Later settings override earlier ones. The entire list of settings forms the
|
||||||
|
build definition.
|
||||||
|
|
||||||
|
## Next
|
||||||
|
|
||||||
|
Move on to [[Using Plugins]].
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
|
||||||
|
# Hello, World
|
||||||
|
|
||||||
|
This page assumes you've [[installed sbt|Setup]].
|
||||||
|
|
||||||
|
## Create a project directory with source code
|
||||||
|
|
||||||
|
A valid sbt project can be a directory containing a single source file. You could create it and run it like this:
|
||||||
|
|
||||||
|
```text
|
||||||
|
$ mkdir hello
|
||||||
|
$ cd hello
|
||||||
|
$ echo 'object Hi { def main(args: Array[String]) = println("Hi!") }' > hw.scala
|
||||||
|
$ sbt
|
||||||
|
...
|
||||||
|
> run
|
||||||
|
...
|
||||||
|
Hi!
|
||||||
|
```
|
||||||
|
|
||||||
|
In this case, sbt works purely by convention. You don't need to tell sbt about:
|
||||||
|
|
||||||
|
- Sources in the base directory
|
||||||
|
- Sources in `src/main/scala` or `src/main/java`
|
||||||
|
- Tests in `src/test/scala` or `src/test/java`
|
||||||
|
- Data files in `src/main/resources` or `src/test/resources`
|
||||||
|
- jars in `lib`
|
||||||
|
|
||||||
|
By default, sbt will build projects with the same version of Scala used to run sbt itself.
|
||||||
|
|
||||||
|
When you run `sbt` and there is no build definition, it assumes default settings:
|
||||||
|
|
||||||
|
- main Scala sources go in the base directory or in `src/main/scala`
|
||||||
|
- test Scala sources go in `src/test/scala`
|
||||||
|
- unmanaged dependencies (jars) go in `lib/`
|
||||||
|
- the Scala version used to run sbt is used to build the project
|
||||||
|
|
||||||
|
You can run the project with `sbt run` or enter the [Scala REPL](http://www.scala-lang.org/node/2097)
|
||||||
|
with `sbt console`. `sbt console` sets up your project's classpath so you can
|
||||||
|
try out live Scala examples based on your project's code.
|
||||||
|
|
||||||
|
## Build definition
|
||||||
|
|
||||||
|
Most projects will need some manual setup. Basic build definitions are done
|
||||||
|
in a file called `build.sbt` placed in the project's base directory.
|
||||||
|
|
||||||
|
For example, if your project is in the directory `hello`, in `hello/build.sbt` you might write:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
name := "hello"
|
||||||
|
|
||||||
|
version := "1.0"
|
||||||
|
|
||||||
|
scalaVersion := "2.9.1"
|
||||||
|
```
|
||||||
|
|
||||||
|
In [[Basic Build Definition]] you'll learn more about how to write a `build.sbt` file.
|
||||||
|
|
||||||
|
If you plan to package your project in a jar, you will want to set at least
|
||||||
|
the name and version in a `build.sbt`.
|
||||||
|
|
||||||
|
## Setting the sbt version
|
||||||
|
|
||||||
|
You can force a particular version of sbt by creating a file `hello/project/build.properties`.
|
||||||
|
In this file, write:
|
||||||
|
|
||||||
|
```text
|
||||||
|
sbt.version=0.11.0
|
||||||
|
```
|
||||||
|
|
||||||
|
From 0.10 onwards, sbt is 99% compatible from release to release. Still,
|
||||||
|
setting the sbt version in `project/build.properties` avoids any potential
|
||||||
|
confusion.
|
||||||
|
|
||||||
|
# Next
|
||||||
|
|
||||||
|
Learn about the [[file and directory layout|Directory Structure]] of an sbt project.
|
||||||
|
|
||||||
34
Home.md
34
Home.md
|
|
@ -1,19 +1,37 @@
|
||||||
sbt is a build tool for Scala projects that aims to do the basics well. It requires Java 1.6 or later.
|
sbt is a build tool for Scala and Java projects that aims to do the basics well. It requires Java 1.6 or later.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
* Fairly fast, unintrusive, and easy to set up for simple projects
|
* Easy to set up for simple projects
|
||||||
* [[Configuration|Basic Configuration]], [[customization|Tasks]], and [[extension|Plugins]] are done in Scala
|
* [[Basic build definition|Basic Build Definition]] uses a Scala-based "domain-specific language" (DSL)
|
||||||
* Accurate recompilation (in theory) is done using information extracted from the compiler
|
* More advanced [[full build definitions|Full Build Definition]] and [[extensions|Custom Settings and Tasks]] use the full flexibility of unrestricted Scala code
|
||||||
|
* Accurate incremental recompilation using information extracted from the compiler
|
||||||
* Continuous compilation and testing with [[triggered execution|Triggered Execution]]
|
* Continuous compilation and testing with [[triggered execution|Triggered Execution]]
|
||||||
* Supports mixed Scala/[[Java|Java Sources]] projects, packages jars, generates documentation with scaladoc
|
* Packages and publishes jars
|
||||||
|
* Generates documentation with scaladoc
|
||||||
|
* Supports mixed Scala/[[Java|Java Sources]] projects
|
||||||
* Supports [[Testing|testing]] with ScalaCheck, specs, and ScalaTest (JUnit is supported by a plugin)
|
* Supports [[Testing|testing]] with ScalaCheck, specs, and ScalaTest (JUnit is supported by a plugin)
|
||||||
* Starts the Scala REPL with project classes and dependencies on the classpath
|
* Starts the Scala REPL with project classes and dependencies on the classpath
|
||||||
* [[Multi-module and external project|Full Configuration]] support
|
* [[Sub-project|Multi-Project Builds]] support (put multiple packages in one project)
|
||||||
|
* [[External project|External Projects]] support (list a git repository as a dependency!)
|
||||||
* Parallel task execution, including parallel test execution
|
* Parallel task execution, including parallel test execution
|
||||||
* [[Dependency management support|Library Management]]: inline declarations, external Ivy or Maven configuration files, or manual management
|
* [[Library management support|Library Management]]: inline declarations, external Ivy or Maven configuration files, or manual management
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
To get started, read [[Setup]], [[Running]]. For configuration instructions, start with [[Settings]]. See also [[Basic Configuration]], [[Full Configuration]], and [[Quick Configuration Examples]]. If you are familiar with 0.7.x, please see the [[migration page|Migrating from sbt 0.7.x to 0.10.x]]. Documentation for 0.7.x is still available on the [Google Code Site](http://code.google.com/p/simple-build-tool/wiki/DocumentationHome).
|
|
||||||
|
To get started, start with [[Setup]], and continue through the other Getting
|
||||||
|
Started pages listed in the sidebar on the right. It's best to read in
|
||||||
|
order, as later pages in the Getting Started series build on concepts
|
||||||
|
introduced earlier.
|
||||||
|
|
||||||
|
_Please read the Getting Started pages._ You will save yourself a _lot_ of
|
||||||
|
time if you have the right understanding of the big picture
|
||||||
|
up-front. [[Start with setup|Setup]].
|
||||||
|
|
||||||
|
If you are familiar with 0.7.x, please see the
|
||||||
|
[[migration page|Migrating from sbt 0.7.x to 0.10.x]]. Documentation for
|
||||||
|
0.7.x is still available on the
|
||||||
|
[Google Code Site](http://code.google.com/p/simple-build-tool/wiki/DocumentationHome).
|
||||||
|
This wiki applies to sbt 0.10 and later.
|
||||||
|
|
||||||
The mailing list is at <http://groups.google.com/group/simple-build-tool/topics>. Please use it for questions and comments!
|
The mailing list is at <http://groups.google.com/group/simple-build-tool/topics>. Please use it for questions and comments!
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,229 @@
|
||||||
|
[Keys]: http://harrah.github.com/xsbt/latest/sxr/Keys.scala.html "Keys.scala"
|
||||||
|
[Apache Ivy]: http://ant.apache.org/ivy/
|
||||||
|
[Ivy revisions]: http://ant.apache.org/ivy/history/2.2.0/ivyfile/dependency.html#revision
|
||||||
|
[Extra attributes]: http://ant.apache.org/ivy/history/2.2.0/concept.html#extra
|
||||||
|
[through Ivy]: http://ant.apache.org/ivy/history/latest-milestone/concept.html#checksum
|
||||||
|
[ScalaCheck]: http://code.google.com/p/scalacheck/
|
||||||
|
[specs]: http://code.google.com/p/specs/
|
||||||
|
[ScalaTest]: http://www.artima.com/scalatest/
|
||||||
|
|
||||||
|
# Library Dependencies
|
||||||
|
|
||||||
|
This page assumes you've read the earlier Getting Started pages, in particular
|
||||||
|
[[Basic Build Definition]], [[Scopes]], and [[More About Settings]].
|
||||||
|
|
||||||
|
Library dependencies can be added in two ways:
|
||||||
|
|
||||||
|
- _unmanaged dependencies_ are jars dropped into the `lib` directory
|
||||||
|
- _managed dependencies_ are configured in the build definition and
|
||||||
|
downloaded automatically from repositories
|
||||||
|
|
||||||
|
## Unmanaged dependencies
|
||||||
|
|
||||||
|
Most people use managed dependencies instead of unmanaged. But unmanaged can
|
||||||
|
be simpler when starting out.
|
||||||
|
|
||||||
|
Unmanaged dependencies work like this: add jars to `lib` and they will be
|
||||||
|
placed on the project classpath. Not much else to it!
|
||||||
|
|
||||||
|
You can place test jars such as [ScalaCheck], [specs], and [ScalaTest] in
|
||||||
|
`lib` as well.
|
||||||
|
|
||||||
|
Dependencies in `lib` go on all the classpaths (for `compile`, `test`,
|
||||||
|
`run`, and `console`). If you wanted to change the classpath for just one of
|
||||||
|
those, you would adjust `dependencyClasspath in Compile` or
|
||||||
|
`dependencyClasspath in Runtime` for example. You could use `~=` to get the
|
||||||
|
previous classpath value, filter some entries out, and return a new
|
||||||
|
classpath value. See [[More About Settings]] 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 a different
|
||||||
|
directory rather than `lib`.
|
||||||
|
|
||||||
|
To use `custom_lib` instead of `lib`:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
unmanagedBase <<= baseDirectory { base => base / "custom_lib" }
|
||||||
|
```
|
||||||
|
|
||||||
|
`baseDirectory` is the project's root directory, so here you're changing
|
||||||
|
`unmanagedBase` depending on `baseDirectory`, using `<<=` as explained in
|
||||||
|
[[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 or do
|
||||||
|
something else complex, you might need to replace the whole `unmanaged-jars`
|
||||||
|
task with one that does something else.
|
||||||
|
|
||||||
|
## Managed Dependencies
|
||||||
|
|
||||||
|
sbt uses [Apache Ivy] to implement managed dependencies, so if you're
|
||||||
|
familiar with Maven or Ivy, you won't have much trouble.
|
||||||
|
|
||||||
|
### The `libraryDependencies` key
|
||||||
|
|
||||||
|
Most of the time, you can simply list your dependencies in the setting
|
||||||
|
`libraryDependencies`. It's also possible to write a Maven POM file or Ivy
|
||||||
|
configuration file to externally configure your dependencies, and have sbt
|
||||||
|
use those external configuration files. You can learn more about that
|
||||||
|
[[here|Library Management]].
|
||||||
|
|
||||||
|
Declaring a dependency looks like this, where `groupId`, `artifactId`, and
|
||||||
|
`revision` are strings:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
libraryDependencies += groupID % artifactID % revision
|
||||||
|
```
|
||||||
|
|
||||||
|
or like this, where `configuration` is also a string:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
libraryDependencies += groupID % artifactID % revision % configuration
|
||||||
|
```
|
||||||
|
|
||||||
|
`libraryDependencies` is declared in [Keys] like this:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
val libraryDependencies = SettingKey[Seq[ModuleID]]("library-dependencies", "Declares managed dependencies.")
|
||||||
|
```
|
||||||
|
|
||||||
|
The `%` methods create `ModuleID` objects from strings, then you add those
|
||||||
|
`ModuleID` to `libraryDependencies`.
|
||||||
|
|
||||||
|
Of course, sbt (via Ivy) has to know where to download the module. If
|
||||||
|
your module is in one of the default repositories sbt comes with, this will
|
||||||
|
just work. For example, Apache Derby is in a default repository:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
libraryDependencies += "org.apache.derby" % "derby" % "10.4.1.3"
|
||||||
|
```
|
||||||
|
|
||||||
|
If you type that in `build.sbt` and then `update`, sbt should download
|
||||||
|
Derby to `~/.ivy2/cache/org.apache.derby/`. (By the way, `update` is a
|
||||||
|
dependency of `compile` so there's no need to manually type `update` most of
|
||||||
|
the time.)
|
||||||
|
|
||||||
|
Of course, you can also use `++=` to add a list of dependencies all at once:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
libraryDependencies ++= Seq(
|
||||||
|
groupID % artifactID % revision,
|
||||||
|
groupID % otherID % otherRevision
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
And in rare cases you might find reasons to use `:=`, `<<=`, `<+=`,
|
||||||
|
etc. with `libraryDependencies` as well.
|
||||||
|
|
||||||
|
### Getting the right Scala version with `%%`
|
||||||
|
|
||||||
|
If you use `groupID %% artifactID % revision` rather than `groupID %
|
||||||
|
artifactID % revision` (the difference is the double `%%` after the
|
||||||
|
groupID), sbt will add your project's Scala version to the artifact name.
|
||||||
|
This is just a shortcut. You could write this without the `%%`:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
libraryDependencies += "org.scala-tools" % "scala-stm_2.9.1" % "0.3"
|
||||||
|
```
|
||||||
|
|
||||||
|
Assuming the `scalaVersion` for your build is `2.9.1`, the following is
|
||||||
|
identical:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
libraryDependencies += "org.scala-tools" %% "scala-stm" % "0.3"
|
||||||
|
```
|
||||||
|
|
||||||
|
The idea is that many dependencies are compiled for multiple Scala versions,
|
||||||
|
and you'd like to get the one that matches your project.
|
||||||
|
|
||||||
|
The complexity in practice is that often a dependency will work with a slightly different Scala version; but `%%` is not smart about that. So if
|
||||||
|
the dependency is available for `2.9.0` but you're using `scalaVersion :=
|
||||||
|
"2.9.1"`, you won't be able to use `%%` even though the `2.9.0` dependency
|
||||||
|
likely works. If `%%` stops working just go see which versions the
|
||||||
|
dependency is really built for, and hardcode the one you think will work
|
||||||
|
(assuming there is one).
|
||||||
|
|
||||||
|
See [[Cross Build]] for some more detail on this.
|
||||||
|
|
||||||
|
### Ivy revisions
|
||||||
|
|
||||||
|
The `revision` in `groupID % artifactID % revision` does not have to be a
|
||||||
|
single fixed version. Ivy can select the latest revision of a module
|
||||||
|
according to constraints you specify. Instead of a fixed revision like
|
||||||
|
`"1.6.1"`, you specify `"latest.integration"`, `"2.9.+"`, or
|
||||||
|
`"[1.0,)"`. See the [Ivy revisions] documentation for details.
|
||||||
|
|
||||||
|
### Resolvers
|
||||||
|
|
||||||
|
Not all packages live on the same server; sbt uses the standard Maven2
|
||||||
|
repository and the Scala Tools Releases
|
||||||
|
(<http://scala-tools.org/repo-releases>) repositories by default. If your
|
||||||
|
dependency isn't on one of the default repositories, you'll have to add a
|
||||||
|
_resolver_ to help Ivy find it.
|
||||||
|
|
||||||
|
To add an additional repository, use
|
||||||
|
|
||||||
|
```scala
|
||||||
|
resolvers += name at location
|
||||||
|
```
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
resolvers += "Scala-Tools Maven2 Snapshots Repository" at "http://scala-tools.org/repo-snapshots"
|
||||||
|
```
|
||||||
|
|
||||||
|
The `resolvers` key is defined in [Keys] like this:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
val resolvers = SettingKey[Seq[Resolver]]("resolvers", "The user-defined additional resolvers for automatically managed dependencies.")
|
||||||
|
```
|
||||||
|
|
||||||
|
The `at` method creates a `Resolver` object from two strings.
|
||||||
|
|
||||||
|
sbt can search your local Maven repository if you add it as a repository:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
resolvers += "Local Maven Repository" at "file://"+Path.userHome.absolutePath+"/.m2/repository"
|
||||||
|
```
|
||||||
|
|
||||||
|
See [[Resolvers]] for details on defining other types of repositories.
|
||||||
|
|
||||||
|
### Overriding default resolvers
|
||||||
|
|
||||||
|
`resolvers` does not contain the default resolvers; only additional ones
|
||||||
|
added by your build definition.
|
||||||
|
|
||||||
|
`sbt` combines `resolvers` with some default repositories to form
|
||||||
|
`external-resolvers`.
|
||||||
|
|
||||||
|
Therefore, to change or remove the default resolvers, you would need to
|
||||||
|
override `external-resolvers` instead of `resolvers`.
|
||||||
|
|
||||||
|
### Per-configuration dependencies
|
||||||
|
|
||||||
|
Often a dependency is used by your test code (in `src/test/scala`, which is
|
||||||
|
compiled by the `Test` configuration) but not your main code.
|
||||||
|
|
||||||
|
If you want a dependency to show up in the classpath only for the `Test`
|
||||||
|
configuration and not the `Compile` configuration, add `% "test"` like this:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
libraryDependencies += "org.apache.derby" % "derby" % "10.4.1.3" % "test"
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, if you type `show compile:dependency-classpath` 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 list.
|
||||||
|
|
||||||
|
Typically, test-related dependencies such as [ScalaCheck], [specs], and
|
||||||
|
[ScalaTest] would be defined with `% "test"`.
|
||||||
|
|
||||||
|
# Next
|
||||||
|
|
||||||
|
There are some more details and tips-and-tricks related to library
|
||||||
|
dependencies [[on this page|Library-Management]], if you didn't find an
|
||||||
|
answer on this introductory page.
|
||||||
|
|
||||||
|
If you're reading Getting Started in order, for now, you might move on to
|
||||||
|
read [[Full Build Definition]].
|
||||||
|
|
@ -0,0 +1,407 @@
|
||||||
|
[Keys]: http://harrah.github.com/xsbt/latest/sxr/Keys.scala.html "Keys.scala"
|
||||||
|
[ScopedSetting]: http://harrah.github.com/xsbt/latest/api/sbt/ScopedSetting.html
|
||||||
|
|
||||||
|
# More Kinds of Setting
|
||||||
|
|
||||||
|
This page explains other ways to create a `Setting`, beyond the basic `:=`
|
||||||
|
method. It assumes you've read [[Basic Build Definition]] and [[Scopes]].
|
||||||
|
|
||||||
|
## Refresher: Settings
|
||||||
|
|
||||||
|
[[Remember|Basic Build Definition]], a build definition creates a list of
|
||||||
|
`Setting`, which is then used to transform sbt's description of the build
|
||||||
|
(which is a map of key-value pairs). A `Setting` is a 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. [[Earlier|Basic Build Definition]], 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 setting
|
||||||
|
`name := "hello"` the new map has the string `"hello"` stored under the key
|
||||||
|
`name`.
|
||||||
|
|
||||||
|
Settings must end up in the master list of settings to do any good (all
|
||||||
|
lines in a `build.sbt` automatically end up in the list, but in a
|
||||||
|
[[full build definition|Full Build Definition]] you can get it wrong).
|
||||||
|
|
||||||
|
## Appending to previous values: `+=` and `++=`
|
||||||
|
|
||||||
|
Replacement with `:=` is the simplest transformation, but keys have other
|
||||||
|
methods as well. If the `T` in `Key[T]` is a sequence, i.e. the key's value
|
||||||
|
type is a sequence, you can append to the sequence rather than replacing it.
|
||||||
|
|
||||||
|
- `+=` will append a single element to the sequence.
|
||||||
|
- `++=` will concatenate another sequence.
|
||||||
|
|
||||||
|
For example, the key `sourceDirectories in Compile` has a `Seq[File]` as its
|
||||||
|
value. By default this key's value would include `src/main/scala`.
|
||||||
|
If you wanted to also compile source code in a directory called `source`
|
||||||
|
(since you just have to be nonstandard), you could add that directory:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
sourceDirectories in Compile += new File("source")
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, using the `file()` function from the sbt package for convenience:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
sourceDirectories in Compile += file("source")
|
||||||
|
```
|
||||||
|
|
||||||
|
(`file()` just creates a new `File`.)
|
||||||
|
|
||||||
|
You could use `++=` to add more than one directory at a time:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
sourceDirectories in Compile ++= Seq(file("sources1"), file("sources2"))
|
||||||
|
```
|
||||||
|
|
||||||
|
Where `Seq(a, b, c, ...)` is standard Scala syntax to construct a sequence.
|
||||||
|
|
||||||
|
To replace the default source directories entirely, you use `:=` of
|
||||||
|
course:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
sourceDirectories in Compile := Seq(file("sources1"), file("sources2"))
|
||||||
|
```
|
||||||
|
|
||||||
|
## Transforming a value: `~=`
|
||||||
|
|
||||||
|
What happens if you want to _prepend_ to `sourceDirectories in Compile`, or
|
||||||
|
filter out one of the default directories?
|
||||||
|
|
||||||
|
You can create a `Setting` that depends on the previous value of a key.
|
||||||
|
|
||||||
|
- `~=` applies a function to the setting's previous value, producing a new
|
||||||
|
value of the same type.
|
||||||
|
|
||||||
|
To modify `sourceDirectories in Compile`, you could use `~=` as follows:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
// filter out src/main/scala
|
||||||
|
sourceDirectories in Compile ~= { srcDirs => srcDirs filter(!_.getAbsolutePath.endsWith("src/main/scala")) }
|
||||||
|
```
|
||||||
|
|
||||||
|
Here, `srcDirs` is a parameter to an anonymous function, and the old value
|
||||||
|
of `sourceDirectories in Compile` gets passed in to the anonymous
|
||||||
|
function. The result of this function becomes the new value of
|
||||||
|
`sourceDirectories in Compile`.
|
||||||
|
|
||||||
|
Or a simpler example:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
// make the project name upper case
|
||||||
|
name ~= { _.toUpperCase }
|
||||||
|
```
|
||||||
|
|
||||||
|
The function you pass to the `~=` method will always have type `T => T`, if
|
||||||
|
the key has type `Key[T]`. The function transforms the key's value into another
|
||||||
|
value of the same type.
|
||||||
|
|
||||||
|
## 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?
|
||||||
|
|
||||||
|
- `<<=` 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:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
// useless but valid
|
||||||
|
name <<= name
|
||||||
|
```
|
||||||
|
|
||||||
|
When treated as an `Initialize[T]`, a `Key[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.
|
||||||
|
|
||||||
|
```scala
|
||||||
|
// name our organization after our project (both are Key[String])
|
||||||
|
organization <<= name
|
||||||
|
```
|
||||||
|
|
||||||
|
(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:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
// name is a Key[String], baseDirectory is a Key[File]
|
||||||
|
// name the project after the directory it's inside
|
||||||
|
name <<= baseDirectory.apply(_.getName)
|
||||||
|
```
|
||||||
|
|
||||||
|
`apply` is special in Scala and means you can invoke the object with
|
||||||
|
function syntax; so you could also write this:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
name <<= baseDirectory(_.getName)
|
||||||
|
```
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
### Settings with dependencies
|
||||||
|
|
||||||
|
In the setting `name <<= baseDirectory(_.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):
|
||||||
|
|
||||||
|
```text
|
||||||
|
[info] Dependencies:
|
||||||
|
[info] *:base-directory
|
||||||
|
```
|
||||||
|
|
||||||
|
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 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 inputs to the `compile`
|
||||||
|
computation require sbt to do the `update` computation first.
|
||||||
|
|
||||||
|
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 muliple 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 `Key[T]` are also instances of `Initialize[T]`.
|
||||||
|
|
||||||
|
Here's a simple example, in this case all three keys are strings:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
// a tuple of three Key[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:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
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 any number of
|
||||||
|
simple `Initialize` (such as keys) into one composite `Initialize` by
|
||||||
|
placing them in tuples, and invoking the `apply` method.
|
||||||
|
|
||||||
|
The `<<=` method on `Key[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:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
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:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
name <<= (name, organization, version) { (n, o, v) => "project " + n + " from " + o + " version " + v }
|
||||||
|
```
|
||||||
|
|
||||||
|
Here the tuple of `Initialize` (also a tuple of `Key`) 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 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 in the
|
||||||
|
[[scope|Scopes]] that defines it.
|
||||||
|
|
||||||
|
It's possible to create cycles, which is an error; sbt will tell you if you
|
||||||
|
do this.
|
||||||
|
|
||||||
|
### Tasks with dependencies
|
||||||
|
|
||||||
|
As noted in [[Basic Build Definition]], 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.
|
||||||
|
|
||||||
|
Take these two keys (from [Keys]):
|
||||||
|
|
||||||
|
```scala
|
||||||
|
val scalacOptions = TaskKey[Seq[String]]("scalac-options", "Options for the Scala compiler.")
|
||||||
|
val checksums = SettingKey[Seq[String]]("checksums", "The list of checksums to generate and to verify for dependencies.")
|
||||||
|
```
|
||||||
|
|
||||||
|
(`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:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
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`:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
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 can't
|
||||||
|
depend on a task key. That's because a setting key is cached, 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 you build an `Initialize[Task[T]]` rather than an `Initialize[T]`.
|
||||||
|
Remember the usage of `apply` with a non-task setting looks like this:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
name <<= (name, organization, version) { (n, o, v) => "project " + n + " from " + o + " version " + v }
|
||||||
|
```
|
||||||
|
|
||||||
|
(`(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`:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
// 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 uses `<<=` not `:=`
|
||||||
|
|
||||||
|
If you want one key to be an alias for another, you might be tempted to
|
||||||
|
use `:=` to create the following nonsense alias:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
// 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`):
|
||||||
|
|
||||||
|
```scala
|
||||||
|
// 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 `<++=`
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
For example, say you have a coverage report named after the project, and you
|
||||||
|
want to add it to the files removed by `clean`:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
cleanFiles <+= (name) { n => file("coverage-report-" + n + ".txt") }
|
||||||
|
```
|
||||||
|
|
||||||
|
## Next
|
||||||
|
|
||||||
|
At this point you know how to get things done with settings, so we can move
|
||||||
|
on to a specific key that comes up often: `libraryDependencies`.
|
||||||
|
[[Learn about library dependencies|Library Dependencies]].
|
||||||
|
|
@ -0,0 +1,164 @@
|
||||||
|
# Multi-Project Builds
|
||||||
|
|
||||||
|
This page introduces multiple projects in a single build.
|
||||||
|
|
||||||
|
It's part of a Getting Started series. Please read the earlier pages in the
|
||||||
|
series first, in particular you need to understand
|
||||||
|
[[build.sbt|Basic Build Definition]] and [[Full Build Definition]] before
|
||||||
|
reading this page.
|
||||||
|
|
||||||
|
## Multiple projects
|
||||||
|
|
||||||
|
It can be useful to keep multiple related projects in a single build,
|
||||||
|
especially if they depend on one another and you tend to modify them
|
||||||
|
together.
|
||||||
|
|
||||||
|
Each sub-project in a build has its own `src/main/scala`, generates its own
|
||||||
|
jar file when you run `package`, and in general works like any other
|
||||||
|
project.
|
||||||
|
|
||||||
|
## Defining projects in a `.scala` file
|
||||||
|
|
||||||
|
To have multiple projects, you must declare each project and how they relate
|
||||||
|
in a `.scala` file; there's no way to do it in a `.sbt` file. However, you
|
||||||
|
can define settings for each project in `.sbt` files. Here's an example of a
|
||||||
|
`.scala` file which defines a root project `hello`, where the root project
|
||||||
|
aggregates two sub-projects, `hello-foo` and `hello-bar`:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
import sbt._
|
||||||
|
import Keys._
|
||||||
|
|
||||||
|
object HelloBuild extends Build {
|
||||||
|
lazy val root = Project(id = "hello",
|
||||||
|
base = file(".")) aggregate(foo, bar)
|
||||||
|
|
||||||
|
lazy val foo = Project(id = "hello-foo",
|
||||||
|
base = file("foo"))
|
||||||
|
|
||||||
|
lazy val bar = Project(id = "hello-bar",
|
||||||
|
base = file("bar"))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
sbt finds the list of `Project` objects using reflection, looking for fields
|
||||||
|
with type `Project` in the `Build` object.
|
||||||
|
|
||||||
|
Because project `hello-foo` is defined with `base = file("foo")`, it will be
|
||||||
|
contained in the subdirectory `foo`. Its sources could be directly under
|
||||||
|
`foo`, like `foo/Foo.scala`, or in `foo/src/main/scala`. The usual sbt
|
||||||
|
[[directory structure|Directory Structure]] applies underneath `foo` with
|
||||||
|
the exception of build definition files.
|
||||||
|
|
||||||
|
Any `.sbt` files in `foo`, say `foo/build.sbt`, will be merged with the
|
||||||
|
build definition for the entire build, but scoped to the `hello-foo`
|
||||||
|
project.
|
||||||
|
|
||||||
|
If your whole project is in `hello`, try defining a different version
|
||||||
|
(`version := "0.6"`) in `hello/build.sbt`, `hello/foo/build.sbt`, and
|
||||||
|
`hello/bar/build.sbt`. Now `show version` at the sbt interactive
|
||||||
|
prompt. You should get something like this (with whatever versions you
|
||||||
|
defined):
|
||||||
|
|
||||||
|
```text
|
||||||
|
> show version
|
||||||
|
[info] hello-foo/*:version
|
||||||
|
[info] 0.7
|
||||||
|
[info] hello-bar/*:version
|
||||||
|
[info] 0.9
|
||||||
|
[info] hello/*:version
|
||||||
|
[info] 0.5
|
||||||
|
```
|
||||||
|
|
||||||
|
`hello-foo/*:version` was defined in `hello/foo/build.sbt`,
|
||||||
|
`hello-bar/*:version` was defined in `hello/bar/build.sbt`, and
|
||||||
|
`hello/*:version` was defined in `hello/build.sbt`. Remember the
|
||||||
|
[[syntax for scoped keys|Scopes]]. Each `version` key is scoped to a
|
||||||
|
project, based on the location of the `build.sbt`. But all three `build.sbt`
|
||||||
|
are part of the same build definition.
|
||||||
|
|
||||||
|
_Each project's settings can go in `.sbt` files in the base
|
||||||
|
directory of that project_, while the `.scala` file can be as simple as the
|
||||||
|
one shown above, listing the projects and base directories. _There is no need
|
||||||
|
to put settings in the `.scala` file._
|
||||||
|
|
||||||
|
You cannot have a `project` subdirectory or `project/*.scala` files in the
|
||||||
|
sub-projects. `foo/project/Build.scala` would be ignored.
|
||||||
|
|
||||||
|
## Aggregation
|
||||||
|
|
||||||
|
Projects in the build can be completely independent of one another, if you
|
||||||
|
want.
|
||||||
|
|
||||||
|
In the above example, however, you can see the method call `aggregate(foo, bar)`.
|
||||||
|
This aggregates `hello-foo` and `hello-bar` underneath the root project.
|
||||||
|
|
||||||
|
Aggregation means that running a task on the aggregate project will also run
|
||||||
|
it on the aggregated projects. Start up sbt with two subprojects as in the
|
||||||
|
example, and try `compile`. You should see that all three projects are
|
||||||
|
compiled.
|
||||||
|
|
||||||
|
_In the project doing the aggregating_, the root `hello` project in this
|
||||||
|
case, you can control aggregation per-task. So for example in
|
||||||
|
`hello/build.sbt` you could avoid aggregating the `update` task:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
aggregate in update := false
|
||||||
|
```
|
||||||
|
|
||||||
|
`aggregate in update` is the `aggregate` key scoped to the `update` task,
|
||||||
|
see [[Scopes]].
|
||||||
|
|
||||||
|
Note: aggregation will run the aggregated tasks in parallel and with no defined
|
||||||
|
ordering.
|
||||||
|
|
||||||
|
## Classpath dependencies
|
||||||
|
|
||||||
|
A project may depend on code in another project. This is done by adding a
|
||||||
|
`dependsOn` method call. For example, if `hello-foo` needed the classpath from
|
||||||
|
`hello-bar`, you would write in your `Build.scala`:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
lazy val foo = Project(id = "hello-foo",
|
||||||
|
base = file("foo")) dependsOn(bar)
|
||||||
|
```
|
||||||
|
|
||||||
|
Now code in `hello-foo` can use classes from `hello-bar`. This also creates
|
||||||
|
an ordering between the projects when compiling them; `hello-bar` must be
|
||||||
|
updated and compiled before `hello-foo` can be compiled.
|
||||||
|
|
||||||
|
To depend on multiple projects, use multiple arguments to `dependsOn`, like
|
||||||
|
`dependsOn(bar, baz)`.
|
||||||
|
|
||||||
|
### Per-configuration classpath dependencies
|
||||||
|
|
||||||
|
`foo dependsOn(bar)` means that the `Compile` configuration in `foo` depends
|
||||||
|
on the `Compile` configuration in `bar`. You could write this explicitly as
|
||||||
|
`dependsOn(bar % "compile->compile"`.
|
||||||
|
|
||||||
|
The `->` in `"compile->compile"` means "depends on" so `"test->compile"`
|
||||||
|
means the `Test` configuration in `foo` would depend on the `Compile`
|
||||||
|
configuration in `bar`.
|
||||||
|
|
||||||
|
Omitting the `->config` part implies `->compile`, so `dependsOn(bar %
|
||||||
|
"test")` means that the `Test` configuration in `foo` depends on the
|
||||||
|
`Compile` configuration in `bar`.
|
||||||
|
|
||||||
|
A useful declaration is `"test->test"` which means `Test` depends on
|
||||||
|
`Test`. This allows you to put utility code for testing in
|
||||||
|
`bar/src/test/scala` and then use that code in `foo/src/test/scala`, for
|
||||||
|
example.
|
||||||
|
|
||||||
|
You can have multiple configurations for a dependency, separated by
|
||||||
|
semicolons. For example, `dependsOn(bar % "test->test;compile->compile")`.
|
||||||
|
|
||||||
|
## Navigating projects interactively
|
||||||
|
|
||||||
|
At the sbt interactive prompt, type `projects` to list your projects and
|
||||||
|
`project <projectname>` to select a current project. When you run a task
|
||||||
|
like `compile`, it runs on the current project. So you don't necessarily
|
||||||
|
have to compile the root project, you could compile only a subproject.
|
||||||
|
|
||||||
|
## Next
|
||||||
|
|
||||||
|
Move on to create [[Custom Settings and Tasks]].
|
||||||
|
|
@ -0,0 +1,382 @@
|
||||||
|
# Snippets of docs that need to move to another page
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Temporarily change the logging level and configure how stack traces are displayed by modifying the `log-level` or `trace-level` settings:
|
||||||
|
|
||||||
|
```text
|
||||||
|
> set logLevel := Level.Warn
|
||||||
|
```
|
||||||
|
|
||||||
|
Valid `Level` values are `Debug, Info, Warn, Error`.
|
||||||
|
|
||||||
|
You can run an action for multiple versions of Scala by prefixing the action with `+`. See [[Cross Build]] for details. You can temporarily switch to another version of Scala using `++ <version>`. This version does not have to be listed in your build definition, but it does have to be available in a repository. You can also include the initial command to run after switching to that version. For example:
|
||||||
|
|
||||||
|
```text
|
||||||
|
> ++2.9.1 console-quick
|
||||||
|
...
|
||||||
|
Welcome to Scala version 2.9.1.final (Java HotSpot(TM) Server VM, Java 1.6.0).
|
||||||
|
...
|
||||||
|
scala>
|
||||||
|
...
|
||||||
|
> ++2.8.1 console-quick
|
||||||
|
...
|
||||||
|
Welcome to Scala version 2.8.1 (Java HotSpot(TM) Server VM, Java 1.6.0).
|
||||||
|
...
|
||||||
|
scala>
|
||||||
|
```
|
||||||
|
|
||||||
|
# Tasks
|
||||||
|
|
||||||
|
Some tasks produce useful values. The `toString` representation of these values can be shown using `show <task>` to run the task instead of just `<task>`.
|
||||||
|
In a multi-project build, execution dependencies and the `aggregate` setting control which tasks from which projects are executed. See [[Full Configuration]].
|
||||||
|
|
||||||
|
## Project-level tasks
|
||||||
|
|
||||||
|
* `clean`
|
||||||
|
Deletes all generated files (the `target` directory).
|
||||||
|
* `publish-local`
|
||||||
|
Publishes artifacts (such as jars) to the local Ivy repository as described in [[Publishing]].
|
||||||
|
* `publish`
|
||||||
|
Publishes artifacts (such as jars) to the repository defined by the `publish-to` setting, described in [[Publishing]].
|
||||||
|
* `update`
|
||||||
|
Resolves and retrieves external dependencies as described in [[Library Management]].
|
||||||
|
|
||||||
|
## Configuration-level tasks
|
||||||
|
|
||||||
|
Configuration-level tasks are tasks associated with a configuration. For example, `compile`, which is equivalent to `compile:compile`, compiles the main source code (the `compile` configuration). `test:compile` compiles the test source code (test `test` configuration). Most tasks for the `compile` configuration have an equivalent in the `test` configuration that can be run using a `test:` prefix.
|
||||||
|
|
||||||
|
* `compile`
|
||||||
|
Compiles the main sources (in the `src/main/scala` directory). `test:compile` compiles test sources (in the `src/test/scala/` directory).
|
||||||
|
* `console`
|
||||||
|
Starts the Scala interpreter with a classpath including the compiled sources, all jars in the `lib` directory, and managed 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` 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 build definition on the classpath. The build definition and related values are bound to variables and common packages and values are imported. See [[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`.
|
||||||
|
* `package`
|
||||||
|
Creates a jar file containing the files in `src/main/resources` and the classes compiled from `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 generated from Scala source files in `src/main/scala`.
|
||||||
|
`test:package-doc` 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 and resources. The packaged paths are relative to `src/main/scala` and `src/main/resources`.
|
||||||
|
Similarly, `test:package-src` 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 `argument`s provided. Please see [[Running Project Code]] for 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 for the project in the same virtual machine as `sbt`. The main class is passed the `argument`s provided. Please see [[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`
|
||||||
|
Runs all tests detected during test compilation. See [[Testing]] for details.
|
||||||
|
* `test-only <test>*`
|
||||||
|
Runs the tests provided as arguments. `*` (will be) interpreted as a wildcard in the test name. See [[Testing]] for details.
|
||||||
|
|
||||||
|
## General commands
|
||||||
|
|
||||||
|
* `exit` or `quit`
|
||||||
|
End the current interactive session or build. Additionally, `Ctrl+D` (Unix) or `Ctrl+Z` (Windows) will exit the interactive prompt.
|
||||||
|
* `help <command>`
|
||||||
|
Displays detailed help for the specified command. If no command is provided, displays brief descriptions of all commands.
|
||||||
|
* `projects`
|
||||||
|
List all available projects. (See [[Full Configuration]] for details on multi-project builds.)
|
||||||
|
* `project <project-id>`
|
||||||
|
Change the current project to the project with ID `<project-id>`. Further operations will be done in the context of the given project. (See [[Full Configuration]] for details on multiple project builds.)
|
||||||
|
* `~ <command>`
|
||||||
|
Executes the project specified action or method whenever source files change. See [[Triggered Execution]] for details.
|
||||||
|
* `< filename`
|
||||||
|
Executes the commands in the given file. Each command 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` setting.
|
||||||
|
* `++ <version> <command>`
|
||||||
|
Temporarily changes the version of Scala building the project and executes the provided command. `<command>` is optional. The specified version of Scala is used until the project is reloaded, settings are modified (such as by the `set` or `session` commands), or `++` is run again. `<version>` does not need to be listed in the build definition, but it must be available in a repository.
|
||||||
|
* `; A ; B`
|
||||||
|
Execute A and if it succeeds, run B. Note that the leading semicolon is required.
|
||||||
|
* `eval <Scala-expression>`
|
||||||
|
Evaluates the given Scala expression and returns the result and inferred type. This can be used to set system properties, as a calculator, fork processes, etc ...
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
> eval System.setProperty("demo", "true")
|
||||||
|
> eval 1+1
|
||||||
|
> eval "ls -l" !
|
||||||
|
```
|
||||||
|
|
||||||
|
## Commands for managing the build definition
|
||||||
|
|
||||||
|
* `reload [plugins|return]`
|
||||||
|
If no argument is specified, reloads the build, recompiling any build or plugin definitions as necessary.
|
||||||
|
`reload plugins` changes the current project to the build definition project (in `project/`). This can be useful to directly manipulate the build definition. For example, running `clean` on the build definition project will force snapshots to be updated and the build definition to be recompiled.
|
||||||
|
`reload return` changes back to the main project.
|
||||||
|
* `set <setting-expression>`
|
||||||
|
Evaluates and applies the given setting definition. The setting applies until sbt is restarted, the build is reloaded, or the setting is overridden by another `set` command or removed by the `session` command. See [[Basic Configuration]] and [[Inspecting Settings]] for details.
|
||||||
|
* `session <command>`
|
||||||
|
Manages session settings defined by the `set` command. See [[Inspecting Settings]] for details.
|
||||||
|
* `inspect <setting-key>`
|
||||||
|
Displays information about settings, such as the value, description, defining scope, dependencies, delegation chain, and related settings. See [[Inspecting Settings]] for details.
|
||||||
|
|
||||||
|
|
||||||
|
## Command Line Options
|
||||||
|
|
||||||
|
System properties can be provided either as JVM options, or as SBT arguments, in both cases as `-Dprop=value`. The following properties influence SBT execution.
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td>_Property_</td>
|
||||||
|
<td>_Values_</td>
|
||||||
|
<td>_Default_</td>
|
||||||
|
<td>_Meaning_</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>`sbt.log.noformat`</td>
|
||||||
|
<td>Boolean</td>
|
||||||
|
<td>false</td>
|
||||||
|
<td>If true, disable ANSI color codes. Useful on build servers or terminals that don't support color.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>`sbt.global.base`</td>
|
||||||
|
<td>Directory</td>
|
||||||
|
<td>`~/.sbt`</td>
|
||||||
|
<td>The directory containing global settings and plugins</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>`sbt.ivy.home`</td>
|
||||||
|
<td>Directory</td>
|
||||||
|
<td>`~/.ivy2`</td>
|
||||||
|
<td>The directory containing the local Ivy repository and artifact cache</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Manual Dependency Management
|
||||||
|
|
||||||
|
Manually managing dependencies involves copying any jars that you want to use to the `lib` directory. sbt will put these jars on the classpath during compilation, testing, running, and when using the interpreter. You are responsible for adding, removing, updating, and otherwise managing the jars in this directory. No modifications to your 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 use `custom_lib/`:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
unmanagedBase <<= baseDirectory { base => base / "custom_lib" }
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want more control and flexibility, override the `unmanaged-jars` task, which ultimately provides the manual dependencies to sbt. The default implementation is roughly:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
unmanagedJars in Compile <<= baseDirectory map { base => (base ** "*.jar").classpath }
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to add jars from multiple directories in addition to the default directory, you can do:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
unmanagedJars in Compile <++= baseDirectory map { base =>
|
||||||
|
val baseDirectories = (base / "libA") +++ (base / "b" / "lib") +++ (base / "libC")
|
||||||
|
val customJars = (baseDirectories ** "*.jar") +++ (base / "d" / "my.jar")
|
||||||
|
customJars.classpath
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See [[Paths]] for more information on building up paths.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Resolver.withDefaultResolvers method
|
||||||
|
|
||||||
|
To use the local and Maven Central repositories, but not the Scala Tools releases repository:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
externalResolvers <<= resolvers map { rs =>
|
||||||
|
Resolver.withDefaultResolvers(rs, mavenCentral = true, scalaTools = false)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Explicit URL
|
||||||
|
|
||||||
|
If your project requires a dependency that is not present in a repository, a
|
||||||
|
direct URL to its jar can be specified with the `from` method as follows:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
libraryDependencies += "slinky" % "slinky" % "2.1" from "http://slinky2.googlecode.com/svn/artifacts/2.1/slinky.jar"
|
||||||
|
```
|
||||||
|
|
||||||
|
The URL is only used as a fallback if the dependency cannot be found through
|
||||||
|
the configured repositories. Also, when you publish a project, a pom or
|
||||||
|
ivy.xml is created listing your dependencies; the explicit URL is not
|
||||||
|
included in this published metadata.
|
||||||
|
|
||||||
|
### Disable Transitivity
|
||||||
|
|
||||||
|
By default, sbt fetches all dependencies, transitively. (That is, it downloads
|
||||||
|
the dependencies of the dependencies you list.)
|
||||||
|
|
||||||
|
In some instances, you may find that the dependencies listed for a project
|
||||||
|
aren't necessary for it to build. Avoid fetching artifact dependencies with
|
||||||
|
`intransitive()`, as in this example:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
libraryDependencies += "org.apache.felix" % "org.apache.felix.framework" % "1.8.0" intransitive()
|
||||||
|
```
|
||||||
|
|
||||||
|
### Classifiers
|
||||||
|
|
||||||
|
You can specify the classifer for a dependency using the `classifier` method. For example, to get the jdk15 version of TestNG:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
libraryDependencies += "org.testng" % "testng" % "5.7" classifier "jdk15"
|
||||||
|
```
|
||||||
|
|
||||||
|
To obtain particular classifiers for all dependencies transitively, run the `update-classifiers` task. By default, this resolves all artifacts with the `sources` or `javadoc` classifer. Select the classifiers to obtain by configuring the `transitive-classifiers` setting. For example, to only retrieve sources:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
transitiveClassifiers := Seq("sources")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Extra Attributes
|
||||||
|
|
||||||
|
[Extra attributes] can be specified by passing key/value pairs to the `extra` method.
|
||||||
|
|
||||||
|
To select dependencies by extra attributes:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
libraryDependencies += "org" % "name" % "rev" extra("color" -> "blue")
|
||||||
|
```
|
||||||
|
|
||||||
|
To define extra attributes on the current project:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
projectID <<= projectID { id =>
|
||||||
|
id extra("color" -> "blue", "component" -> "compiler-interface")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Inline Ivy XML
|
||||||
|
|
||||||
|
sbt additionally supports directly specifying the configurations or dependencies sections of an Ivy configuration file inline. You can mix this with inline Scala dependency and repository declarations.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
ivyXML :=
|
||||||
|
<dependencies>
|
||||||
|
<dependency org="javax.mail" name="mail" rev="1.4.2">
|
||||||
|
<exclude module="activation"/>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ivy Home Directory
|
||||||
|
|
||||||
|
By default, sbt uses the standard Ivy home directory location `${user.home}/.ivy2/`.
|
||||||
|
This can be configured machine-wide, for use by both the sbt launcher and by projects, by setting the system property `sbt.ivy.home` in the sbt startup script (described in [[Setup]]).
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```text
|
||||||
|
java -Dsbt.ivy.home=/tmp/.ivy2/ ...
|
||||||
|
```
|
||||||
|
|
||||||
|
### Checksums
|
||||||
|
|
||||||
|
sbt ([through Ivy]) verifies the checksums of downloaded files by default. It also publishes checksums of artifacts by default. The checksums to use are specified by the _checksums_ setting.
|
||||||
|
|
||||||
|
To disable checksum checking during update:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
checksums in update := Nil
|
||||||
|
```
|
||||||
|
|
||||||
|
To disable checksum creation during artifact publishing:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
checksums in publishLocal := Nil
|
||||||
|
|
||||||
|
checksums in publish := Nil
|
||||||
|
```
|
||||||
|
|
||||||
|
The default value is:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
checksums := Seq("sha1", "md5")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Publishing
|
||||||
|
|
||||||
|
Finally, see [[Publishing]] for how to publish your project.
|
||||||
|
|
||||||
|
## Maven/Ivy
|
||||||
|
|
||||||
|
For this method, create the configuration files as you would for Maven (`pom.xml`) or Ivy (`ivy.xml` and optionally `ivysettings.xml`).
|
||||||
|
External configuration is selected by using one of the following expressions.
|
||||||
|
|
||||||
|
### Ivy settings (resolver configuration)
|
||||||
|
|
||||||
|
```scala
|
||||||
|
externalIvySettings()
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
```scala
|
||||||
|
externalIvySettings(baseDirectory(_ / "custom-settings-name.xml"))
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ivy file (dependency configuration)
|
||||||
|
|
||||||
|
```scala
|
||||||
|
externalIvyFile()
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
```scala
|
||||||
|
externalIvyFile(baseDirectory(_ / "custom-name.xml"))
|
||||||
|
```
|
||||||
|
|
||||||
|
Because Ivy files specify their own configurations, sbt needs to know which configurations to use for the compile, runtime, and test classpaths. For example, to specify that the Compile classpath should use the 'default' configuration:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
classpathConfiguration in Compile := config("default")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Maven pom (dependencies only)
|
||||||
|
|
||||||
|
```scala
|
||||||
|
externalPom()
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
```scala
|
||||||
|
externalPom(baseDirectory(_ / "custom-name.xml"))
|
||||||
|
```
|
||||||
|
|
||||||
|
### Full Ivy Example
|
||||||
|
|
||||||
|
For example, a `build.sbt` using external Ivy files might look like:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
externalIvySettings()
|
||||||
|
|
||||||
|
externalIvyFile( baseDirectory { base => base / "ivyA.xml"} )
|
||||||
|
|
||||||
|
classpathConfiguration in Compile := Compile
|
||||||
|
|
||||||
|
classpathConfiguration in Test := Test
|
||||||
|
|
||||||
|
classpathConfiguration in Runtime := Runtime
|
||||||
|
```
|
||||||
|
|
||||||
|
### Known limitations
|
||||||
|
|
||||||
|
Maven support is dependent on Ivy's support for Maven POMs.
|
||||||
|
Known issues with this support:
|
||||||
|
|
||||||
|
* Specifying `relativePath` in the `parent` section of a POM will produce an error.
|
||||||
|
* Ivy ignores repositories specified in the POM. A workaround is to specify repositories inline or in an Ivy `ivysettings.xml` file.
|
||||||
204
Running.md
204
Running.md
|
|
@ -1,147 +1,93 @@
|
||||||
# Running
|
# Running
|
||||||
|
|
||||||
This page describes how to use `sbt` once you have set up your project (see [[Setup]]).
|
This page describes how to use `sbt` once you have set up your project. It
|
||||||
|
assumes you've [[installed sbt|Setup]] and created a [[Hello, World|Hello World]] or other project.
|
||||||
|
|
||||||
Run sbt in your project directory. If you have created a script to start sbt, this should be as simple as:
|
## Interactive mode
|
||||||
|
|
||||||
```
|
Run sbt in your project directory with no arguments:
|
||||||
|
|
||||||
|
```text
|
||||||
$ sbt
|
$ sbt
|
||||||
```
|
```
|
||||||
|
|
||||||
This starts sbt in interactive mode. You are given a prompt at which you type commands. Tab completion and history are available at this prompt.
|
Running sbt with no command line arguments starts it in interactive mode.
|
||||||
|
Interactive mode has a command prompt (with tab completion and
|
||||||
|
history!).
|
||||||
|
|
||||||
Alternatively, you can run sbt in batch mode. You specify a space-separated list of actions as arguments. For commands that take arguments, pass the command and arguments as one argument to `sbt` by enclosing them in quotes. For example,
|
For example, you could type `compile` at the sbt prompt:
|
||||||
|
|
||||||
|
```text
|
||||||
|
> compile
|
||||||
|
```
|
||||||
|
|
||||||
|
To `compile` again, press up arrow and then enter.
|
||||||
|
|
||||||
|
To run your program, type `run`.
|
||||||
|
|
||||||
|
To leave interactive mode, type `exit` or use Ctrl+D (Unix) or Ctrl+Z (Windows).
|
||||||
|
|
||||||
|
## Batch mode
|
||||||
|
|
||||||
|
You can also run sbt in batch mode, specifying a space-separated list of
|
||||||
|
sbt actions as arguments. For sbt commands that take arguments, pass the command and arguments as one argument to `sbt` by enclosing them in quotes. For example,
|
||||||
|
|
||||||
```text
|
```text
|
||||||
$ sbt clean compile "test-only TestA TestB"
|
$ sbt clean compile "test-only TestA TestB"
|
||||||
```
|
```
|
||||||
|
|
||||||
You can make an action run when one or more source files change by prefixing the action with `~`. For example:
|
In this example, `test-only` has arguments, `TestA` and `TestB`. The actions will be
|
||||||
|
run in sequence (`clean`, `compile`, then `test-only`).
|
||||||
|
|
||||||
|
## Continuous build and test
|
||||||
|
|
||||||
|
To speed up your edit-compile-test cycle, you can ask sbt to automatically
|
||||||
|
recompile or run tests whenever you save a source file.
|
||||||
|
|
||||||
|
Make an action run when one or more source files change by prefixing the
|
||||||
|
action with `~`. For example, in interactive mode try:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
> ~ compile
|
> ~ compile
|
||||||
```
|
```
|
||||||
|
|
||||||
See [[Triggered Execution]] for details.
|
Press enter to stop watching for changes.
|
||||||
|
|
||||||
Temporarily change the logging level and configure how stack traces are displayed by modifying the `log-level` or `trace-level` settings:
|
You can use the `~` prefix with either interactive mode or batch mode.
|
||||||
|
|
||||||
```text
|
See [[Triggered Execution]] for more details.
|
||||||
> set logLevel := Level.Warn
|
|
||||||
```
|
|
||||||
|
|
||||||
Valid `Level` values are `Debug, Info, Warn, Error`.
|
## Common actions
|
||||||
|
|
||||||
You can run an action for multiple versions of Scala by prefixing the action with `+`. See [[Cross Build]] for details. You can temporarily switch to another version of Scala using `++ <version>`. This version does not have to be listed in your build definition, but it does have to be available in a repository. You can also include the initial command to run after switching to that version. For example:
|
Here are some of the most common sbt commands. For a more complete list, see [[FIXME]].
|
||||||
|
|
||||||
```text
|
|
||||||
> ++2.9.1 console-quick
|
|
||||||
...
|
|
||||||
Welcome to Scala version 2.9.1.final (Java HotSpot(TM) Server VM, Java 1.6.0).
|
|
||||||
...
|
|
||||||
scala>
|
|
||||||
...
|
|
||||||
> ++2.8.1 console-quick
|
|
||||||
...
|
|
||||||
Welcome to Scala version 2.8.1 (Java HotSpot(TM) Server VM, Java 1.6.0).
|
|
||||||
...
|
|
||||||
scala>
|
|
||||||
```
|
|
||||||
|
|
||||||
# Tasks
|
|
||||||
|
|
||||||
Some tasks produce useful values. The `toString` representation of these values can be shown using `show <task>` to run the task instead of just `<task>`.
|
|
||||||
In a multi-project build, execution dependencies and the `aggregate` setting control which tasks from which projects are executed. See [[Full Configuration]].
|
|
||||||
|
|
||||||
## Project-level tasks
|
|
||||||
|
|
||||||
* `clean`
|
* `clean`
|
||||||
Deletes all generated files (the `target` directory).
|
Deletes all generated files (the `target` directory).
|
||||||
* `publish-local`
|
|
||||||
Publishes artifacts (such as jars) to the local Ivy repository as described in [[Publishing]].
|
|
||||||
* `publish`
|
|
||||||
Publishes artifacts (such as jars) to the repository defined by the `publish-to` setting, described in [[Publishing]].
|
|
||||||
* `update`
|
|
||||||
Resolves and retrieves external dependencies as described in [[Library Management]].
|
|
||||||
|
|
||||||
## Configuration-level tasks
|
|
||||||
|
|
||||||
Configuration-level tasks are tasks associated with a configuration. For example, `compile`, which is equivalent to `compile:compile`, compiles the main source code (the `compile` configuration). `test:compile` compiles the test source code (test `test` configuration). Most tasks for the `compile` configuration have an equivalent in the `test` configuration that can be run using a `test:` prefix.
|
|
||||||
|
|
||||||
* `compile`
|
* `compile`
|
||||||
Compiles the main sources (in the `src/main/scala` directory). `test:compile` compiles test sources (in the `src/test/scala/` directory).
|
Compiles the main sources (in the `src/main/scala` directory).
|
||||||
|
* `test`
|
||||||
|
Compiles and runs all tests.
|
||||||
* `console`
|
* `console`
|
||||||
Starts the Scala interpreter with a classpath including the compiled sources, all jars in the `lib` directory, and managed 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.
|
Starts the Scala interpreter with a classpath including the compiled
|
||||||
* `console-quick`
|
sources and all dependencies. To return to sbt, type `:quit`, Ctrl+D
|
||||||
Starts the Scala interpreter with the project's compile-time dependencies on the classpath. `test:console-quick` uses the test dependencies. This task differs from `console` in that it does not force compilation of the current project's sources.
|
(Unix), or Ctrl+Z (Windows).
|
||||||
* `console-project`
|
* `run <argument>*`
|
||||||
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 [[Console Project]] for more information.
|
Runs the main class for the project in the same virtual machine as `sbt`.
|
||||||
* `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`.
|
|
||||||
* `package`
|
* `package`
|
||||||
Creates a jar file containing the files in `src/main/resources` and the classes compiled from `src/main/scala`.
|
Creates a jar file containing the files in `src/main/resources` and the classes compiled from `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 generated from Scala source files in `src/main/scala`.
|
|
||||||
`test:package-doc` 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 and resources. The packaged paths are relative to `src/main/scala` and `src/main/resources`.
|
|
||||||
Similarly, `test:package-src` 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 `argument`s provided. Please see [[Running Project Code]] for 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 for the project in the same virtual machine as `sbt`. The main class is passed the `argument`s provided. Please see [[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`
|
|
||||||
Runs all tests detected during test compilation. See [[Testing]] for details.
|
|
||||||
* `test-only <test>*`
|
|
||||||
Runs the tests provided as arguments. `*` (will be) interpreted as a wildcard in the test name. See [[Testing]] for details.
|
|
||||||
|
|
||||||
## General commands
|
|
||||||
|
|
||||||
* `exit` or `quit`
|
|
||||||
End the current interactive session or build. Additionally, `Ctrl+D` (Unix) or `Ctrl+Z` (Windows) will exit the interactive prompt.
|
|
||||||
* `help <command>`
|
* `help <command>`
|
||||||
Displays detailed help for the specified command. If no command is provided, displays brief descriptions of all commands.
|
Displays detailed help for the specified command. If no command is
|
||||||
* `projects`
|
provided, displays brief descriptions of all commands.
|
||||||
List all available projects. (See [[Full Configuration]] for details on multi-project builds.)
|
* `reload`
|
||||||
* `project <project-id>`
|
Reloads the build definition (`build.sbt`, `project/*.scala`,
|
||||||
Change the current project to the project with ID `<project-id>`. Further operations will be done in the context of the given project. (See [[Full Configuration]] for details on multiple project builds.)
|
`project/*.sbt` files). Needed if you change the build definition.
|
||||||
* `~ <command>`
|
|
||||||
Executes the project specified action or method whenever source files change. See [[Triggered Execution]] for details.
|
|
||||||
* `< filename`
|
|
||||||
Executes the commands in the given file. Each command 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` setting.
|
|
||||||
* `++ <version> <command>`
|
|
||||||
Temporarily changes the version of Scala building the project and executes the provided command. `<command>` is optional. The specified version of Scala is used until the project is reloaded, settings are modified (such as by the `set` or `session` commands), or `++` is run again. `<version>` does not need to be listed in the build definition, but it must be available in a repository.
|
|
||||||
* `; A ; B`
|
|
||||||
Execute A and if it succeeds, run B. Note that the leading semicolon is required.
|
|
||||||
* `eval <Scala-expression>`
|
|
||||||
Evaluates the given Scala expression and returns the result and inferred type. This can be used to set system properties, as a calculator, fork processes, etc ...
|
|
||||||
For example:
|
|
||||||
|
|
||||||
```scala
|
|
||||||
> eval System.setProperty("demo", "true")
|
|
||||||
> eval 1+1
|
|
||||||
> eval "ls -l" !
|
|
||||||
```
|
|
||||||
|
|
||||||
## Commands for managing the build definition
|
|
||||||
|
|
||||||
* `reload [plugins|return]`
|
|
||||||
If no argument is specified, reloads the build, recompiling any build or plugin definitions as necessary.
|
|
||||||
`reload plugins` changes the current project to the build definition project (in `project/`). This can be useful to directly manipulate the build definition. For example, running `clean` on the build definition project will force snapshots to be updated and the build definition to be recompiled.
|
|
||||||
`reload return` changes back to the main project.
|
|
||||||
* `set <setting-expression>`
|
|
||||||
Evaluates and applies the given setting definition. The setting applies until sbt is restarted, the build is reloaded, or the setting is overridden by another `set` command or removed by the `session` command. See [[Basic Configuration]] and [[Inspecting Settings]] for details.
|
|
||||||
* `session <command>`
|
|
||||||
Manages session settings defined by the `set` command. See [[Inspecting Settings]] for details.
|
|
||||||
* `inspect <setting-key>`
|
|
||||||
Displays information about settings, such as the value, description, defining scope, dependencies, delegation chain, and related settings. See [[Inspecting Settings]] for details.
|
|
||||||
|
|
||||||
## History Commands
|
## History Commands
|
||||||
|
|
||||||
|
Interactive mode remembers history, even if you exit sbt and restart it.
|
||||||
|
The simplest way to access history is with the up arrow key. The following
|
||||||
|
commands are also supported:
|
||||||
|
|
||||||
* `!`
|
* `!`
|
||||||
Show history command help.
|
Show history command help.
|
||||||
* `!!`
|
* `!!`
|
||||||
|
|
@ -159,36 +105,6 @@ Configuration-level tasks are tasks associated with a configuration. For exampl
|
||||||
* `!?string`
|
* `!?string`
|
||||||
Execute the most recent command containing 'string'
|
Execute the most recent command containing 'string'
|
||||||
|
|
||||||
## Command Line Options
|
## Next
|
||||||
|
|
||||||
System properties can be provided either as JVM options, or as SBT arguments, in both cases as `-Dprop=value`. The following properties influence SBT execution.
|
Move on to [[understanding build.sbt|Basic Build Definition]].
|
||||||
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<td>_Property_</td>
|
|
||||||
<td>_Values_</td>
|
|
||||||
<td>_Default_</td>
|
|
||||||
<td>_Meaning_</td>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>`sbt.log.noformat`</td>
|
|
||||||
<td>Boolean</td>
|
|
||||||
<td>false</td>
|
|
||||||
<td>If true, disable ANSI color codes. Useful on build servers or terminals that don't support color.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>`sbt.global.base`</td>
|
|
||||||
<td>Directory</td>
|
|
||||||
<td>`~/.sbt`</td>
|
|
||||||
<td>The directory containing global settings and plugins</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>`sbt.ivy.home`</td>
|
|
||||||
<td>Directory</td>
|
|
||||||
<td>`~/.ivy2`</td>
|
|
||||||
<td>The directory containing the local Ivy repository and artifact cache</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,320 @@
|
||||||
|
[MavenScopes]:
|
||||||
|
http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Scope
|
||||||
|
"Maven scopes"
|
||||||
|
|
||||||
|
# Scopes
|
||||||
|
|
||||||
|
This page describes scopes. It assumes you've read and understood the
|
||||||
|
previous page, [[Basic Build Definition]].
|
||||||
|
|
||||||
|
## The whole story about keys
|
||||||
|
|
||||||
|
[[Previously|Basic Build Definition]] we pretended that a key like `name`
|
||||||
|
corresponded to one entry in sbt's map of key-value pairs. This was a
|
||||||
|
simplification.
|
||||||
|
|
||||||
|
In truth, each key can have an associated value in more than one context,
|
||||||
|
called a "scope."
|
||||||
|
|
||||||
|
Some concrete examples:
|
||||||
|
|
||||||
|
- if you have multiple projects in your build definition, a key can 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
|
||||||
|
packages) may have different values when packaging class files
|
||||||
|
(`package-bin`) or packaging source code (`package-src`).
|
||||||
|
|
||||||
|
_There is no single value for a given key name_, because the value may differ
|
||||||
|
according to scope.
|
||||||
|
|
||||||
|
However, there is a single value for a given _scoped_ key.
|
||||||
|
|
||||||
|
If you think about sbt processing a list of settings to generate a key-value
|
||||||
|
map describing the project, as [[discussed earlier|Basic Build Definition]],
|
||||||
|
the keys in that key-value map are _scoped_ keys. Each setting defined in
|
||||||
|
the build definition (for example in `build.sbt`) applies to a scoped key as
|
||||||
|
well.
|
||||||
|
|
||||||
|
Often the scope is implied or has a default, but if the defaults are wrong,
|
||||||
|
you'll need to mention the desired scope in `build.sbt`.
|
||||||
|
|
||||||
|
## Scope axes
|
||||||
|
|
||||||
|
A _scope axis_ is a type, where each instance of the type can define its own
|
||||||
|
scope (that is, each instance can have its own unique values for keys).
|
||||||
|
|
||||||
|
There are three scope axes:
|
||||||
|
|
||||||
|
- Projects
|
||||||
|
- Configurations
|
||||||
|
- Tasks
|
||||||
|
|
||||||
|
### Scoping by project axis
|
||||||
|
|
||||||
|
If you [[put multiple projects in a single build|Multi-Project Builds]], each
|
||||||
|
project needs its own settings. That is, keys can be scoped according to the
|
||||||
|
project.
|
||||||
|
|
||||||
|
The project axis can also be set to "entire build", so a setting applies to
|
||||||
|
the entire build rather than a single project. Build-level settings are
|
||||||
|
often used as a fallback when a project doesn't define a project-specific
|
||||||
|
setting.
|
||||||
|
|
||||||
|
### Scoping by configuration axis
|
||||||
|
|
||||||
|
A _configuration_ defines a flavor of build, potentially with its own
|
||||||
|
classpath, sources, generated packages, etc. The configuration concept comes
|
||||||
|
from Ivy, which sbt uses for [[managed dependencies|Library Dependencies]], and
|
||||||
|
from [MavenScopes].
|
||||||
|
|
||||||
|
Some configurations you'll see in sbt:
|
||||||
|
|
||||||
|
- `Compile` which defines the main build (`src/main/scala`).
|
||||||
|
- `Test` which defines how to build tests (`src/test/scala`).
|
||||||
|
- `Runtime` which defines the classpath for the `run` task.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
### Scoping by task axis
|
||||||
|
|
||||||
|
Settings can affect how a task works. For example, the `package-src` task is
|
||||||
|
affected by the `package-options` setting.
|
||||||
|
|
||||||
|
To support this, a task key (such as `package-src`) can be a scope for
|
||||||
|
another key (such as `package-options`).
|
||||||
|
|
||||||
|
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 distinct values for each
|
||||||
|
packaging task.
|
||||||
|
|
||||||
|
## Global scope
|
||||||
|
|
||||||
|
Each scope axis can be filled in with an instance of the axis type (for
|
||||||
|
example the task axis can be filled in with a task), or the axis can be
|
||||||
|
filled in with the special value `Global`.
|
||||||
|
|
||||||
|
`Global` means what you would expect: the setting's value applies to all
|
||||||
|
instances of that axis. For example if the task axis is `Global`, then the
|
||||||
|
setting would apply to all tasks.
|
||||||
|
|
||||||
|
## Delegation
|
||||||
|
|
||||||
|
A scoped key may be undefined, if it has no value associated with it in its scope.
|
||||||
|
|
||||||
|
For each scope, sbt has a fallback search path made up of other scopes.
|
||||||
|
Typically, if a key has no associated value in a more-specific scope, sbt
|
||||||
|
will try to get a value from a more general scope, such as the `Global`
|
||||||
|
scope or the entire-build scope.
|
||||||
|
|
||||||
|
This feature allows you to set a value once in a more general scope,
|
||||||
|
allowing multiple more-specific scopes to inherit the value.
|
||||||
|
|
||||||
|
You can see the fallback search path or "delegates" for a key using the
|
||||||
|
`inspect` command, as described below. Read on.
|
||||||
|
|
||||||
|
## Referring to scoped keys when running sbt
|
||||||
|
|
||||||
|
On the command line and in interactive mode, sbt displays (and parses)
|
||||||
|
scoped keys like this:
|
||||||
|
|
||||||
|
```text
|
||||||
|
{<build-uri>}<project-id>/config:key(for task-key)
|
||||||
|
```
|
||||||
|
|
||||||
|
- `{<build-uri>}<project-id>` identifies the project axis. The <project-id>
|
||||||
|
part will be missing if the project axis has "entire build" scope.
|
||||||
|
- `config` identifies the configuration axis.
|
||||||
|
- `(for task-key)` identifies the task axis.
|
||||||
|
- `key` identifies the key being scoped.
|
||||||
|
|
||||||
|
`*` can appear for each axis, referring to the `Global` scope.
|
||||||
|
|
||||||
|
If you omit part of the scoped key, it will be inferred as follows:
|
||||||
|
|
||||||
|
- the current project will be used if you omit the project.
|
||||||
|
- a key-dependent configuration will be auto-detected if you omit the
|
||||||
|
configuration.
|
||||||
|
- the `Global` task scope will be used if you omit the task.
|
||||||
|
|
||||||
|
For more details, see [[Inspecting Settings]].
|
||||||
|
|
||||||
|
## Inspecting scopes
|
||||||
|
|
||||||
|
In sbt's interactive mode, you can use the `inspect` command to understand
|
||||||
|
keys and their scopes. Try `inspect test:full-classpath`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
$ sbt
|
||||||
|
> inspect test:full-classpath
|
||||||
|
[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] Dependencies:
|
||||||
|
[info] test:exported-products
|
||||||
|
[info] test:dependency-classpath
|
||||||
|
[info] Reverse dependencies:
|
||||||
|
[info] test:run-main
|
||||||
|
[info] test:run
|
||||||
|
[info] test:test-loader
|
||||||
|
[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] Related:
|
||||||
|
[info] compile:full-classpath
|
||||||
|
[info] compile:full-classpath(for doc)
|
||||||
|
[info] test:full-classpath(for doc)
|
||||||
|
[info] runtime:full-classpath
|
||||||
|
```
|
||||||
|
|
||||||
|
On the first line, you can see this is a task (as opposed to a setting, as
|
||||||
|
explained in [[Basic Build Definition]]). The value resulting from the task
|
||||||
|
will have type `scala.collection.Seq[sbt.Attributed[java.io.File]]`.
|
||||||
|
|
||||||
|
"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` configuration and the
|
||||||
|
`{file:/home/hp/checkout/hello/}default-aea33a` project).
|
||||||
|
|
||||||
|
"Dependencies" may not make sense yet; stay tuned for the
|
||||||
|
[[next section|More About Settings]].
|
||||||
|
|
||||||
|
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 unspecified meaning "current
|
||||||
|
project" and the task is unspecified meaning `Global`
|
||||||
|
- configuration set to `Global` (`*:full-classpath`), 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,
|
||||||
|
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`)
|
||||||
|
- both project and configuration set to `Global` (`*/*:full-classpath`)
|
||||||
|
(remember that unspecified task means `Global` already, so
|
||||||
|
`*/*:full-classpath` 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. Because the
|
||||||
|
configuration is omitted, it is autodetected as `compile`.
|
||||||
|
`inspect compile:full-classpath` should therefore look the same as
|
||||||
|
`inspect full-classpath`.
|
||||||
|
|
||||||
|
Try `inspect *:full-classpath` for another contrast. `full-classpath`
|
||||||
|
is not defined in the `Global` configuration by default.
|
||||||
|
|
||||||
|
Again, for more details, see [[Inspecting Settings]].
|
||||||
|
|
||||||
|
## Referring to scopes in a build definition
|
||||||
|
|
||||||
|
If you create a setting in `build.sbt` with a bare key, it will be scoped to
|
||||||
|
the current project, configuration `Global` and task `Global`:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
name := "hello"
|
||||||
|
```
|
||||||
|
|
||||||
|
Run sbt and `inspect name` to see that it's provided by
|
||||||
|
`{file:/home/hp/checkout/hello/}default-aea33a/*:name`, that is, the project is
|
||||||
|
`{file:/home/hp/checkout/hello/}default-aea33a`, the configuration is `*`
|
||||||
|
(meaning global), and the task is not shown (which also means global).
|
||||||
|
|
||||||
|
`build.sbt` always defines settings for a single project, so the "current
|
||||||
|
project" is the project you're defining in that particular `build.sbt`.
|
||||||
|
(For [[multi-project builds|Multi-Project Builds]], each project has its own
|
||||||
|
`build.sbt`.)
|
||||||
|
|
||||||
|
Keys have an overloaded method called `in` used to set the scope. The
|
||||||
|
argument to `in` can be an instance of any of the scope axes. So for
|
||||||
|
example, though there's no real reason to do this,
|
||||||
|
you could set the name scoped to the `Compile` configuration:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
name in Compile := "hello"
|
||||||
|
```
|
||||||
|
|
||||||
|
or you could set the name scoped to the `package-bin` task (pointless! just
|
||||||
|
an example):
|
||||||
|
|
||||||
|
```scala
|
||||||
|
name in packageBin := "hello"
|
||||||
|
```
|
||||||
|
|
||||||
|
or you could set the name with multiple scope axes, for example in the
|
||||||
|
`packageBin` task in the `Compile` configuration:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
name in (Compile, packageBin) := "hello"
|
||||||
|
```
|
||||||
|
|
||||||
|
or you could use `Global` for all axes:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
name in Global := "hello"
|
||||||
|
```
|
||||||
|
|
||||||
|
(`name in Global` implicitly converts the scope axis `Global` to a scope
|
||||||
|
with all axes set to `Global`; the task and configuration are already
|
||||||
|
`Global` by default, so here the effect is to make the project `Global`,
|
||||||
|
that is, define `*/*:name` rather than `{file:/home/hp/checkout/hello/}default-aea33a/*:name`)
|
||||||
|
|
||||||
|
If you aren't used to Scala, a reminder: it's important to understand that
|
||||||
|
`in` and `:=` are just methods, not magic. Scala lets you write them in a
|
||||||
|
nicer way, but you could also use the Java style:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
name.in(Compile).:=("hello")
|
||||||
|
```
|
||||||
|
|
||||||
|
There's no reason to use this ugly syntax, but it illustrates that these are
|
||||||
|
in fact methods.
|
||||||
|
|
||||||
|
## When to specify a scope
|
||||||
|
|
||||||
|
You need to specify the scope if the key in question is normally scoped.
|
||||||
|
For example, the `compile` task, by default, is scoped to `Compile` and
|
||||||
|
`Test` configurations, and does not exist outside of those scopes.
|
||||||
|
|
||||||
|
To change the value associated with the `compile` key, you need to write
|
||||||
|
`compile in Compile` or `compile in Test`. Using plain `compile` would
|
||||||
|
define a new compile task scoped to the current project, rather than
|
||||||
|
overriding the standard compile tasks which are scoped to a configuration.
|
||||||
|
|
||||||
|
If you get an error like _"Reference to undefined setting"_, often you've
|
||||||
|
failed to specify a scope, or you've specified the wrong scope. The key
|
||||||
|
you're using may be defined in some other scope.
|
||||||
|
|
||||||
|
One way to think of it is that a name is only _part_ of a key. In reality,
|
||||||
|
all keys consist of both a name, and a scope (where the scope has three
|
||||||
|
axes). The entire expression `packageOptions in (Compile, packageBin)` is a
|
||||||
|
key name, in other words. Simply `packageOptions` is also a key name, but a
|
||||||
|
different one (for keys with no `in`, a scope is implicitly assumed: current
|
||||||
|
project, global config, global task).
|
||||||
|
|
||||||
|
## Next
|
||||||
|
|
||||||
|
Now that you understand scopes, you can [[learn more about settings|More About Settings]].
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
[Scope]: http://harrah.github.com/xsbt/latest/api/sbt/Scope$.html
|
[Scope]: http://harrah.github.com/xsbt/latest/api/sbt/Scope$.html
|
||||||
[Initialize]: http://harrah.github.com/xsbt/latest/api/sbt/Init$Initialize.html
|
[Initialize]: http://harrah.github.com/xsbt/latest/api/sbt/Init$Initialize.html
|
||||||
[SettingKey]: http://harrah.github.com/xsbt/latest/api/sbt/SettingKey.html
|
[SettingKey]: http://harrah.github.com/xsbt/latest/api/sbt/SettingKey.html
|
||||||
[Keys]: http://harrah.github.com/xsbt/latest/sxr/Keys.scala.html
|
[Keys]: http://harrah.github.com/xsbt/latest/sxr/Keys.scala.html "Keys.scala"
|
||||||
[InputKey]: http://harrah.github.com/xsbt/latest/api/sbt/InputKey.html
|
[InputKey]: http://harrah.github.com/xsbt/latest/api/sbt/InputKey.html
|
||||||
[TaskKey]: http://harrah.github.com/xsbt/latest/api/sbt/TaskKey.html
|
[TaskKey]: http://harrah.github.com/xsbt/latest/api/sbt/TaskKey.html
|
||||||
[Append]: http://harrah.github.com/xsbt/latest/api/sbt/Append$.html
|
[Append]: http://harrah.github.com/xsbt/latest/api/sbt/Append$.html
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
# Setup Notes
|
||||||
|
|
||||||
|
Some notes on how to set up your `sbt` script.
|
||||||
|
|
||||||
|
## Do not put `sbt-launch.jar` on your classpath.
|
||||||
|
|
||||||
|
Do _not_ put `sbt-launch.jar` in your `$SCALA_HOME/lib` directory, your project's `lib` directory, or anywhere it will be put on a classpath. It isn't a library.
|
||||||
|
|
||||||
|
## Terminal encoding
|
||||||
|
|
||||||
|
The character encoding used by your terminal may differ from Java's default encoding for your platform. In this case, you will need to add the option `-Dfile.encoding=<encoding>` in your `sbt` script to set the encoding, which might look like:
|
||||||
|
|
||||||
|
```text
|
||||||
|
java -Dfile.encoding=UTF8
|
||||||
|
```
|
||||||
|
|
||||||
|
## JVM heap, permgen, and stack sizes
|
||||||
|
|
||||||
|
If you find yourself running out of permgen space or your workstation is low
|
||||||
|
on memory, adjust the JVM configuration as you would for any application. For example
|
||||||
|
a common set of memory-related options is:
|
||||||
|
|
||||||
|
```text
|
||||||
|
java -Xmx1536M -Xss1M -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=256m
|
||||||
|
```
|
||||||
|
## Boot directory
|
||||||
|
|
||||||
|
`sbt-launch.jar` is just a bootstrap; the actual meat of sbt, and the Scala
|
||||||
|
compiler and standard library, are downloaded to a directory `project/boot`
|
||||||
|
in each project.
|
||||||
|
|
||||||
|
To avoid an extra copy of Scala and sbt in every project, you can set up
|
||||||
|
a shared boot directory by adding an option in your `sbt` script, like this:
|
||||||
|
|
||||||
|
```text
|
||||||
|
java -Dsbt.boot.directory=$HOME/.sbt/boot/
|
||||||
|
```
|
||||||
|
|
||||||
|
## HTTP Proxy
|
||||||
|
|
||||||
|
On Unix, sbt will pick up any HTTP proxy settings from the `http.proxy` environment variable. If you are behind a proxy requiring authentication, your `sbt` script must also pass flags to set the `http.proxyUser` and `http.proxyPassword` properties:
|
||||||
|
|
||||||
|
```text
|
||||||
|
java -Dhttp.proxyUser=username -Dhttp.proxyPassword=mypassword
|
||||||
|
```
|
||||||
|
|
||||||
|
On Windows, your script should set properties for proxy host, port, and if applicable, username and password:
|
||||||
|
|
||||||
|
```text
|
||||||
|
java -Dhttp.proxyHost=myproxy -Dhttp.proxyPort=8080 -Dhttp.proxyUser=username -Dhttp.proxyPassword=mypassword
|
||||||
|
```
|
||||||
175
Setup.md
175
Setup.md
|
|
@ -1,61 +1,44 @@
|
||||||
[sbt-launch.jar]: http://typesafe.artifactoryonline.com/typesafe/ivy-releases/org.scala-tools.sbt/sbt-launch/0.11.0/sbt-launch.jar
|
[sbt-launch.jar]: http://typesafe.artifactoryonline.com/typesafe/ivy-releases/org.scala-tools.sbt/sbt-launch/0.11.0/sbt-launch.jar
|
||||||
[ScalaCheck]: http://code.google.com/p/scalacheck/
|
|
||||||
[specs]: http://code.google.com/p/specs/
|
|
||||||
[ScalaTest]: http://www.artima.com/scalatest/
|
|
||||||
[Maven]: http://maven.apache.org/
|
|
||||||
|
|
||||||
# Setup (In Progress)
|
# Setup
|
||||||
|
|
||||||
# Introduction
|
This page is the first in a series of Getting Started pages that will introduce you to sbt.
|
||||||
|
|
||||||
This page describes how to set up your project for use with sbt. The basic steps are:
|
Please go in order! Later pages assume you're familiar with earlier concepts.
|
||||||
|
|
||||||
* Create a script to launch sbt.
|
# Overview
|
||||||
* Create your sources and put jars in `lib/`.
|
|
||||||
* Create your build definition(s).
|
|
||||||
* Read [[Running]] for basic usage instructions.
|
|
||||||
* For configuration instructions, see [[Settings]].
|
|
||||||
|
|
||||||
# Launching Sbt
|
To create an sbt project, you'll need to take these steps:
|
||||||
|
|
||||||
The easiest way to launch sbt is to create a one-line script. Download [sbt-launch.jar] if you have not already.
|
- Install sbt and create a script to launch it.
|
||||||
|
- Setup a simple [[Hello World]] project
|
||||||
|
- Create a project directory with source files in it.
|
||||||
|
- Create your build definition.
|
||||||
|
- Move on to [[Running]] to learn how to run sbt.
|
||||||
|
- Then move on to [[Basic Build Definition]] to learn more about build definitions.
|
||||||
|
|
||||||
**Note**: do _not_ put `sbt-launch.jar` in your `$SCALA_HOME/lib` directory, your project's `lib` directory, or anywhere it will be put on a classpath.
|
# Installing sbt
|
||||||
|
|
||||||
**Note**: The encoding used by your terminal may differ from Java's default encoding for your platform. In this case, you will need to add the option `-Dfile.encoding=<encoding>` in the following scripts to set the encoding.
|
You need two files; [sbt-launch.jar] and a script to run it.
|
||||||
|
|
||||||
**Note**: Adjust the JVM options as necessary, especially heap and permgen sizes.
|
|
||||||
|
|
||||||
A common set of options is:
|
|
||||||
|
|
||||||
```text
|
|
||||||
-Dfile.encoding=UTF8 -Xmx1536M -Xss1M -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=256m
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note**: You can share the `project/boot` directory between all sbt projects on a machine by setting the `sbt.boot.directory` system property to the directory to use. For example, `-Dsbt.boot.directory=$HOME/.sbt/boot/`.
|
|
||||||
|
|
||||||
## Unix
|
## Unix
|
||||||
Put the jar in your `~/bin` directory, put the line:
|
|
||||||
|
Download [sbt-launch.jar] and place it in `~/bin`.
|
||||||
|
|
||||||
|
Create a script to run the jar, by placing this in a file called `sbt` in your `~/bin` directory:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
java -Xmx512M -jar `dirname $0`/sbt-launch.jar "$@"
|
java -Dsbt.boot.directory=$HOME/.sbt/boot/ -Xmx512M -jar `dirname $0`/sbt-launch.jar "$@"
|
||||||
```
|
```
|
||||||
|
|
||||||
in a file called `sbt` in your `~/bin` directory and do:
|
Make the script executable:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
$ chmod u+x ~/bin/sbt
|
$ chmod u+x ~/bin/sbt
|
||||||
```
|
```
|
||||||
|
|
||||||
This allows you to launch sbt in any directory by typing `sbt` at the command prompt.
|
|
||||||
|
|
||||||
`sbt` will pick up any HTTP proxy settings from the `http.proxy` environment variable. If you are behind a proxy requiring authentication, you must in addition pass flags to set the `http.proxyUser` and `http.proxyPassword` properties:
|
|
||||||
|
|
||||||
```text
|
|
||||||
java -Dhttp.proxyUser=username -Dhttp.proxyPassword=mypassword -Xmx512M -jar `dirname $0`/sbt-launch.jar "$@"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Windows
|
## Windows
|
||||||
|
|
||||||
Create a batch file `sbt.bat`:
|
Create a batch file `sbt.bat`:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
|
|
@ -63,120 +46,12 @@ set SCRIPT_DIR=%~dp0
|
||||||
java -Xmx512M -jar "%SCRIPT_DIR%sbt-launch.jar" %*
|
java -Xmx512M -jar "%SCRIPT_DIR%sbt-launch.jar" %*
|
||||||
```
|
```
|
||||||
|
|
||||||
and put the jar in the same directory as the batch file. Put `sbt.bat` on your path so that you can launch `sbt` in any directory by typing `sbt` at the command prompt.
|
and put [sbt-launch.jar] in the same directory as the batch file. Put `sbt.bat` on your path so that you can launch `sbt` in any directory by typing `sbt` at the command prompt.
|
||||||
|
|
||||||
If you are behind a proxy on Windows, add flags to this second line for proxy host, port, and if applicable, username and password:
|
## Tips and Notes
|
||||||
|
|
||||||
```text
|
If you have any trouble running `sbt`, see [[Setup Notes]] on terminal encodings, HTTP proxies, and JVM options.
|
||||||
java -Dhttp.proxyHost=myproxy -Dhttp.proxyPort=8080 -Dhttp.proxyUser=username -Dhttp.proxyPassword=mypassword -Xmx512M -jar "%SCRIPT_DIR%sbt-launch.jar" %*
|
|
||||||
```
|
|
||||||
|
|
||||||
# Run
|
## Next
|
||||||
|
|
||||||
When you run `sbt` and there is no build definition, it assumes default settings:
|
Move on to [[create a simple project|Hello World]].
|
||||||
|
|
||||||
- main Scala sources go in the base directory or in `src/main/scala`
|
|
||||||
- test Scala sources go in `src/test/scala`
|
|
||||||
- unmanaged dependencies (jars) go in `lib/`
|
|
||||||
- the Scala version used to run sbt is used to build the project
|
|
||||||
|
|
||||||
With these defaults, you can run `console` to enter the Scala interpreter, or create an application and run it with `run`. For example:
|
|
||||||
|
|
||||||
```text
|
|
||||||
$ echo 'object Hi { def main(args: Array[String]) = println("Hi!") }' > hw.scala
|
|
||||||
$ sbt
|
|
||||||
...
|
|
||||||
> run
|
|
||||||
...
|
|
||||||
Hi!
|
|
||||||
```
|
|
||||||
|
|
||||||
# Configure Build
|
|
||||||
|
|
||||||
Basic configuration can be done in a `build.sbt` file using Scala code. For example:
|
|
||||||
|
|
||||||
```scala
|
|
||||||
name := "My Project"
|
|
||||||
|
|
||||||
version := "1.0"
|
|
||||||
|
|
||||||
scalaVersion := "2.9.1"
|
|
||||||
|
|
||||||
libraryDependencies += "junit" % "junit" % "4.8" % "test"
|
|
||||||
```
|
|
||||||
|
|
||||||
For details, start with [[Settings]], but see also [[Basic Configuration]], [[Full Configuration]], and [[Quick Configuration Examples]].
|
|
||||||
|
|
||||||
A specific SBT version can be configured in `project/build.properties`. For example:
|
|
||||||
|
|
||||||
```text
|
|
||||||
sbt.version=0.11.0
|
|
||||||
```
|
|
||||||
|
|
||||||
# Directory Layout
|
|
||||||
|
|
||||||
## Sources
|
|
||||||
|
|
||||||
Sbt uses the same directory structure as [Maven] for source files by default (all paths are relative to the project directory):
|
|
||||||
|
|
||||||
```text
|
|
||||||
src/
|
|
||||||
main/
|
|
||||||
resources/
|
|
||||||
<files to include in main jar here>
|
|
||||||
scala/
|
|
||||||
<main Scala sources>
|
|
||||||
java/
|
|
||||||
<main Java sources>
|
|
||||||
test/
|
|
||||||
resources
|
|
||||||
<files to include in test jar here>
|
|
||||||
scala/
|
|
||||||
<test Scala sources>
|
|
||||||
java/
|
|
||||||
<test Java sources>
|
|
||||||
```
|
|
||||||
|
|
||||||
Other directories in `src/` will be ignored. Additionally, all hidden directories will be ignored.
|
|
||||||
|
|
||||||
All manually managed dependencies (jars) go in the `lib` directory by default. Hidden directories will be ignored. If you want to use [ScalaCheck], [specs], or [ScalaTest] for testing, those jars can go in here. Alternatively, you can configure `sbt` to automatically manage your dependencies (see [[Library Management]]).
|
|
||||||
|
|
||||||
## Build Configuration
|
|
||||||
|
|
||||||
Build configuration is done in `.sbt` files, such as `build.sbt`, and/or by `.scala` files in the `project` directory:
|
|
||||||
|
|
||||||
```text
|
|
||||||
build.sbt
|
|
||||||
project/
|
|
||||||
Build.scala
|
|
||||||
boot/
|
|
||||||
```
|
|
||||||
|
|
||||||
The `project/boot` directory is where the versions of Scala and `sbt` used to build the project are downloaded to.
|
|
||||||
|
|
||||||
## Products
|
|
||||||
|
|
||||||
Generated files (compiled classes, packaged jars, managed files, caches, and documentation) will be written to the `target` directory by default.
|
|
||||||
|
|
||||||
## Version Control
|
|
||||||
|
|
||||||
As described in the previous sections, `sbt` creates and uses a couple of directories that you will normally want to exclude from version control:
|
|
||||||
|
|
||||||
```text
|
|
||||||
target/
|
|
||||||
project/boot/
|
|
||||||
```
|
|
||||||
|
|
||||||
The above list is suitable as an initial `.gitignore` file for your project.
|
|
||||||
|
|
||||||
# Next Step
|
|
||||||
|
|
||||||
Read [[Running]] for basic `sbt` usage information.
|
|
||||||
|
|
||||||
# Summary
|
|
||||||
|
|
||||||
* Create a script to launch sbt.
|
|
||||||
* Create your sources and put jars in `lib/`.
|
|
||||||
* Create your build definition(s).
|
|
||||||
* Read [[Running]] for basic usage instructions.
|
|
||||||
* For configuration instructions, start with [[Settings]]. See also [[Basic Configuration]], [[Full Configuration]], and [[Quick Configuration Examples]]
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
# Getting Started Summary
|
||||||
|
|
||||||
|
This page wraps up a series of pages in the Getting Started category.
|
||||||
|
|
||||||
|
To use sbt, there are a small number of concepts you must understand. These
|
||||||
|
have some learning curve, but on the positive side, there isn't much to sbt
|
||||||
|
_except_ these concepts. sbt uses a small core of powerful concepts to do
|
||||||
|
everything it does.
|
||||||
|
|
||||||
|
If you've read the whole Getting Started series, now you know what you need
|
||||||
|
to know.
|
||||||
|
|
||||||
|
## sbt: The Core Concepts
|
||||||
|
|
||||||
|
- the basics of Scala. It's undeniably helpful to be familiar with Scala
|
||||||
|
syntax. [Programming in Scala](http://www.artima.com/shop/programming_in_scala_2ed)
|
||||||
|
written by the creator of Scala is a great introduction.
|
||||||
|
- [[Basic Build Definition]]
|
||||||
|
- 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).
|
||||||
|
- 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.
|
||||||
|
- each setting has a value of a particular type, determined by the key.
|
||||||
|
- _tasks_ are special settings where the computation to produce the key's
|
||||||
|
value will be re-run each time you kick off a task. Non-tasks compute the
|
||||||
|
value once and cache it.
|
||||||
|
- [[Scopes]]
|
||||||
|
- each key may have multiple values, in distinct scopes.
|
||||||
|
- scoping may use three axes: configuration, project, and task.
|
||||||
|
- a configuration is a kind of build, such as the main one (`Compile`) or
|
||||||
|
the test one (`Test`).
|
||||||
|
- scoping allows you to have different behaviors per-project,
|
||||||
|
per-task, or per-configuration.
|
||||||
|
- the per-project axis also supports "entire build" scope.
|
||||||
|
- scopes "fall back to" or delegate to more general scopes.
|
||||||
|
- Basic vs. [[Full Build Definition]]
|
||||||
|
- put most of your settings in basic (`build.sbt`), but use the full
|
||||||
|
build definition to
|
||||||
|
[[define multiple subprojects|Multi-Project Builds]], and to factor out
|
||||||
|
common values, objects, and methods.
|
||||||
|
- the build definition is an sbt project in its own right,
|
||||||
|
rooted in the `project` directory.
|
||||||
|
- [[Plugins|Using Plugins]] are extensions to the build definition
|
||||||
|
- add plugins with the `addSbtPlugin` method in `project/build.sbt` (NOT
|
||||||
|
`build.sbt` in the project's base directory).
|
||||||
|
|
||||||
|
If any of this leaves you wondering rather than nodding, please ask for help
|
||||||
|
on the
|
||||||
|
[mailing list](http://groups.google.com/group/simple-build-tool/topics),
|
||||||
|
go back and re-read, or try some experiments in sbt's interactive mode.
|
||||||
|
|
||||||
|
Good luck!
|
||||||
|
|
||||||
|
## Advanced Notes
|
||||||
|
|
||||||
|
The rest of this wiki consists of deeper dives and less-commonly-needed
|
||||||
|
information.
|
||||||
|
|
||||||
|
Since sbt is open source, don't forget you can check out the source code
|
||||||
|
too!
|
||||||
|
|
@ -2,6 +2,9 @@
|
||||||
[TestReportListener]: http://harrah.github.com/xsbt/latest/api/sbt/TestReportListener.html
|
[TestReportListener]: http://harrah.github.com/xsbt/latest/api/sbt/TestReportListener.html
|
||||||
[TestsListener]: http://harrah.github.com/xsbt/latest/api/sbt/TestsListener.html
|
[TestsListener]: http://harrah.github.com/xsbt/latest/api/sbt/TestsListener.html
|
||||||
[junit-interface]: https://github.com/szeiger/junit-interface
|
[junit-interface]: https://github.com/szeiger/junit-interface
|
||||||
|
[ScalaCheck]: http://code.google.com/p/scalacheck/
|
||||||
|
[specs]: http://code.google.com/p/specs/
|
||||||
|
[ScalaTest]: http://www.artima.com/scalatest/
|
||||||
|
|
||||||
# Testing
|
# Testing
|
||||||
|
|
||||||
|
|
@ -15,7 +18,7 @@ The standard source locations for testing are:
|
||||||
|
|
||||||
The resources may be accessed from tests by using the `getResource` methods of `java.lang.Class` or `java.lang.ClassLoader`.
|
The resources may be accessed from tests by using the `getResource` methods of `java.lang.Class` or `java.lang.ClassLoader`.
|
||||||
|
|
||||||
The main Scala testing frameworks (Specs(2), ScalaCheck, and ScalaTest) provide an implementation of the common test interface and only need to be added to the classpath to work with sbt. For example, ScalaCheck may be used by declaring it as a [[managed dependency|Library Management]]:
|
The main Scala testing frameworks ([specs], [ScalaCheck], and [ScalaTest]) provide an implementation of the common test interface and only need to be added to the classpath to work with sbt. For example, ScalaCheck may be used by declaring it as a [[managed dependency|Library Management]]:
|
||||||
|
|
||||||
```scala
|
```scala
|
||||||
libraryDependencies += "org.scala-tools.testing" %% "scalacheck" % "1.9" % "test"
|
libraryDependencies += "org.scala-tools.testing" %% "scalacheck" % "1.9" % "test"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,232 @@
|
||||||
|
# Using Plugins
|
||||||
|
|
||||||
|
This page is part of a Getting Started series. Please read the earlier pages
|
||||||
|
in the series first, in particular you need to understand
|
||||||
|
[[build.sbt|Basic Build Definition]], [[Library Dependencies]], and
|
||||||
|
[[Full Build Definition]] before reading this page.
|
||||||
|
|
||||||
|
## What is a plugin?
|
||||||
|
|
||||||
|
A plugin extends the build definition, most commonly by adding new
|
||||||
|
settings. The new settings could be new tasks. For example, a plugin could
|
||||||
|
add a `code-coverage` task which would generate a test coverage report.
|
||||||
|
|
||||||
|
## Adding a plugin
|
||||||
|
|
||||||
|
### The short answer
|
||||||
|
|
||||||
|
If your project is in directory `hello`, edit `hello/project/build.sbt` and
|
||||||
|
add the plugin location as a resolver, then call `addSbtPlugin` with the
|
||||||
|
plugin's Ivy module ID:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
resolvers += Classpaths.typesafeResolver
|
||||||
|
|
||||||
|
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse" % "1.4.0")
|
||||||
|
```
|
||||||
|
|
||||||
|
If the plugin were located on one of the default repositories, you wouldn't
|
||||||
|
have to add a resolver, of course.
|
||||||
|
|
||||||
|
So that's how you do it... read on to understand what's going on.
|
||||||
|
|
||||||
|
### How it works
|
||||||
|
|
||||||
|
Be sure you understand the
|
||||||
|
[[recursive nature of sbt projects|Full Build Definition]] described
|
||||||
|
earlier and how to add a [[managed dependency|Library Dependencies]].
|
||||||
|
|
||||||
|
#### Dependencies for the build definition
|
||||||
|
|
||||||
|
Adding a plugin means _adding a library dependency to the build
|
||||||
|
definition_. To do that, you edit the build definition for the build
|
||||||
|
definition.
|
||||||
|
|
||||||
|
Recall that for a project `hello`, its build definition project lives in
|
||||||
|
`hello/*.sbt` and `hello/project/*.scala`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
|
||||||
|
hello/ # your project's base directory
|
||||||
|
|
||||||
|
build.sbt # build.sbt is part of the source code for the
|
||||||
|
# build definition project inside project/
|
||||||
|
|
||||||
|
project/ # base directory of the build definition project
|
||||||
|
|
||||||
|
Build.scala # a source file in the project/ project,
|
||||||
|
# that is, a source file in the build definition
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
If you wanted to add a managed dependency to project `hello`, you would add
|
||||||
|
to the `libraryDependencies` setting either in `hello/*.sbt` or
|
||||||
|
`hello/project/*.scala`.
|
||||||
|
|
||||||
|
You could add this in `hello/build.sbt`:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
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 classpath.
|
||||||
|
|
||||||
|
To add a plugin, do the same thing but recursed one level. We want the
|
||||||
|
_build definition project_ to have a new dependency. That means changing the
|
||||||
|
`libraryDependencies` setting for the build definition of the build
|
||||||
|
definition.
|
||||||
|
|
||||||
|
The build definition of the build definition, if your project is `hello`,
|
||||||
|
would be in `hello/project/*.sbt` and `hello/project/project/*.scala`.
|
||||||
|
|
||||||
|
The simplest "plugin" has no special sbt support; it's just a jar file.
|
||||||
|
For example, edit `hello/project/build.sbt` and add this line:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
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 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 based on it, for example.
|
||||||
|
Remember, use `reload return` to leave the build definition project and go
|
||||||
|
back to the parent project.
|
||||||
|
|
||||||
|
(Stupid sbt trick: type `reload plugins` over and over. You'll find yourself
|
||||||
|
in the project rooted in
|
||||||
|
`project/project/project/project/project/project/`. Don't worry, it isn't
|
||||||
|
useful. Also, it creates `target` directories all the way down, which you'll
|
||||||
|
have to clean up.)
|
||||||
|
|
||||||
|
#### `addSbtPlugin`
|
||||||
|
|
||||||
|
`addSbtPlugin` is just a convenience method. Here's its definition:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
def addSbtPlugin(dependency: ModuleID): Setting[Seq[ModuleID]] =
|
||||||
|
libraryDependencies <+= (sbtVersion in update,scalaVersion) { (sbtV, scalaV) => sbtPluginExtra(dependency, sbtV, scalaV) }
|
||||||
|
```
|
||||||
|
|
||||||
|
Remember from [[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` (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 version information to
|
||||||
|
the module ID.
|
||||||
|
|
||||||
|
#### `plugins.sbt`
|
||||||
|
|
||||||
|
Some people like to list plugin dependencies (for a project `hello`) in
|
||||||
|
`hello/project/plugins.sbt` to avoid confusion with `hello/build.sbt`. sbt
|
||||||
|
does not care what `.sbt` files are called, so both `build.sbt` and
|
||||||
|
`project/plugins.sbt` are conventions. sbt _does_ of course care where
|
||||||
|
the sbt files are located. `hello/*.sbt` would contain dependencies for
|
||||||
|
`hello` and `hello/project/*.sbt` would contain dependencies for `hello`'s
|
||||||
|
build definition.
|
||||||
|
|
||||||
|
## Plugins can add settings and imports automatically
|
||||||
|
|
||||||
|
In one sense a plugin is just a jar added to `libraryDependencies` for the
|
||||||
|
build definition; you can then use the jar from build definition code as in
|
||||||
|
the lift-json example above.
|
||||||
|
|
||||||
|
However, jars intended for use as sbt plugins can do more.
|
||||||
|
|
||||||
|
If you download a plugin jar
|
||||||
|
([here's one for sbteclipse](http://repo.typesafe.com/typesafe/ivy-releases/com.typesafe.sbteclipse/sbteclipse/scala_2.9.1/sbt_0.11.0/1.4.0/jars/sbteclipse.jar))
|
||||||
|
and unpack it with `jar xf`, you'll see that it contains a file `sbt/sbt.plugins`. In `sbt/sbt.plugins`
|
||||||
|
there's something like this:
|
||||||
|
|
||||||
|
```text
|
||||||
|
com.typesafe.sbteclipse.SbtEclipsePlugin
|
||||||
|
```
|
||||||
|
|
||||||
|
`com.typesafe.sbteclipse.SbtEclipsePlugin` is the name of an object that
|
||||||
|
extends `sbt.Plugin`. The `sbt.Plugin` trait is very simple:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
trait Plugin
|
||||||
|
{
|
||||||
|
def settings: Seq[Setting[_]] = Nil
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
sbt looks for objects listed in `sbt/sbt.plugins`. When it finds
|
||||||
|
`com.typesafe.sbteclipse.SbtEclipsePlugin`, it adds
|
||||||
|
`com.typesafe.sbteclipse.SbtEclipsePlugin.settings` to the settings for the
|
||||||
|
project. It also does `import com.typesafe.sbteclipse.SbtEclipsePlugin._`
|
||||||
|
for any `.sbt` files, allowing a plugin to provide values, objects, and
|
||||||
|
methods to `.sbt` files in the build definition.
|
||||||
|
|
||||||
|
## Adding settings manually from a plugin
|
||||||
|
|
||||||
|
If a plugin defines settings in the `settings` field of a `Plugin` object,
|
||||||
|
you don't have to do anything to add them.
|
||||||
|
|
||||||
|
However, plugins often avoid this because you could not control which
|
||||||
|
projects in a [[multi-project build|Multi-Project Builds]] would use the plugin.
|
||||||
|
|
||||||
|
sbt provides a method called `seq` which adds a whole batch of settings at
|
||||||
|
once. So if a plugin has something like this:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
object MyPlugin extends Plugin {
|
||||||
|
val myPluginSettings = Seq(settings in here)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You could add all those settings in `build.sbt` with this syntax:
|
||||||
|
|
||||||
|
```scala
|
||||||
|
seq(myPluginSettings: _*)
|
||||||
|
```
|
||||||
|
|
||||||
|
If you aren't familiar with the `_*` syntax:
|
||||||
|
|
||||||
|
- `seq` is defined with a variable number of arguments: `def seq(settings: Setting[_]*)`
|
||||||
|
- `_*` converts a sequence into a variable argument list
|
||||||
|
|
||||||
|
Short version: `seq(myPluginSettings: _*)` in a `build.sbt` adds all the
|
||||||
|
settings in `myPluginSettings` to the project.
|
||||||
|
|
||||||
|
## Creating a plugin
|
||||||
|
|
||||||
|
After reading this far, you pretty much know how to _create_ an sbt plugin
|
||||||
|
as well. There's one trick to know; set `sbtPlugin := true` in `build.sbt`.
|
||||||
|
If `sbtPlugin` is true, the project will scan for instances of `Plugin`,
|
||||||
|
and list them in `sbt/sbt.plugins`. `sbtPlugin := true` also adds sbt to the
|
||||||
|
project's classpath, so you can use sbt APIs to implement your plugin.
|
||||||
|
|
||||||
|
Learn more about creating a plugin at [[Plugins]] and [[Plugins Best Practices]].
|
||||||
|
|
||||||
|
## Global plugins
|
||||||
|
|
||||||
|
Plugins can be installed for all your projects at once by dropping them in
|
||||||
|
`~/.sbt/plugins/`. `~/.sbt/plugins/` is an sbt project whose classpath is
|
||||||
|
exported to all sbt build definition projects. Roughly speaking, any `.sbt`
|
||||||
|
fils in `~/.sbt/plugins/` behave as if they were in the
|
||||||
|
`project/` directory for all projects, and any `.scala` files in
|
||||||
|
`~/.sbt/plugins/project/` behave as if they were in the `project/project/`
|
||||||
|
directory for all projects.
|
||||||
|
|
||||||
|
You can create `~/.sbt/plugins/build.sbt` and put `addSbtPlugin()`
|
||||||
|
expressions in there to add plugins to all your projects at once.
|
||||||
|
|
||||||
|
## Available Plugins
|
||||||
|
|
||||||
|
There's [[a list of available plugins|sbt 0.10 plugins list]].
|
||||||
|
|
||||||
|
Some especially popular plugins are:
|
||||||
|
|
||||||
|
- those for IDEs (to import an sbt project into your IDE)
|
||||||
|
- those supporting web frameworks, such as [xsbt-web-plugin](https://github.com/siasia/xsbt-web-plugin).
|
||||||
|
|
||||||
|
[[Check out the list.|sbt 0.10 plugins list]]
|
||||||
|
|
||||||
|
## Next
|
||||||
|
|
||||||
|
Move on to [[multi-project builds|Multi-Project Builds]].
|
||||||
17
_Sidebar.md
17
_Sidebar.md
|
|
@ -1,6 +1,19 @@
|
||||||
|
* [[Home]] - Overview of sbt
|
||||||
* Getting Started
|
* Getting Started
|
||||||
* [[Setup]] - Get sbt running on your machine
|
* [[Setup]] - Install sbt
|
||||||
* [[Running]] - Use sbt from the command line
|
* [[Hello World]] - Create a simple project
|
||||||
|
* [[Directory Structure]] - Basic project layout
|
||||||
|
* [[Running]] - The command line and interactive mode
|
||||||
|
* [[Basic Build Definition]] - Understanding build.sbt settings
|
||||||
|
* [[Scopes]] - Put settings in context
|
||||||
|
* [[More About Settings]] - Settings based on other settings
|
||||||
|
* [[Library Dependencies]] - Adding jars or managed dependencies
|
||||||
|
* [[Full Build Definition]] - When build.sbt is not enough
|
||||||
|
* [[Using Plugins]] - Adding plugins to the build
|
||||||
|
* [[Multi-Project Builds]] - Adding sub-projects to the build
|
||||||
|
* [[Custom Settings and Tasks]] - Intro to extending sbt
|
||||||
|
* [[Summary]] - What you should know now
|
||||||
|
* Help
|
||||||
* [[Migrating from sbt 0.7.x to 0.10.x]]
|
* [[Migrating from sbt 0.7.x to 0.10.x]]
|
||||||
* [[Index]] - Look up common types, values, and methods
|
* [[Index]] - Look up common types, values, and methods
|
||||||
* [[FAQ]]
|
* [[FAQ]]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue