Okay, this is pretty cool. With sbt, you can magically refer to dependencies that are set up as GitHub projects, and those projects don't need to have a jar file, they can just be a source code library. This means you can save your Scala libraries as source code to GitHub (like you normally would), then pull them into your other Scala projects simply by referencing them in your build.sbt
file.
Assuming you're comfortable with sbt, here's a quick six-step example that shows how to pull a GitHub library into a simple Scala project:
1) First, install SBT (0.11.x or newer) if you don't already have it.
2) Once that's done, create an empty directory named something like "SbtGithubTest", then cd
into that directory.
3) Put these contents into a build.sbt
file in that directory:
name := "SoundPlayerTest" version := "1.0" scalaVersion := "2.9.1"
This is a normal, basic build.sbt
file.
4) Put these contents into a file named Test.scala
in that directory:
package foobar import com.alvinalexander.sound._ object TestSbtGithub extends App { // you'll need your own short sound clip val testClip = "/Users/al/Sarah/plugins/DDRandomNoise/HAL9000/this-mission-too-important.wav" val player = SoundFilePlayer.getSoundFilePlayer(testClip) try { player.play // necessary b/c play() doesn't block, and i didn't want to add a // listener to this short test Thread.sleep(5000) } catch { case e:Exception => println(e.getMessage) } }
5) Create a subdirectory named project
, and put these contents in a file named Build.scala
in that subdirectory:
import sbt._ object MyBuild extends Build { lazy val root = Project("root", file(".")) dependsOn(soundPlayerProject) lazy val soundPlayerProject = RootProject(uri("git://github.com/alvinj/SoundFilePlayer.git")) }
As you can guess by looking at that code, this is the code that references the GitHub project you want to use as a dependency. In this case I want to use the source from my SoundFilePlayer project on GitHub.
6) Now use sbt run to compile and run your Scala project:
$ sbt run
You should see sbt do a lot of work on your behalf, and after a lot of work and output related to the magic that it's doing for you, it will run your test program, with the last lines of output looking like this:
[info] Set current project to root (in build file:/Users/al/Projects/Scala/Tests/SbtGithubTest/) [info] Compiling 1 Scala source to /Users/al/Projects/Scala/Tests/SbtGithubTest/target/scala-2.9.1.final/classes... [info] Running foobar.TestSbtGithub [success] Total time: 15 s, completed Jul 1, 2012 8:28:58 AM
Pretty cool, eh?
Referencing multiple GitHub projects
As you start adding more GitHub projects as library dependencies to your project, your project/Build.scala file will change shape a little bit. Here's mine with two library dependencies:
import sbt._ object MyBuild extends Build { lazy val root = Project("root", file(".")) .dependsOn(soundPlayerProject) .dependsOn(appleScriptUtils) lazy val soundPlayerProject = RootProject(uri("git://github.com/alvinj/SoundFilePlayer.git")) lazy val appleScriptUtils = RootProject(uri("git://github.com/alvinj/AppleScriptUtils.git")) }
As you can see, you can just keep chaining the "dependsOn" references.
Using this with Eclipse
For my work today I also installed the sbteclipse plugin, and just generated my Eclipse files with that plugin. By looking at the .classpath file that it generates, you can see some of the magic sbt did for you when pulling in the GitHub project:
<classpath> <classpathentry output="target/scala-2.9.1/classes" path="src/main/scala" kind="src"></classpathentry> <classpathentry output="target/scala-2.9.1/classes" path="src/main/java" kind="src"></classpathentry> <classpathentry output="target/scala-2.9.1/test-classes" path="src/test/scala" kind="src"></classpathentry> <classpathentry output="target/scala-2.9.1/test-classes" path="src/test/java" kind="src"></classpathentry> <classpathentry path="/Users/al/.sbt/staging/4a78a580940b3d38ed80/lib/basicplayer3.0.jar" kind="lib"></classpathentry> <classpathentry path="/Users/al/.sbt/staging/4a78a580940b3d38ed80/lib/commons-logging-api.jar" kind="lib"></classpathentry> <classpathentry path="/Users/al/.sbt/staging/4a78a580940b3d38ed80/lib/jl1.0.1-orig.jar" kind="lib"></classpathentry> <classpathentry path="/Users/al/.sbt/staging/4a78a580940b3d38ed80/lib/kj_dsp1.1.jar" kind="lib"></classpathentry> <classpathentry path="/Users/al/.sbt/staging/4a78a580940b3d38ed80/lib/mp3spi1.9.4.jar" kind="lib"></classpathentry> <classpathentry path="/Users/al/.sbt/staging/4a78a580940b3d38ed80/lib/tritonus_share.jar" kind="lib"></classpathentry> <classpathentry kind="con" path="org.scala-ide.sdt.launching.SCALA_CONTAINER"></classpathentry> <classpathentry exported="true" path="/Sound Tests" kind="src" combineaccessrules="false"></classpathentry> <classpathentry path="org.eclipse.jdt.launching.JRE_CONTAINER" kind="con"></classpathentry> <classpathentry path="bin" kind="output"></classpathentry> </classpath>
To install the sbteclipse plugin, please see this sbteclipse page.
More information
I'll write more about this as I move more of my own library projects to GitHub, but in the meantime, you can learn more about the GitHub syntax at this sbt documentation page. (Search for "github" on that page for the examples.)