I have a scala SBT project where I'm using the native packager plugin. I'm bundling as a JavaServerAppPackaging and would like to generate scripts for automatically registering the application for startup and shutdown with rc.d scripts (Amazon Linux).
In my plugins.sbt:
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.2.0-M5")
In build.sbt
lazy val server =
DefProject("some/server", "server")
.settings(serverModuleDeps)
.settings(ServerSettings.allSettings: _*)
.settings(CloudFormation.defaultSettings: _*)
.settings(serverLoading in Universal := Option(ServerLoader.SystemV))
.settings(serviceAutostart:=true)
.settings(startRunlevels:=Option("3"))
.settings(stopRunlevels:=Option("3"))
.settings(stackRegion := "US_WEST_2")
.settings(codedeployAWSCredentialsProvider := Option(new ProfileCredentialsProvider("devcredentialsprovider")))
.dependsOn(sharedJvm)
.dependsOn(langJVM)
.enablePlugins(JavaServerAppPackaging, SystemVPlugin)
.settings(daemonUser:="ec2-user")
.configure(InBrowserTesting.jvm)
when I run sbt stage I can see a universal folder containing a bin folder with a sh and a cmd file to start the application. However, there is not code to register/start the application as a system service. Is there any additional configuration required to have the plugin generate scripts for registering the application? What am I missing?
I have a created a basic project to demonstrate the issue: https://github.com/MojoJojo/sbt-native-packager-test
Your configuration is correct. Your sbt command isn't :)
with packageBin ( which IIRC triggers universal:packageBin ) generates only a universal zip file. A systemloader is a operating system specific part. That's why it's not included in a universal zip.
Generate a debian or rpm file with
debian:packageBin
rpm:packageBin
The generated deb or rpm package will have the systemloader files included, because they are in the place a rpm/debian based system would expect them.
Related issue: https://github.com/sbt/sbt-native-packager/issues/869
Related
I am new to Scala and sbt (0.13.13) - I started using Play Framework (2.5.10) a few weeks ago.
My question:
I added
unmanagedResourceDirectories in Compile += baseDirectory( _ / "devstuff" ).value
to the build.sbt. This is because I want all the files (these are not source files) in devstuff on the classpath (only) during developing my app (when running sbt run). Also, when editing a file in devstuff the application gets restarted/re-compiled. That's fine and that's what I want for development.
However when running sbt dist, sbt stage, universal:packageZipTarball, etc. - when I create the final distribution package - I do not want that this folder gets included. The folder only contains stuff needed during developing, but I don't want it packaged in my final package.
How can I achieve that the myfolder is in unmanagedResourceDirectories for sbt run (and also sbt test) but not for creating the distribution packages?
According to the sbt documentation you should be able to use the Runtime scope to achieve this:
unmanagedResourceDirectories in Runtime += baseDirectory( _ / "devstuff" ).value
I'm trying to create a standalone jar file from the elastic4s sources on github. I've used sbt compile as detailed on the github page, but I can't find the jar file.
How do I use sbt to create the jar file so I can import it into my projects as a dependency?
The compile task will only compile the project.
> help compile
Compiles sources.
If you want to create a jar file and use it as a dependency in your project, you have two ways of doing that.
Unmanaged dependency (not recommended)
Unmanaged dependency run +package, which will create a jar file for each supported scala version, which you can use in your projects as an unmanaged dependency. Copy the package-generated jar to lib folder in your project.
The jar files will be located in target/scala-2.11 and target/scala-2.10, depending on the Scala version you want to use it with.
Publish to Local Repository (recommended yet imperfect)
If you want to include your custom-built elastic4s, as a managed dependency, you have to run +publishLocal. This will do the same as above, but additionally it will publish the artifact to your local repository. Assuming you've built it with version := "1.2.1.1-SNAPSHOT", you can include it in your project by just adding:
libraryDependencies += "com.sksamuel.elastic4s" %% "elastic4s" % "1.2.1.1-SNAPSHOT"
What makes the approach imperfect is that once you shared the project on GitHub (or any other project sharing platform), people will have to do publishLocal themselves to be able to build your project. The dependency should therefore go to one of the official binary repositories so when a dependency is needed, it's downloaded from Internet. Consult Publishing.
What is the + character in front of the commands
The + in the commands is for cross-building, if you don't use it the command will be executed only using scalaVersion declared in the build.sbt of the project.
(This is a follow up to sbt not creating projects correctly. The question wasn't answered.)
Basically, that question says "I don't know how to create a project under the new sbt. With the old one, I just ran sbt in a new folder and there was a guided wizard that led me through the setup."
The accepted answer does not explain how to create a new project, it just points to the documentation, which also doesn't explicitly say how to create a new project -- only how to write a build.sbt file.
So I tried first writing a build.sbt and then running sbt in the directory with the build.sbt file, but I still don't see a src directory to work with.
Could someone post a simple step-by-step (I'm assuming there are like 3 steps at most) guiding how to create a new project under sbt 0.10.X?
I found the answer I was looking for at this webpage: Scala 2.9.1, sbt 0.10 and ScalaTest step-by-step.
The high-level steps are:
mkdir my_project make a folder for your project
Create a simple my_project/build.sbt file, e.g.:
name := "A Project"
version := "0.1"
scalaVersion := "2.9.1"
libraryDependencies ++= Seq(
"org.scalatest" %% "scalatest" % "1.6.1" % "test"
)
Create a file my_project/src/main/scala/HelloWorld.scala, where you create all the directories you need as you go (e.g. create the directory structure src/main/scala/)
object Main extends App {
Console.println("Hello World!")
}
Execute your sbt commands: e.g. sbt run
I am surprised that noone gave another solution which is the closest to the old way (as mentioned by #dsg) to create a simple project in sbt:
Just run sbt in your project directory, then issue the following commands in the sbt REPL:
> set name := "MyProject"
> set version := "1.0"
> set scalaVersion := "2.9.0"
> session save
> exit
Granted, it is only mildly useful as it will just create the build.sbt file (enough to make it a proper sbt project) with the corresponding properties set, and you might as well create the file by hand (I usually prefer to do so myself). It won't create the src directory either.
Just a few days ago np (new project) plugin to sbt was released. It intended to dealt exactly with that problem:
Initial release. Provides a minimal interface for generating new sbt
projects via,... sbt.
Basic use is to install the plugin globally and start up a new project
with
$ sbt
$ np name:my-project org:com.mypackage version:0.1.0-SNAPSHOT
This will generate a simple build.sbt project for you along with the
standard project directory structure for main and test sources.
For more advanced usage, see the project's readme for more info
You can use https://github.com/n8han/giter8 to generate project layout using various templates
In newer versions of sbt, you can just install sbteclipse:
// ~/.sbt/plugins/build.sbt
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.1.0")
then from sbt's console you can run:
eclipse with-source=true
In version 0.10.x I think this post can help you:
http://dcsobral.blogspot.fr/2011/06/very-quick-guide-to-project-creation-on.html
I've been using https://github.com/ymasory/sbt-prototype skeleton. See also my other answer.
It was the first one that just worked and I've been a quite happy with it since then.
Don't forget the recent sbt 0.13.3 new command:
Example:
First, you need sbt’s launcher version 0.13.13 or above.
Normally the exact version for the sbt launcher does not matter because it will use the version specified by sbt.version in project/build.properties; however for new sbt’s launcher 0.13.13 or above is required as the command functions without a project/build.properties present.
Next, run:
$ sbt new eed3si9n/hello.g8
....
name [hello]:
scala_version [2.11.8]:
Template applied in ./hello
This ran the template eed3si9n/hello.g8 using Giter8, prompted for values for “name” and “scala_version” (which have defaults “hello” and “2.11.8”, which we accepted hitting [Enter]), and created a build under ./hello.
Check out the GitHub repo Scala SBT Template. In particular the buildt.sbt file.
Just clone the repo, go to that directory, then call the sbt command.
$ git clone git://github.com/dph01/scala-sbt-template.git
$ cd scala-sbt-template
$ ./sbt
From inside of sbt, you can type run to execute provided code. Have fun!
An alternative way to generate the project structure using Intellij:
Create the directory for the project and include there a basic sbt file. You just need to specify the project name.
name := "porjectName"
With Intellij import the project. During the process check the options "Use auto-import" and "Create directories for empty content roots automatically"
That will create for you the basic skeleton for the sbt project.
How can I run an sbt app from the shell, so that I can run my app as a normal command-line program (as if run directly via scala but without having to set up an enormous classpath)?
I know I can do:
echo hello | sbt 'run-main com.foo.MyMain3 arg1 arg2' > out.txt
But this (1) takes forever to start because it starts sbt, (2) causes all stdout and stderr to go to stdout, and (3) causes all output to be decorated with a logger [info] or [error].
I looked at https://github.com/harrah/xsbt/wiki/Launcher but it seems too heavyweight, since it downloads dependencies and sets up a new environment and whatnot. I just want to run this app within my existing development environment.
Thus far I've cobbled together my own script to build up a classpath, and you can also do some other things like modify your project file to get sbt to print the raw classpath, but I feel like there must be a better way.
Here's what I have in my SBT (version 0.10) project definition,
val Mklauncher = config("mklauncher") extend(Compile)
val mklauncher = TaskKey[Unit]("mklauncher")
val mklauncherTask = mklauncher <<= (target, fullClasspath in Runtime) map { (target, cp) =>
def writeFile(file: File, str: String) {
val writer = new PrintWriter(file)
writer.println(str)
writer.close()
}
val cpString = cp.map(_.data).mkString(":")
val launchString = """
CLASSPATH="%s"
scala -usejavacp -Djava.class.path="${CLASSPATH}" "$#"
""".format(cpString)
val targetFile = (target / "scala-sbt").asFile
writeFile(targetFile, launchString)
targetFile.setExecutable(true)
}
... // remember to add mklauncherTask to Project Settings
The mklauncher task creates a script target/scala-sbt that executes scala with the project classpath already set. It would be nice to have mklauncher executed automatically whenever the classpath changes, but I haven't looked into doing this yet.
(I use the Java classpath, rather than Scala's, for ease of creating embedded interpreters.)
The start-script SBT plugin is now at:
https://github.com/sbt/sbt-start-script
It requires a few steps to set up and generates scripts that do not work on OS X, but that can be easily fixed if you're on that platform (see below).
Setup
Install greadlink (OS X only):
a) brew install coreutils
b) map readlink to the new function (greadlink) by adding these lines to ~/.bashrc:
function readlink() { greadlink "$#"; }
export -f readlink`
Add start-script plugin to ~/.sbt/plugins/build.sbt:
addSbtPlugin("com.typesafe.sbt" % "sbt-start-script" % "0.8.0")
Add start-script task to current project:
$ sbt add-start-script-tasks # execute from directory where build.sbt resides
Add start-script support to current build.sbt:
import com.typesafe.sbt.SbtStartScript
seq(SbtStartScript.startScriptForClassesSettings: _*)
Note the blank line in between statements (de rigueur for SBT build files).
Generate Start Script
Then, whenever you want to create a script to start your app like sbt run-main, but without sbt, execute:
$ sbt start-script
Run
target/start mypackage.MyMainClass
Time flies by and a lot have changed since the other answers. It's currently SBT 0.13.6 time.
I think what you may need is the sbt-onejar plugin or the SBT Native Packager plugin.
sbt-onejar "is a simple-build-tool plugin for building a single executable JAR containing all your code and dependencies as nested JARs."
SBT Native Packager's "goal is to be able to bundle up Scala software built with SBT for native packaging systems, like deb, rpm, homebrew, msi."
Just discovered the sbt start script plugin: https://github.com/typesafehub/xsbt-start-script-plugin:
This plugin allows you to generate a script target/start for a
project. The script will run the project "in-place" (without having to
build a package first).
The target/start script is similar to sbt run but it doesn't rely on
SBT. sbt run is not recommended for production use because it keeps
SBT itself in-memory. target/start is intended to run an app in
production.
The plugin adds a task start-script which generates target/start. It
also adds a stage task, aliased to the start-script task.
I know if I add withSources when I define one dependency, sbt can download that sources jar file automatically.
For example,
val specs = "org.scala-tools.testing" % "specs_2.8.1" % "1.6.6" % "test" withSources ()
But for the scala-library.jar and scala-compiler.jar, I don't need define them explicitly, how can I get sbt download their sources for me? So, I don't need config it manually after generate idea project using sbt-idea-plugin.
You have to change the boot properties. There is a nice description in the recent blog decodified from Mathias:
"How to make SBT download scala library sources" (started from #hseeberger key starting points)
Here is the relevant part (in case that link ever goes stale)
First, forget about trying to find some “hidden” setting in your SBT project definition enabling Scala library source download! It does not exist (at least not in SBT version 0.7.x).
Rather, there are these two things you need to do in order to whip SBT into submission:
Create an alternative configuration file for your SBT launcher.
Make the SBT launcher use it.
These are the steps in detail:
Find your sbt-launcher-0.7.x.jar file.
Since I’m on OS/X and use SBT via Homebrew mine lives at /usr/local/Cellar/sbt/0.7.5.RC0/libexec/sbt-launch-0.7.5.RC0.jar.
Extract the sbt.boot.properties from the sbt sub directory in the launcher jar
Fire up your favorite editor and change line 3 to classifiers: sources (uncomment the line)
Find the sbt script file you created during your SBT setup (e.g. ~/bin/sbt, or, when using Homebrew, /usr/local/Cellar/sbt/0.7.x/bin/sbt)
Add the path to your tweaked sbt.boot.properties file, prepended with an ’#’ character and in double quotes, as the second-to-last argument of the java call.
This is what my sbt script file looks like:
#!/bin/sh
java -Xmx768M -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=256m \
-jar /usr/local/Cellar/sbt/0.7.5.RC0/libexec/sbt-launch-0.7.5.RC0.jar \
"#/usr/local/Cellar/sbt/0.7.5.RC0/libexec/sbt.boot.properties" \
"$#"
Once you have completed these steps SBT should happily download the scala-...-sources.jar files for the Scala compiler and standard library for any new project you create.
To have SBT do this for an existing project, you have to manually delete the project/boot/scala-{version} directory before performing an ‘sbt update’ (SBT does not fetch additional source artifacts if the main jar is already present).
Once you have a custom sbt.boot.properties file, there are also other ways to supply it to the SBT launcher.
See SO question "how do I get sbt to use a local maven proxy repository (Nexus)?"
Based on Michael Slinn comments:
If you are using sbt 0.11.x and above, use this command:
sbt update-sbt-classifiers
Two pieces of information.
(1) SBT Documentation
http://www.scala-sbt.org/0.13.5/docs/Detailed-Topics/Library-Management.html
and I quote:
"To obtain particular classifiers for all dependencies transitively, run the updateClassifiers task. By default, this resolves all artifacts with the sources or javadoc classifier."
This means you should not need to do anything, but you can make it explicit and put in you build.sbt:
transitiveClassifiers := Seq("sources", "javadoc")
To actually get the sources downloaded by SBT then you do:
"updateClassifiers"
(2) If you are working with Eclipse scala IDE - most likely you are as development of plugins for Eclipse/Netebeans is a lot more active for eclipse - then you should configure your ecplise to find out the sources if you do the following.
EclipseKeys.withSource := true
Here is the documentation you should read,
https://github.com/typesafehub/sbteclipse/wiki/Using-sbteclipse