nosewheelie

Technology, mountain biking, politics & music.

Archive for the ‘Obi’ Category

Obi source moved to Google Code

without comments

I’ve just moved the Obi code from the internal Workingmouse repository to Google Code. Behold the shiny new home of Obi. Still not much to see, you’ll need to grab the source.

Written by Tom Adams

January 23rd, 2008 at 3:56 pm

Posted in Obi,Scala

Path composition in Obi

without comments

Over the last few days I’ve been progressing steadily with Obi, my Scala-based build tool. I’m starting at the bottom level, building some low level primitives that can then be combined into higher level layers (examples at the end of this post).

Here’s the first simple example, it represents a path to a file on the filesystem.

import org.obi.io.file.FilePath._

// Create a FilePath
val p1 = filepath("/foo/bar.jar")
val p2 = path("/foo/bar.jar")

// Implicit conversion from String to FilePath
val p3: FilePath = "/foo/bar.jar"

// Implicit conversion from FilePath to String
val p4: String = path("/foo/bar.jar")
 

FilePaths can also be combined to form classpaths (I’m working on javac). Here’s some examples of the way you can create classpaths, each of the these will give the classpath string /foo/bar.jar:/foo/baz.jar (on a *nix box). All are syntactically valid Scala, syntax requests/suggestions are welcome, these are some that I came up with, that’ll probably change once it’s used inline in the compilation task.

import org.obi.attr.ClassPath._
import org.obi.io.file.FilePath._

val cp1 = classpath("/foo/bar.jar", "/foo/baz.jar")
val cp2 = classpath(List("/foo/bar.jar", "/foo/baz.jar"))
val cp3 = classpath < < "/foo/bar.jar" << "/foo/baz.jar"
val cp4 = classpath << List("/foo/bar.jar", "/foo/baz.jar")
val cp5 = "/foo/bar.jar" <<: classpath("/foo/baz.jar")
val cp6 = List("/foo/bar.jar", "/foo/baz.jar") <<: classpath
val cp7 = "/foo/bar.jar" << classpath << "/foo/baz.jar"
val cp8 = classpath("/foo/bar.jar") << classpath("/foo/baz.jar")
val cp9 = classpath("/foo/bar.jar") ::: classpath("/foo/baz.jar")
val cp10 = classpath("/foo/bar.jar") + classpath("/foo/baz.jar")
val cp11 = classpath("/foo/bar.jar") + "/foo/baz.jar"
val cp12 = "/foo/bar.jar" :: classpath("/foo/baz.jar")
val cps: String = classpath << "/foo/bar.jar" << "/foo/baz.jar"

With these kind of primitives, it'd be pretty easy to create abstractions such as "library" which would enable a feature such as Maven's dependency management using a syntax similar to buildr's. Here's a simple example of what's currently implemented, syntax can be cleaned up.

val log4j = path("log4j.jar")
val cglib = path("cglib.jar")
val commons_logging = path("commons-logging.jar") < <: log4j
val ehcache = commons_logging << "ehcache.jar"
val hibernate = ehcache + commons_logging + cglib

There's no way to "resolve" dependencies as yet (and won't be for a while) and you get duplicates in the path. But, this would open up things such as (I've no idea if this is valid syntax, I doubt it is):

val hibernate = library(
        dependencies |= ehcache + commons_logging + cglib,
        version "3.2.5.ga")

All in all I think the syntax is quite readable and flexible, it’s also strongly typed. Writing these kinds of DSLs has proved very easy using Scala, I’m quite impressed.

Written by Tom Adams

January 22nd, 2008 at 8:58 pm

Posted in Obi,Scala

Obi is born

with 5 comments

In an effort to learn Scala I’ve been playing around with creating a build tool, called Obi. This is nothing more than me looking for a nice way to learn Scala, but after a couple of days of thinking it looks quite doable.

Obi has three goals; 1) allow me to learn Scala, 2) provide a nice DSL that is expressive and allows use of Scala APIs and idioms and 3) provide the type safety of the Scala language, e.g. a javac task will not compile if you do not pass it a source file.

Here’s an example of the current syntax we’re playing with, this doesn’t actually do anything as yet, but does compile (well, most of it compiles). Each call is pure (side effect free), you need to apply the ! to actually execute the tasks.

import SrcDir._
import Javac._
import AntJavac._

// Two compile targets, Java code and Scala code
val jc = javac(srcdir("src/main/java")).srcfiles(
        List("Foo.java", "Bar.java"))
val sc = scalac.srcdir("src/main/scala").srcfiles(
        List("Foo.scala", "Bar.scala"))

// Equivalent of an Ant "target", Java compile is performed
// before Scala compile, both tasks are executed when called.
def compile {
    !jc
    !sc
}

// Compile Foo.java & Bar.java in src/main/java
!javac(srcdir("src/main/java")).srcfiles(
        List("Foo.java", "Bar.java"))

// Create a compile for Foo.java & Bar.java in src/main.java
List("Foo.java", "Bar.java") >>: javac(srcdir("src/main/java"))

// Create a compile for all files in src/main.java
Dir("src/main/scala")  >>: scala(srcdir("src/main/scala"))

// compile all Scala source files in an "obi" directory
val scalaCompile = Dir("src/main/scala")
        .filter(_.matches("""obi.*\.scala$""")) >>: scalac
!scalaCompile

For those that want to look at other Scala tools, it looks like the only tool available currently is SAnt, Maven and Ant.

If you are interested, Obi is not named after Obi-Wan Kenobi, but after Obi Obi Creek on the Sunshine Coast of Queensland (where I’m doing a throughwalk later this year).

Written by Tom Adams

January 17th, 2008 at 4:44 pm

Posted in Obi,Scala