Skip to content

Instantly share code, notes, and snippets.

@sam
Last active January 29, 2016 17:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save sam/5223921 to your computer and use it in GitHub Desktop.
Save sam/5223921 to your computer and use it in GitHub Desktop.
Quickstart for using SBT with IntelliJ IDEA.

Quickstart for using SBT with IntelliJ IDEA.

  • Create a new blank repository for your project
  • Create a project sub-folder
  • Add the following files to it (tweaking where necessary)

Now you can start sbt (at your project's root folder, not the ./project/ sub-folder), and run the gen-idea command to generate all your IntelliJ IDEA configuration files.

NOTE

If you're going the multi-project route, you'll end up with something like this:

./meta-project
    project/$SBT_FILES
    widget-core # <- This is a git submodule to another project
        src # Project structure...
            main/scala
            test
            # etc...
    widgetization # Another submodule/project that depends on widget-core
    widget-migrations # Another submodule
    acme # A client project submodule that depends on the other projects

None of your sub-projects would have build files of their own!

That's important. By putting the SBT build files in the meta-project, you can define inter-project dependencies and such. If you had build files in the subprojects sure, they could run standalone if they didn't have dependencies, but Build.scala files aren't recursive, so they couldn't be a "master copy" of your project definitions. You'd have to duplicate the configuration in your meta-project, and maintain the definition in both places.

So I'd recommend just giving up on running the projects standalone for the most part, and depending on running SBT only through your meta-project. The submodules become just a way to organize your code then so if you referenced 20 client projects in your structure, you wouldn't have to clone-the-world necessarily to work on Client-A. You can git submodule init just the client you need.

sbt.version=0.12.2
import sbt._
import Keys._
// If you want to use a Play project in your multi-project build:
import play.Project._
object ApplicationBuild extends Build {
// In a true multi-project setup you might have a "meta-project" repository
// with submodules for sub-projects. Then one Project definition here for
// each subproject. So you wouldn't have a project with the path of "."
// as we do below. This is just to get you started, and since we have
// dependency examples as well, you can go either direction from here.
// (Full-blown multi-project with sub-folders/modules, or slimmed down
// single project against the root folder.)
lazy val myApp = Project("myApp", file("."))
.dependsOn(hasher, sprouch) // Project dependencies!
.settings(
scalaVersion := "2.10.1", // Ignore system, aquire latest.
version := "1.0-SNAPSHOT",
resolvers := Seq(
// In theory the Typesafe Repository is a full mirror of Central.
// In practice some libs are manifested, but the actual JARs are
// missing. So it's important to include Central before the Typesafe
// repository.
"Maven Central" at "http://repo1.maven.org/maven2/",
"Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
),
libraryDependencies ++= Seq(
// "%%" only applies to Scala libs. It means: Append "_2.10" (your current Scala version)
// to the artifact id since different Scala versions will require builds specific to them.
// The scalatest dependency below is the same as writing this:
// "org.scalatest" % "scalatest_2.10" % "2.0.M5b" % "test"
// So "%%" is just a short-cut so when you bump Scala versions you only need
// to change it one place (the scalaVersion key above), instead of needing to
// also bump it on each Scala lib dependency declaration.
"org.scalatest" %% "scalatest" % "2.0.M5b" % "test",
"org.mindrot" % "jbcrypt" % "0.3m" // This is a JAR. 3-part name only. No "%%" since it's a Java project.
),
// Scalatest's defaults are good, avoid Specs2 defaults,
// (which testOptions would contain by default if this were a Play project).
testOptions in Test := Nil,
// Make sure the compiler doesn't throw warnings for lines like "1 toString"
// by enabling postfixOps. Enable feature, unchecked and deprecation compiler warnings.
scalacOptions ++= Seq("-language:postfixOps", "-feature", "-unchecked", "-deprecation"),
// To call our task, we need to bind it to a Project so it has a classpath, dependencies,
// etc to operate against.
evolveTask
)
// And here we're using a git url to depend on another project.
// SBT will clone and build this for us for any projects that
// depend on this project.
lazy val sprouch = RootProject(uri("git://github.com/sam/sprouch.git#2.10"))
lazy val hasher = RootProject(uri("git://github.com/Nycto/Hasher.git"))
// Example of writing a Task.
// The syntax is TaskKey[ReturnValueType](name, description) := { body }
// The := operator is an SBT-ism that means "bind this block of code to this Task".
// At least in this context. There's more to learn by reading the SBT docs, but for the
// most part a little cargo-culting will get you what you want as long as you don't
// forget to use the operator when binding your task's body.
lazy val evolveTask = TaskKey[Unit]("evolve", "Ensures CouchDB Views are current") := {
println("Hello Funky World!")
}
}
// Comment to get more information during initialization
logLevel := Level.Warn
// The Typesafe repository
resolvers += "Maven Central" at "http://repo1.maven.org/maven2/"
resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
// Use the Play sbt plugin for Play projects
addSbtPlugin("play" % "sbt-plugin" % "2.1.0")
// IDEA plugin
addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.2.0")
@sam
Copy link
Author

sam commented Mar 25, 2013

BTW, I've heard that build.sbt files are recursive. So you could use those if you really wanted. But then you're dealing with slightly different syntaxes, and there's a good chance you'd still need Build.scala files anyways, so it's not really an alternative as much as it is a way to pull out declarative settings like repositories, name, etc.

They might ultimately be useful if your build got big enough. It's probably a judgement call more than anything at that point.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment