Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does extend for a configuration do?

Tags:

sbt

In SBT I create a new config, called katebush, as follows:

lazy val KateBush: Configuration = config("katebush")

When I try to run katebush:compile I get an error. That's what I expect.

> katebush:compile
[error] No such setting/task
[error] katebush:compile
[error]                 ^

Now I extend Compile in my config definition, and I expect to pick up the compile from the inherited scope.

lazy val KateBush: Configuration = config("katebush") extend Compile

Except it doesn't work:

> katebush:compile
[error] No such setting/task
[error] katebush:compile
[error]                 ^

But if I add in the defaults to the config (in build.sbt) so it looks as follows:

lazy val KateBush: Configuration = config("katebush") extend Compile

inConfig(KateBush)(Defaults.compileSettings)

it works fine:

> katebush:compile
[info] Updating {file:/Users/jacek/sandbox/so-25596360/}so-25596360...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[success] Total time: 0 s, completed Aug 31, 2014 11:35:47 PM

So, my question is, what exactly does extend for a configuration do?

like image 541
sksamuel Avatar asked Aug 31 '14 21:08

sksamuel


1 Answers

DISCLAIMER I've got a rather basic understanding of the config concept of sbt.

tl;dr Extending a configuration is solely to inherit the dependencies groups not settings.

From the sources of final case class Configuration:

def extend(configs: Configuration*) = Configuration(name, description, isPublic, configs.toList ::: extendsConfigs, transitive)

By default, extendsConfigs is Nil as can be seen in the sbt.Configurations object:

def config(name: String) = new Configuration(name)

that resolves to (note Nil)

def this(name: String) = this(name, "", true, Nil, true)

In sbt.IvySbt.toIvyConfiguration:

import org.apache.ivy.core.module.descriptor.{ Configuration => IvyConfig }

and that's where the support of the config concept ends in sbt and Ivy steps in. That's where you'd have to look at the documentation of Ivy.

But before that read Advanced configurations example where it says:

This is an example .scala build definition that demonstrates using Ivy configurations to group dependencies.

That's the beginning of the explanation. Ivy configurations are to group dependencies and extending a configuration is to extend the grouping.

From the official documentation of Ivy about the conf element:

a configuration is a way to use or construct a module.(...) a module may need some other modules and artifacts only at build time, and some others at runtime. All those differents ways to use or build a module are called in Ivy module configurations.

Reading along you can find the answer to your question (that I'm myself yet to digest, too):

A configuration can also extend one or several other ones of the same module. When a configuration extends another one, then all artifacts required in the extended configuration will also be required in the configuration that extends the other one. For instance, if configuration B extends configuration A, and if artifacts art1 and art2 are required in configuration A, then they will be automatically required in configuration B. On the other hand, artifacts required in configuration B are not necessarily required in configuration A.

This notion is very helpful to define configurations which are similar with some differences.

At the bottom of the page, there's the Examples section with an example with runtime config that has "runtime will be composed of all dependencies, all transitively, including the dependencies declared only in compile."

With this, you can now understand the config concept in sbt as a dependencies groups and what's grouped in Compile is available in Runtime as its definition looks as follows:

lazy val Runtime = config("runtime") extend (Compile)
like image 163
Jacek Laskowski Avatar answered Oct 06 '22 22:10

Jacek Laskowski