Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 3 additions & 36 deletions src/reference/01-Faq/00.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ out: Faq.html
[Multi-Project]: Multi-Project.html
[Name-Index]: Name-Index.html
[Mapping-Files]: Mapping-Files.html
[Custom-Dependency-Configuration]: Custom-Dependency-Configuration.html
[Testing]: Testing.html
[additional-test-configurations]: Testing.html#additional-test-configurations
[Library-Management]: Library-Management.html
Expand Down Expand Up @@ -170,43 +171,9 @@ See [Caching][Caching].

### Extending sbt

#### How can I add a new configuration?
#### How can I add a new dependency configuration?

The following example demonstrates adding a new set of compilation
settings and tasks to a new configuration called `Samples`. The sources
for this configuration go in `src/samples/scala/`. Unspecified settings
delegate to those defined for the `Compile` configuration. For example,
if `scalacOptions` are not overridden for `Samples`, the options for the
main sources are used.

Options specific to `Samples` may be declared like:

```scala
Samples / scalacOptions += "-deprecation"
```

This uses the main options as base options because of `+=`. Use `:=` to
ignore the main options:

```scala
Samples / scalacOptions := "-deprecation" :: Nil
```

The example adds all of the usual compilation related settings and tasks
to `samples`:

```
Samples/run
Samples/runMain
Samples/compile
Samples/console
Samples/consoleQuick
Samples/scalacOptions
Samples/fullClasspath
Samples/package
Samples/packageSrc
...
```
See [How to define a custom dependency configuration][Custom-Dependency-Configuration].

#### How do I add a test configuration?

Expand Down
88 changes: 88 additions & 0 deletions src/reference/04-Howto/30-Howto-Custom-Dependency-Configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
out: Custom-Dependency-Configuration.html
---

[Testing]: Testing.html
[additional-test-configurations]: Testing.html#additional-test-configurations

How to define a custom dependency configuration
-----------------------------------------------

A *dependency configuration* (or *configuration* for short) defines
a graph of library dependencies, potentially with its own
classpath, sources, generated packages, etc. The dependency configuration concept
comes from Ivy, which sbt used to use for
managed dependencies [Library Dependencies][Library-Dependencies], and from
[MavenScopes](https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Scope).

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.

### Cautions on custom dependency configurations

A custom configuration should be considered only when you are
introducing either a new set of source code or its own
library dependencies (like `Test`).

In general, it would be a bad idea to introduce configuration
merely as a way to namespace keys.

One drawback of the custom configuration is that the users will be confused
about the complexity around scoping. They might be familar with
subprojects and tasks, but it becomes complicated when configuration scoping
is involved.

Another drawback is that there is limited support from sbt.
For instance, you can express that a configuration is meant to `extend`
another configuration, but there is no inheritance of settings.
You have to provide all expected settings and tasks.
This means that when a new features are added to sbt, there's a good
chance the custom configurations will not be covered.
The same goes for third-party plugins.

### Example basic custom configuration

Here's an example of a minimum custom configuration.

#### project/FuzzPlugin.scala

@@snip [FuzzPlugin.scala]($root$/src/sbt-test/ref/custom-config/project/FuzzPlugin.scala) {}

#### build.sbt

@@snip [build.sbt]($root$/src/sbt-test/ref/custom-config/build.sbt) {}

### Example sandbox configuration

One sometimes useful technique with a configuration is adding a side graph
to the user's project so Coursier would download some JARs,
which your task can invoke. This is called a sandbox configuration.
This can be used for instance to invoke Scala 2.13 CLI version of scalafmt.
As of sbt 1.4.x there's a limitation so the sandbox configuration
must use the same Scala version as the user's subproject.

#### project/ScalafmtPlugin.scala

@@snip [ScalafmtPlugin.scala]($root$/src/sbt-test/ref/custom-config/project/ScalafmtPlugin.scala) {}

Enabling `ScalafmtPlugin` would add `scalafmt` task, which runs the CLI.

```
sbt:custom-configs> scalafmt --version
[info] running (fork) org.scalafmt.cli.Cli --version
[info] scalafmt 2.7.5
[success] Total time: 3 s, completed Feb 8, 2021 12:01:34 AM
sbt:custom-configs> scalafmt
[info] running (fork) org.scalafmt.cli.Cli
[info] Reformatting...
Reformatting...
[success] Total time: 6 s, completed Feb 8, 2021 12:01:40 AM
```

### How do I add a test configuration?

See the [Additional test configurations][additional-test-configurations] section of
[Testing][Testing].
9 changes: 9 additions & 0 deletions src/sbt-test/ref/custom-config/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
ThisBuild / scalaVersion := "2.13.4"
ThisBuild / version := "0.1.0-SNAPSHOT"

lazy val root = (project in file("."))
.configs(Fuzz)
.enablePlugins(FuzzPlugin, ScalafmtCliPlugin)
.settings(
name := "use",
)
12 changes: 12 additions & 0 deletions src/sbt-test/ref/custom-config/project/FuzzPlugin.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.example.sbtfuzz

import sbt._

object FuzzPlugin extends AutoPlugin {
object autoImport {
lazy val Fuzz = config("fuzz")
}
import autoImport._
override lazy val projectSettings =
inConfig(Fuzz)(Defaults.configSettings)
}
33 changes: 33 additions & 0 deletions src/sbt-test/ref/custom-config/project/ScalafmtPlugin.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.example

import sbt._
import Keys._

object ScalafmtCliPlugin extends AutoPlugin {
object autoImport {
lazy val ScalafmtSandbox = config("scalafmt").hide
lazy val scalafmt = inputKey[Unit]("")
}
import autoImport._
override lazy val projectSettings = Seq(
ivyConfigurations += ScalafmtSandbox,
libraryDependencies += "org.scalameta" %% "scalafmt-cli" % "2.7.5" % ScalafmtSandbox,
scalafmt := (ScalafmtSandbox / run).evaluated
) ++ inConfig(ScalafmtSandbox)(
Seq(
run := Defaults.runTask(managedClasspath, run / mainClass, run / runner)
.evaluated,
managedClasspath := Classpaths.managedJars(
ScalafmtSandbox,
classpathTypes.value,
update.value,
)
) ++
inTask(run)(
Seq(
mainClass := Some("org.scalafmt.cli.Cli"),
fork := true, // to avoid exit
) ++ Defaults.runnerSettings
)
)
}
1 change: 1 addition & 0 deletions src/sbt-test/ref/custom-config/test
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
> scalafmt