问题
The sbt documentation shows example of how to declare dependency only between projects. But I'm positive that there are ways to declare one config be dependent on another, just like the Test configuration uses classpath from the Compile configuration.
How can I declare my own configuration so that it would depend on the Compile config generated classpath?
I take a more close look to suggested solution and bunch of question arose again. So I reopen the question
I can not deduce sbt behavior solely from the delegate relation between Test and Compile config.
The source directories turn out to be completely different for Test and Compile config despite being delegated.
> show test:unmanagedSourceDirectories
[info] List(./src/test/scala, ./src/test/java)
> show test:scalaSource
[info] ./src/test/scala
> show test:javaSource
[info] ./src/test/java
> show compile:unmanagedSourceDirectories
[info] List(./src/main/scala, ./src/main/java)
> show compile:scalaSource
[info] ./src/main/scala
> show compile:javaSource
[info] ./src/main/java
And other significant keys such as unmanagementClasspath
and fullClasspath
are not SettingsKey
s that may be naturally stacked with delegating. They are full-fledged TaskKey
s that stores complex procedure for generating class-paths behind them.
So, the question is still actual: How can I mimic exporting classes from Compile to Test config for my custom defined config? And there is closely related optional question: how this is actually done for aforementioned pre-defined configs?
回答1:
You can make one configuration extend another. You do that by using extend
method.
lazy val MyConfig = config("myConfig") extend(Compile)
lazy val root = project.in(file(".")).
configs(MyConfig).
settings(inConfig(MyConfig)(Defaults.compileSettings ++ Defaults.compileInputsSettings): _*)
Extend will delegate to Compile
in this case, for settings which are undefined in the MyConfig
configuration.
You can check it by running SBT and executing for example show myConfig:managedClasspath
, the output should be exactly the same as for show compile:managedClasspath
.
If you inspect your new configuration's managedClasspath
you'll see that it delegates to the compile
.
[info] Delegates:
[info] myConfig:managedClasspath
[info] compile:managedClasspath
[info] *:managedClasspath
[info] {.}/myConfig:managedClasspath
[info] {.}/compile:managedClasspath
[info] {.}/*:managedClasspath
[info] */myConfig:managedClasspath
[info] */compile:managedClasspath
[info] */*:managedClasspath
As I've stated above, SBT will only delegate to the setting if it's not defined in the given configuration.
For example, if you do not define any specific compiler options for myConfig
the settings will be taken from compile
.
> show compile:scalacOptions
[info] List()
> show myConfig:scalacOptions
[info] List()
Changing setting in compile
configuration will have an effect on myConfig
:
> set scalacOptions in Compile += "-Xexperimental"
> show compile:scalacOptions
[info] List(-Xexperimental)
> show myConfig:scalacOptions
[info] List(-Xexperimental)
Overriding the setting in myConfig
will make SBT to use the setting defined in that configuration, while Compile
will have its own value:
> set scalacOptions in MyConfig := Seq("-Xcheck-null")
> show compile:scalacOptions
[info] List(-Xexperimental)
> show myConfig:scalacOptions
[info] List(-Xcheck-null)
Note the delegation is one way. Change to the MyConfig
has no influence on the Compile
configuration.
You can check the documentation for details.
来源:https://stackoverflow.com/questions/23586436/make-one-sbt-config-depend-on-another