Specify main class for sbt-resolver - sbt

After upgrading to version 0.8.0 of the sbt-resolver plugin I get the following error messages after typing sbt ~re-start:
[info] Application exampleJS not yet started
[info] Application exampleJVM not yet started
[info] Starting application exampleJVM in the background ...
exampleJVM Starting example.Server.main()
java.lang.RuntimeException: No main class detected!
at scala.sys.package$.error(package.scala:27)...
Hoewever, I did specify a main class in my build.sbt:
).jvmSettings(
name := "Server",
mainClass := Some("example.Server"),
...
My project setup is quite analogous to this example.
However - despite this error message - the spray server is started correctly!?
But I want to get rid of this annoying message...

If you're just looking to suppress the warning, try replacing reStart in the JS subproject's build settings with a no-op:
import spray.revolver.RevolverPlugin.Revolver
// Assuming you're using the same name as the example you linked.
// Override the reStart task to do nothing.
val exampleJS = example.js.settings(Revolver.reStart := {})

Related

Running sbt release task from cli for sub-project doesn't work

I have a multi-project sbt where I use sbt-release plugin. Everything works fine if I run release in a sub-project
> project reporter
[info] Set current project to reporter (in build file:/source/storage-integ/)
> release
[info] Starting release process off commit: c069698baf8bb6fca611ab4e7e086398aab473c5
[info] Checking remote [origin] ...
But this doesn't work when I run "sbt reporter/release" from cli. Where as "sbt reporter/compile" or "sbt reporter/assembly" do work.
$ sbt reporter/release
[warn] Executing in batch mode.
[warn] For better performance, hit [ENTER] to switch to interactive mode, or
[warn] consider launching sbt without any commands, or explicitly passing 'shell'
[info] Loading global plugins from /home/vagrant/.sbt/0.13/plugins
[info] Loading project definition from /source/storage-integ/project
[info] Set current project to root (in build file:/source/storage-integ/)
[error] Expected ':' (if selecting a configuration)
[error] Not a valid key: release (similar: releaseVcs, rpmRelease, rpm-release)
[error] reporter/release
This looks very similar to another SO post. I tried adding releaseSettings to build.sbt as suggested but it throws error
build.sbt:62: error: not found: value releaseSettings
I tried import sbtrelease.Release._ but that throws
error: object Release is not a member of package sbtrelease
At this point I feel the solution mentioned is no longer valid. Also, I don't see any reference to releaseSettings in sbt-release readme. Any idea how to get this working?
sbt.version = 0.13.15 && sbt-release: "1.0.6"
The release settings should be only in your root project. So, in order to have that:
First, your build.sbt could be something like this
lazy val root: Project = project.in(file("."))
.settings(Releases.settings: _*)
.aggregate(module1, module2)
Then, your project/Releases.scala like:
object Releases {
// You need to custom these to reflect your actual procedure
private val releaseProcess = Def.setting {
Seq[ReleaseStep](
checkSnapshotDependencies,
inquireVersions,
runClean,
runTest,
setReleaseVersion,
commitReleaseVersion,
tagRelease,
publishArtifacts,
setNextVersion,
commitNextVersion,
pushChanges
)
}
val settings = Seq(
releaseCommitMessage := s"Set version to ${(version in ThisBuild).value}",
releaseTagName := (version in ThisBuild).value,
releaseProcess := releaseProcess.value
)
}
By default you need a version.sbt with your current version. Lets say:
version in ThisBuild := "1.0.0-SNAPSHOT"
Then just:
sbt release

Invoking a subproject's main with a custom task

I have a project performing integration tests for a bunch of projects which are all bundled in the same multi-project build with it. The integration tests run through a regular main (object Runner extends App).
I wish being able to run it from the root project of the multi-project build through a task or command named integrationTest, so I try:
val integrationTest = taskKey[Unit]("Executes integration tests.")
lazy val root = (project in file(".")).aggregate(projIntegrationTest, projA, projB, ...).settings(
integrationTest := (run in Compile in projIntegrationTest).value
)
Which does nothing when I issue integrationTest on the prompt, only emitting:
[success] Total time: 0 s, completed Oct 23, 2015 12:31:21 AM
How may I approach finding out why does it not get run when my custom task integrationTest runs?
Oddly, replacing run with compile or publishlocal in integrationTest := (run in Compile in projIntegrationTest).value above, my custom task line acts as expected and takes care of compiling or publishing when the custom task is executed.
It doesn't work because run is an InputTask, not a regular Task.
You need to do:
integrationTest :=
(run in Compile in projIntegrationTest)
.toTask("").value
this is covered in the "Get a Task from an InputTask" section of http://www.scala-sbt.org/0.13/docs/Input-Tasks.html.
As of sbt 0.13.13 your code gives:
warning: `value` is deprecated for an input task. Use `evaluated` or `inputTaskValue`.
This is a nice improvement; earlier versions of sbt let this pass, making it hard to troubleshoot. (But note that the deprecation message suggests a different solution than I've used here; I haven't investigated that discrepancy. Can someone shed some light on that?)

Making package a dependency of a new sbt task

When at the sbt CLI I can just type package and everything works fine - two jar files are produced. But I want to make package a dependency of a new task I am creating, so I want to make packaging happen as part of the build script. This is what I have:
lazy val deployTask = TaskKey[Unit]("deploy")
deployTask := { println("deploy happening now!") }
deployTask := {
(deployTask.in(file("."))).value
(Keys.`package` in Compile).value
}
My reading of the documentation tells me that Compile really means file("src/main/scala"), which is not what I want. It seems that I have to put in <Something>. What do I need to put in instead of <Something> to get package to mean what it means when I type it at the CLI?
At the CLI I should be able to:
clean
show deploy
, but unfortunately it does not do the packaging I expect.
These are the projects:
projects
[info] In file:/C:/dev/v2/atmosphere/
[info] atmosphereJS
[info] atmosphereJVM
[info] * root
So it makes sense that when I run package from the CLI the root project is used.
So another way of asking this question might be: "How do I make package work for root from the deploy task I am creating?"

What does extend for a configuration do?

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?
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)
I have just had to figure this out, so I thought this was worth clarifying. The configuration has to be added to the project for delegation to the extended configuration to occur:
lazy val KateBush: Configuration = config("katebush") extend Compile
lazy val root = (project in file(".")).configs(KateBush)
will work fine. If you
inspect katebush:compile
then you can view the delegation chain:
...
[info] Delegates:
[info] katebush:compile
[info] compile:compile
[info] *:compile
[info] {.}/katebush:compile
[info] {.}/compile:compile
[info] {.}/*:compile
[info] */katebush:compile
[info] */compile:compile
[info] */*:compile
...

How do you do develop an SBT project, itself?

Background: I've got a Play 2.0 project, and I am trying to add something to do aspectj weaving using aspects in a jar on some of my classes (Java). (sbt-aspectj doesn't seem to do it, or I can't see how). So I need to add a custom task, and have it depend on compile. I've sort of figured out the dependency part. However, because I don't know exactly what I'm doing, yet, I want to develop this using the IDE (I'm using Scala-IDE). Since sbt projects (and therefore Play projects) are recursively defined, I assumed I could:
Add the eclipse plugin to the myplay/project/project/plugins.sbt
Add the sbt main jar (and aspectj jar) to myplay/project/project/build.sbt:
libraryDependencies ++= Seq(
"org.scala-sbt" % "main" % "0.12.2",
"aspectj" % "aspectj-tools" % "1.0.6"
)
Drop into the myplay/project
Run sbt, run the eclipse task, then import the project into eclipse as a separate project.
I can do this, though the build.scala (and other scala files) aren't initially considered source, and I have to fiddle with the build path a bit. However, even though I've got the sbt main defined for the project, both eclipse IDE and the compile task give errors:
> compile
[error] .../myplay/project/Build.scala:2: not found: object keys
[error] import keys.Keys._
[error] ^
[error] .../myplay/project/SbtAspectJ.scala:2: object Configurations is not a member of package sbt
[error] import sbt.Configurations.Compile
[error] ^
[error] .../myplay/project/SbtAspectJ.scala:3: object Keys is not a member of package sbt
[error] import sbt.Keys._
[error] ^
[error] three errors found
The eclipse project shows neither main nor aspectj-tools in its referenced-libraries. However, if I give it a bogus version (e.g. 0.12.4), reload fails, so it appears to be using
the dependency.
So,...
First: Is this the proper way to do this?
Second: If so, why aren't the libs getting added.
(Third: please don't let this be something dumb that I missed.)
If you are getting the object Keys is not a member of package sbt error, then you should check that you are running sbt from the base directory, and not the /project directory.
sbt-aspectj
sbt-aspectj doesn't seem to do it, or I can't see how.
I think this is the real issue. There's a plugin already that does the work, so try making it work instead of fiddling with the build. Using plugins from build.scala is a bit tricky.
Luckily there are sample projects on github:
import sbt._
import sbt.Keys._
import com.typesafe.sbt.SbtAspectj.{ Aspectj, aspectjSettings, compiledClasses }
import com.typesafe.sbt.SbtAspectj.AspectjKeys.{ binaries, compileOnly, inputs, lintProperties }
object SampleBuild extends Build {
....
// precompiled aspects
lazy val tracer = Project(
"tracer",
file("tracer"),
settings = buildSettings ++ aspectjSettings ++ Seq(
// stop after compiling the aspects (no weaving)
compileOnly in Aspectj := true,
// ignore warnings (we don't have the sample classes)
lintProperties in Aspectj += "invalidAbsoluteTypeName = ignore",
// replace regular products with compiled aspects
products in Compile <<= products in Aspectj
)
)
}
How do you do develop an SBT project, itself?
If you're interested in hacking on the build still the first place to go is the Getting Started guide. Specifically, your question should be answered in .scala Build Definition page.
I think you want your build to utilize "aspectj" % "aspectj-tools" % "1.0.6". If so it should be included in myplay/project/plugins.sbt, and your code should go into myplay/project/common.scala or something. If you want to use IDE, you have have better luck with building it as a sbt plugin. That way your code would go into src/main/scala. Check out sbt/sbt-aspectj or sbt/sbt-assembly on example of sbt plugin structure.

Resources