A "Little Language" for Building Projects

Table of Contents


Spooky is an XML vocabulary for describing project directory structures and the default content that the project should contain. Its intended that implementations of the Spooky language will use this description to create a project structure.

The goals for developing this language were to create a means of declaratively describing project structures so that these structures can be reused between projects. This enables developers to produce tools based on these standard project structures, such as standardised build files. It also allows simple documentation describing the contents of any given project to be generated directly from its description.

Spooky could potentially be used as a way to quickly add Ant build files, etc for pre-existing projects that don't use them, e.g. legacy apps using Makefiles. It can also be used for standardising project structures within an engineering team, etc.

(For the reasons behind the project name see this blog entry)

Spooky is part of an ongoing investigation into building little languages using XML tools and infastructure.

Implementation Notes

The current implementation of Spooky uses an XSLT stylesheet to generate an Ant build file capable of:

The build file generated from the project description can then be executed to actually construct the project.

The Spooky Language

While there is no formal schema for the Spooky language, the following DTD fragment describes the essence of the language:

      <!ELEMENT project (meta, structure)>
      <!ELEMENT meta (home, name, creator, description)>
      <!ELEMENT structure (file|dir)*>
      <!ELEMENT dir (file|dir)*>
      <!ELEMENT file #ANY> <-- any elements you like -->
      <!ELEMENT home #PCDATA>
      <!ELEMENT name #PCDATA>
      <!ELEMENT creator #PCDATA>
      <!ELEMENT description #PCDATA>

      <!ATTLIST dir name #IMPLIED
                       type #IMPLIED>
      <!ATTLIST file name #IMPLIED>

A Spooky project file is divided into two sections: a meta block which is intended to contain arbitrary metadata relating to the project as a whole. Supported elements are currently:

The bulk of the project is described in the structure section which contains the description of the projects hierarchical file system using nested dir and file elements.

file elements indicate the location in which a file should be created. Each file element should have a name attribute containing the name of the file. Usual operating system limits for naming files apply. file elements can containg any content you want: plain text or elements from other namespaces. The contents of the file elements will be used as the default content for the file. If none is provided then the file name will be used. (This is due to a limitation in Ant which requires some form of text content for its concat task)

dir elements may contain other directories or files. They should have either a name attribute, indicating its name, a type attribute indicating its "type", or both. If a name is not provided then the directory's name will be the value of its type attribute.

Spooky views directories as typed containers, meaning that they contain a certain type of content, e.g. source (src), unit tests (tests), or docs (docs). This is not intended to be a complete list and should be extended where necessary. The type of a container is intended to affect the generation of default build files for the project. For example a Java project build file may require the definition of containers for source code, compiled classes, api docs, etc.

At present the implementation supports only a single directory of each type. However this is not unduly limiting as similar containers can be combined under a single root directory.

An Example

The following example file can be downloaded here

      <!-- where the project lives, and should be created -->
      <!-- name of the project -->
      <!-- creator (not currently used) -->
      <creator>Leigh Dodds</creator>
      <!-- description of the project -->
      <description>The Example Project</description>
      <!-- describes the project directory structure, assigns
             types to each directory, and indicates some default
      <dir type="bin"/>
      <dir name="docs">
        <dir name="api" type="doc"/>
      <dir type="lib"/>
      <dir name="src">
        <dir name="resources"/>
        <dir name="tests" type="test"/>
        <dir name="java" type="src"/>
      <file name="README.txt">
   This is the README file.
      <file name="BUILD.txt"/>
      <file name="LICENSE.txt"/>
      <file name="CREDITS.txt"/>

Sample output from running this input through the spooky-java implementation.


You can download the complete Spooky project, which includes the following files:

Using Spooky

Select which implementation to use and then transform your project description using the implementation stylesheet. Each stylesheet has a required parameter, spooky-home which should be the full path to where Spooky is installed. This is used to ensure that copying over the prefab build files works correctly.

A second optional parameter called output can also be provided. This should simply be the name of the output file being generated and is used merely to customise the messages displayed during the transformation.

How the Stylesheets Work

Noting that Ant contains a number of tasks (creating directories, concatenating files, macro replacement during file copying, etc) that make it suitable as a way of creating cross-platform scripts for working with file systems, Spooky is implemented using XSLT stylesheets that generate Ant build files.

The implementation is divided up into a basic skeleton (spooky.xsl) which deals with creating the directory structure and default content. This implementation has no concept of directory types, and does not create a default build file for the project.

Using the XSLT import element this basic framework is extended to provide two additional implementations; one for generating Java projects (spooky-java.xsl) and one for generating XML/XSLT projects (spooky-html.xsl). The latter is basically where HTML (or other output) is generated using a single stylesheet applied to source XML documents.

Both of these implementations extend the basic framework by also adding a default Ant build file for the created project. The build files are based on one of two "prefab" build files included with the project. These "prefabs" are simple Ant build files that contain macros for the name and description of the files, and also locations of required directories.

Directories are considered to be simple typed containers whose contents are exposed to particular manipulations, e.g. compilation, copying, etc. Each implementation of spooky defines its own container types, but there are likely to be some basics (src, lib, doc, bin, etc) which are common to all (even if the operations on their contents may differ).

spooky-java requires the following directory types: src, test, bin, lib, doc.

spooky-html requires the following directory types: src, bin. It also supports two additional metadata elements as children of the meta element:

Customising Spooky

There are several ways in which Spooky can be customised.

Altering the prefab build files

The build files provided with Spooky while functional, are merely provided for demonstration purposes. A project will typically require additional Ant tasks, so simply customise the prefabs to provide a better default environment.

Adding a new implementation

Again this is pretty straight-forward. Simple create another XSLT transformation, import the basic spooky framework and override any of the named templates in the framework to customise the output. Generally the only change will be to the makeBuildFile template which is invoked to generate the default build file for the project.