Monday, November 26, 2012

Sharing information between SBT build.sbt and your project code...

One way to share data between SBT build.sbt file and your project code is to automatically generate a class. This is quite easy, everything is done directly inside build.sbt file :
import AssemblyKeys._

seq(assemblySettings: _*)

name := "ScalaDummyProject"

version := "0.1.3"

scalaVersion := "2.9.2"

scalacOptions ++= Seq("-unchecked", "-deprecation")

mainClass in assembly := Some("dummy.Dummy")

jarName in assembly := "dummy.jar"

libraryDependencies += "org.scalatest" %% "scalatest" % "1.8" % "test"

libraryDependencies += "junit" % "junit" % "4.10" % "test"


sourceGenerators in Compile <+= 
 (sourceManaged in Compile, version, name, jarName in assembly) map {
  (dir, version, projectname, jarexe) =>
  val file = dir / "dummy" / "MetaInfo.scala"
  IO.write(file,
  """package dummy
    |object MetaInfo { 
    |  val version="%s"
    |  val projectName="%s"
    |  val jarbasename="%s"
    |}
    |""".stripMargin.format(version, projectname, jarexe.split("[.]").head) )
  Seq(file)
}

And that's all, then once done, you can write such things :
package dummy

object Dummy {
  val message = "Hello %s by %s release %s".format(
       util.Properties.userName,
       MetaInfo.projectName,
       MetaInfo.version
  )

  def main(args:Array[String]) {
    println(message)
  }
}

Full example is available on github.

Using custom libraries directly in SBT task code...

Using custom library directly in SBT task code is quite easy, just add your dependencies into project/plugins.sbt, and then your imports in built.sbt and that's all folk.

The following example shows how to use a custom SSH API (JASSH) to send an executable jar to a remote server :

import AssemblyKeys._
import jassh._

seq(assemblySettings: _*)

name := "MyProject"

version := "0.1"

scalaVersion := "2.10.0-RC2"

mainClass in assembly := Some("com.mycompany.myproject.Main")

jarName in assembly := "myproject.jar"


...


TaskKey[Unit]("export", "Send 2 server")<<= (assembly in assembly) map { jarfile=>
  SSH.once(host="localhost", username="test") { ssh =>
    println("Exporting %s on %s".format(jarfile.getPath, ssh.execute("hostname")))
    ssh.send(jarfile.getPath, jarfile.getName)
  }
}

The content of SBT project/plugins.sbt :
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.1.0")

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.8.4")

libraryDependencies += "fr.janalyse" %% "janalyse-ssh" % "0.9.5-b3" % "compile"

resolvers += "JAnalyse repository" at "http://www.janalyse.fr/repository/"

It is worth noting that dependency management system is used both for your project and for your build specification.