Monthly Archives: January 2010

Writing a simple PHP sourcecode buildscript in Scala

Scala is a fascinating language. Running on the Java VM, Scala offers a powerful mixture from both the imperative Java world and functional programming including modern techniques like Actors. Personally I prefer to not just learn programming languages, but also try them out while reading through the book.

As I wanted to have nice a build system for my PHP subversion checkout, I used this need as a project to start coding Scala. So what do I exactly need? I want to build multiple versions of PHP from the same branch without checking out the code twice. I also want to configure these builds somewhere without always typing in the parameter list or so. For further versions I want to be able to configure these in a file that can easily be distributed to other machines.

I set down and wrote a parser for a configuration file that can configured build targets which is then build by
the program. The configuration file I used is specialized for this purpose, which is why I didn’t used something like ant or so. The result is called bauaffe-3.0.0a1.jar.

I’ll just show a few things done in the project, but mainly focus on what the nice script can do. Further blog posts will be about the actual implementation.

The configuration looks like this

$ cat ~/.buildmaker
begin default configuration
    define source "/Users/dsp/dev/c/php-src"
    define build "/Users/dsp/dev/c/php-src/build"
    define defaults as
        with "iconv=/opt/local"
    build trunk as
        "php60" using defaults
        "php60-debug" using defaults
            enable "debug"
    build branch "PHP_5_3" as
        "php53" using defaults
            environment PHP_AUTOCONF="autoconf213"
        "php53-debug" using defaults
            enable "debug"
            environment PHP_AUTOCONF="autoconf213"

.
Proper indention is not necessary (as e.g in python).


You might want to think that parsing the configuration file can be difficult. Well, if you use C you would use YACC, if you use PHP, I don’t know what you would have done, but Scala is made to create this kind of Domain Specific Languages (for my the config is a DSL). You can easily transform a EBNF directly to scala code using the JavaTokenParsers provided by the Scala Library. As an example this it the statement that parses the first line:

def begin : Parser[Configuration] =
"begin" ~ ("default" | stringLiteral) ~ "configuration" ~ rep(define | build) ^^ {
case "begin"~name~"configuration"~confs => new Configuration(name, confs)
}

which is directly taken from the BNF:

config ::= "begin" ( "default" | string ) "configuration" ( define | build )*

Did I mention that the actual parser is 170 lines of code with usual indention and formatting?


Configuration
The configuration file is searched in ~/.buildmaker, or if ~/.builmaker doesn’t exists, buildmaker.conf in the current directory. How do you configure the tool? First of all you can specify a configuration. It is usually called “default”. It is not yet supported to name it differently, although the parser is able to parse it. In further versions multiple configurations per file are allowed.

Variables
Variables are set using the define syntax. At the moment you can set the build and source variable as well the defaults variable, which is usually a block of statements that can be used in the branch configurations.

Branches
A branch is configured using the build syntax. You first have to specify which branch to build. Every branch can then configured to have build target with a given set of options. Branch options are:

  • with string: Builds the target with the given extension
  • enable string: Builds the target with the given extension
  • environment string=string: Builds the target with environment variable

. You can specify using defaults which will cause the runner to use the options specified in the defaults define.

At the moment the parser will not do a good job in notifying you what you are allowed to do and what not, although pure parse error will be emitted. You can also not set any other variable than the described once.

Building
Calling

$ java -jar bauaffe-3.0.0a1.jar list
TARGET                         LAST BUILD
php60                          None
php60-debug                    None
php53                          Sat Jan 09 16:55:12 CET 2010
php53-debug                    Sat Jan 09 16:59:37 CET 2010

gives you a list of parsed targets and their last build date. You can build a target using

$ java -jar bauaffe-3.0.0a1.jar 

or build all using

$ java -jar bauaffe-3.0.0a1.jar all

Please notice that the current version requires that you now what you are doing. You might miss some error messages or find them not useful. I’ll change this before the first release, if I’ll do a final version of it. I hope you like the little tool.

Download It!

Scala (pronounced /ˈskɑːlə, ˈskeɪlə/) is a multi-paradigm programming language designed to integrate features of object-oriented programming and functional programming.[1] The name Scala stands for “scalable language”, signifying that it is designed to grow with the demands of its users.