Let the orchestration waf through the suite.
Python Shell
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


worch - Let the orchestration waf through the suite.

Caveat: worch is now considered obsolete and is not maintained. Instead, please check out Spack.

This package provides a waf based Python module orch, short for “orchestrate”, which allows the creation of a meta-build system for a suite of related packages. The system is centered around a simple configuration language describing the installation and a number of interpreting methods to produce installation tasks. Finally, these tasks are handed to waf for sequenced execution.


Some features of worch:

  • a simple, concise and flexible text-based configuration language which can fully describe the installation of a complex software suite.
  • the Worch machinery itself is distributed in standard Python packages available in PyPI to allow for a flexible and automated installation. Add-on tools or user configuration may be distributed likewise.
  • automated installation includes downloading of source archives in common formats, their unpacking, source preparation using popular configuration methods, building and finally installing and any additional steps the user defines
  • the user defines the conventions that set file/directory installation patterns.
  • batteries included for driving some popular native build mechanisms. Novel build systems can accommodated by providing custom feature methods which may be dynamically incorporated based on the configuration.
  • in order to assure proper build order while allowing parallel builds, dependencies can be defined either implicitly by linking installation steps via the files they require or produce or by explicitly declaring dependencies between any two steps by name.
  • idempotent build steps, repeating a build does not repeat successful steps.
  • no hidden failures, errors abort the installation.
  • packages can be grouped to assure parts of the suite are entirely built before others.
  • while heavy use of environment variables is discouraged one can define build environment variables in the configuration. These can be applied on a per-package basis or can be defined on a package or group basis and applied to those packages which require them.


While waf supports all the way back to Python 2.3, worch requires at least Python 2.6 (eg, Sci. Linux 6). A script is provided to help build a modern version of python from source. See this doc for more info.


Some of the terms and concepts used by Worch.

the collection of all the software installed together with Worch
software from a single source to be installed as an atomic unit. A package has a name and a version
a collection of related packages that must be fully installed independent from others in the suite
the installation of a package is broken down into a linear, series of steps. The steps include “download”, “unpack”, “patch”, “prepare”, “build” and “install”. Fully qualified steps names include the name of the package on which they operate, for example: <package>_<step>
one or more steps collected together in a named and reusable manner (“feature” is in the waf sense of the word)
a mechanism to load external Python code largely to provide new features
before a step can run it may require another step to run either in an absolute way or by depending on the production of some file by that other step.

Getting started with Worch

The use of Worch consists largely of editing a configuration file set and running waf with the orch Python module to interpret them.

Worch comes with example configuration files that build a few simple Free Software programs. To exercise them:

Install waf

Worch includes a copy of waf program in the top level directory but see the waf book for if you wish to explicitly install.

Install Worch

Worch installs in the usual manner for Python packages with the exception that the code relies on the waflib module which is made available by importing the orch module via the waf command.

Recommended installation method

It is recommended to install Worch in a Virtual Environment. To create one do:

$ virtualenv /path/to/venv
$ source /path/to/venv/bin/activate

If you do not have the virtualenv script, see this link for downloading it.

Whether installing into a Virtual Environment or not, Worch may be installed like:

$ pip install worch

Development installation

To develop Worch itself, first set up a Virtual Environment as above and then do:

$ git clone git://github.com/brettviren/worch.git
$ cd worch
$ python setup.py sdist
$ pip install dist/worch-X.Y.Z.tar.gz
(hack away)
$ pip uninstall -y worch
$ python setup.py sdist
$ pip install dist/worch-X.Y.Z.tar.gz

First run of waf

Regardless of the installation method (and of Worch itself) the first time waf is run by you it will unpack itself. This means it needs to reside in a location that is writable by the user. To trigger an unpacking one may run:

$ waf --version

Run waf on the worch configuration files

Worch installs some example configuration files which you can browse in the examples source directory. A configuration is given to Worch by specifying the main file. If specified as a relative path the file will be searched for in the current working directory or, if not found, in the installed location.


Worch needs a waf wscript file to drive the build. A generally suitable one is provided with the Worch distribution

$ cd /path/to/work
$ cp /path/to/venv/share/worch/wscripts/worch/wscript .
$ waf --prefix=/path/to/install \
      --orch-config=examples/simple/*.cfg \
Setting top to  : /path/to/work
Setting out to  : /path/to/work/tmp
'configure' finished successfully (0.065s)

$ ls ./tmp
c4che  config.log


  • if multiple configuration files are given; they are effectively concatenated and the wildcard character (*) will be interpreted by Worch. (tcsh users: beware that your shell sucks)
  • often just a main file needs to be specified and any other ones are implicitly loaded.
  • the ./tmp directory is created as directed by the out variable in the main wscript file and holds all intermediate build files
  • if the configure step is repeated it requires repetition of the options as well.
  • --zones=orch can be passed (to configure and build) to get more verbose output from waf.

Configuration file location

Worch will try to find configuration files specified by --orch-config following these rules in order:

  1. If absolute path, find the file absolutely, otherwise
  2. first check assuming relative to current working directory
  3. relative to any paths listed as elements of the environment variable WORCH_CONFIG_PATH
  4. relative to sys.prefix
  5. relative to =sys.prefix + ‘/share/worch’


The build command is default and need not be explicitly stated.

$ waf [-j4] [-vvv] > log
Waf: Entering directory `/path/to/work/tmp'
[ 1/18] cmake_seturl:  -> tmp/cmake-2.8.8.url
[ 2/18] cmake_download: tmp/cmake-2.8.8.url -> tmp/downloads/cmake-2.8.8.tar.gz
[ 3/18] cmake_unpack: tmp/downloads/cmake-2.8.8.tar.gz -> tmp/sources/cmake-2.8.8/bootstrap
[ 4/18] cmake_prepare: tmp/sources/cmake-2.8.8/bootstrap -> tmp/builds/cmake-2.8.8-debug/cmake_install.cmake
[ 5/18] cmake_build: tmp/builds/cmake-2.8.8-debug/cmake_install.cmake -> tmp/builds/cmake-2.8.8-debug/bin/cmake
[ 6/18] cmake_install: tmp/builds/cmake-2.8.8-debug/bin/cmake -> ../../../../../../tmp/worch-simple-example/cmake/2.8.8/debug/bin/cmake
[ 7/18] hello_seturl:  -> tmp/hello-2.8.url
[ 8/18] bc_seturl:  -> tmp/bc-1.06.url
[ 9/18] bc_download: tmp/bc-1.06.url -> tmp/downloads/bc-1.06.tar.gz
[10/18] hello_download: tmp/hello-2.8.url -> tmp/downloads/hello-2.8.tar.gz
[11/18] bc_unpack: tmp/downloads/bc-1.06.tar.gz -> tmp/sources/bc-1.06/configure
[12/18] hello_unpack: tmp/downloads/hello-2.8.tar.gz -> tmp/sources/hello-2.8/configure
[13/18] bc_prepare: tmp/sources/bc-1.06/configure -> tmp/builds/bc-1.06-debug/config.status
[14/18] hello_prepare: tmp/sources/hello-2.8/configure -> tmp/builds/hello-2.8-debug/config.status
[15/18] bc_build: tmp/builds/bc-1.06-debug/config.status -> tmp/builds/bc-1.06-debug/bc/bc
[16/18] bc_install: tmp/builds/bc-1.06-debug/bc/bc -> ../../../../../../tmp/worch-simple-example/bc/1.06/debug/bin/bc
[17/18] hello_build: tmp/builds/hello-2.8-debug/config.status -> tmp/builds/hello-2.8-debug/src/hello
[18/18] hello_install: tmp/builds/hello-2.8-debug/src/hello -> ../../../../../../tmp/worch-simple-example/hello/2.8/debug/bin/hello
Waf: Leaving directory `/path/to/work/tmp'
'build' finished successfully (8m3.605s)

$ waf
Waf: Entering directory `/path/to/work/tmp'
Waf: Leaving directory `/path/to/work/tmp'
'build' finished successfully (0.028s)

$ ls ./tmp
bc-1.06.url  builds  c4che  cmake-2.8.8.url  config.log  downloads hello-2.8.url  sources

$ ls /tmp/worch-simple-example/*/*/*
bin  info  man

bin  doc  man  share

bin  share


  • parallelism can be used with the -j option, verbosity increased with -v
  • logging from each step is kept atomic and is not printed until that step finishes
  • ordering of steps is determined by dependencies
  • rerunning waf does not repeat the successful steps
  • waf users may expect an explicit “waf install” but it is not used by Worch
  • all installation files are placed under the directory set by the --prefix option in the configure step
  • this example installs each package into a specific <name>/<version>/<qualifier> directory, but other patterns are possible

Configuration File Syntax and Interpretation

The main user interaction, besides running waf as above, is in writing configuration files to describe the installation.

The Worch configuration files are in the standard syntax expected by the Python ConfigParser module (aka “INI” format). They consist of a number of named sections followed by key/value pair settings. They section title is surrounded by square brackets ”[]” and the key/value pairs are separated by either “===” or ”:”.

# this is a comment
key = value
key: value

Worch adds to this simple syntax some these features:

  • string value interpolation
  • hierarchical structure


Most values are interpreted having a scalar string type. These values may contain the names of other keys surrounded by curly braces ”{}”. These will have their value replaced by Worch.

key1 = World
key2 = Hello {key1}

The result is that the value of key2 will be ”Hello World”. Keys must be used in the same hierarchical scope as they are defined. The hierarchy is described in the next section. In addition to interpolation being run on the items in the configuration, Worch provides a few additional key/value pairs:

output of uname stored as kernelname, hostname, kernelversion, vendorstring, machine
a name formed from the kernelname and machine
the native GCC version
the native GCC notion of the hosting machine architecture
the native multiarch string (Debian extension)
the libc version
the UPS flavor string

Additional keys may be provided based on the existence of keys in the configuration.

at most the first two digits of the “.”-separated version string
version string with “.” replaced with “_”
version string with “.” removed
all tags concatenated with dashes
all tags concatenated with underscores

Hierarchical configuration

Worch partitions the configuration logically into packages and groups of packages. This partitioning is done by interpreting certain keys as holding a list of sections names of a certain type. The mapping of key to type is held in the special keytype section. The keytype section used by Worch is:

packages = package
groups = group

This means that if the keys packages or groups are encountered, their values are interpreted as a list of section names of the “type” ”package” or ”group”. The interpretation begins at with one section, ”start” by default and follows down any keytype keys.

groups = group1, group2
key = value_from_start

[group group1]
packages = package1, package2
key = value_from_group1

[package package1]
key = value_from_package1

[package package2]
some_other_key = {key}

The hierarchy built in this way causes all simple, scalar values to be copied down to the leafs, which are packages in this case. This means that each package gets a copy, possibly customized, of all scalar key/value pairs. The interpolation occurs late so resolution is performed with this final, leaf set. Using the example above:

has key set to value_from_package1
has key and some_other_key both set to value_from_group1

Specifying inter-package dependencies

The configuration file can expresses dependencies between steps of different packages in two ways.

  • implicitly through required/produced files
  • explicitly by naming a package+step on which the current a particular package step depends

Implicit file dependencies

Explicit package step dependencies

To express an explicit dependency a package configuration section specifies a depends key with a comma-separated list of <step>:<package>_<step> elements. For example:

depends = prepare:gmp_install


Building a package is split into a number of steps. A step is identified by a simple name. There is no limit to step names but a limited set are identified as covering most meta-build operations. They are:

write the URL of the source archive file (or repository) into a file to start the package dependencies
produce the source archive file (or repository clone) based on the URL
produce a directory of pristine source code
modify the source code, in place, typically by applying a patch
prepare the source for building, for example running cmake or autoconf’s configure script
produce binaries from the source
place build results to a final installation location

A step may have a default, associated directory in which it is run. The directories are specified by the following configuration variables. These locations and their associated steps are:

unpack, patch
prepare, build, install


The common steps are then grouped and implemented by “features” which can then be applied to different packages. Features use the steps as “touch stones” so that different features can be swapped while others can be shared. An example is the tarball and vcs features both provide through to the “unpack” step. The “cmake” and “autoconf” features provide the “prepare” step.

Here is a list of “features” that worch provides and the steps they implement:

download and unpack a tar/zip file (seturl, download, unpack)
clone or checkout source from a version control system (git, hg, cvs, svn), (seturl, download, unpack)
apply a patch to the source (patch)
a generic source preparation feature (prepare)
prepare source using autoconf configure script (prepare)
prepare source by calling cmake script (prepare)
run make/make install (build, install)
install a Python package via setup.py (prepare, build, install)
special purpose feature for installing Pythia6 (prepare, build, install, and feature-specific steps)

The rest of this section gives some examples

Download and unpack

Almost all packages start by a download of a source archive (tar or zip file or git repository). Worch will handle these steps using the tarball feature. The example below shows how the GNU hello package makes use of this feature. A full, working example is in ./examples/simple.

[group gnuprograms]
features = tarball autoconf
srcpkg_ext = tar.gz
source_unpacked = {package}-{version}
source_package = {source_unpacked}.{srcpkg_ext}
download_dir = downloads
source_dir = sources
source_url = http://ftp.gnu.org/gnu/{package}/{source_package}

[package hello]
version: 2.8


  • The tarball feature is added to a special features key which is interpreted as a space separated list (fixme: should allow for comma-separated - space separation exposes a waf detail)
  • The package section is brief as it inherits from the group and only provides the information unique to the pacakge
  • The tarball feature needs to know where the download and source directories are, how the source package, URL and eventual unpacked directory are named
  • The extension is pulled out to its own variable to accommodate multiple packages that are similar but may be archived/compressed differently (eg, another GNU package that happens to be compressed with BZ2)


The vast majority of packages are built with the configure/make/make install pattern provided by GNU autoconf. The autoconf feature can invoke this pattern. It follows on from the tarball feature and thus requires some of the same keys to be defined. One does not typically need to redefine these but rather they are used in the same context. Here is a follow-on to the hello example above but just showing the parts relevant to the autoconf feature. Again, see the simple example for a fully working instance.

[group gnuprograms]
tags = debug
features = tarball autoconf
source_unpacked = {package}-{version}
source_package = {source_unpacked}.{srcpkg_ext}
build_dir = builds/{package}-{version}-{tagsdashed}
install_dir = {PREFIX}/{package}/{version}/{tagsdashed}

[package hello]
version: 2.8
depends = prepare:bc_install
build_target = src/hello
install_target = bin/hello


  • Here a tags key is introduced. Tags are used to indicate variants in the build. In this example a debug version of hello should be built (fixme: tags are not yet supported).
  • The build and install directories are specified while some source-related keys are reused from the tarball feature
  • A build and install target must be specified in order to satisfy waf requirements
  • A depends key is used to place an artificial, contrived dependency on another package step.

Mimicking autoconf

Many native build systems can use the autoconf feature by explicitly defining some variables that it uses. For example, building CMake does not use autoconf but it is close. Its package section can be defined like:

[package cmake]
features = tarball autoconf
unpacked_target = bootstrap
prepare_script = bootstrap

This causes the tarball and autoconf features to look for a bootstrap instead of a configure script.

Writing your own tool providing features

See ./doc/tools.org.

waf/worch tricks

Rerunning a step

Waf honors expressed dependencies and will rerun a step when a dependency changes. However, not all dependencies that could be expressed are. In particular, if a step completes successfully and then one changes either its source code (which is not in a file explicitly depended on) or the worch configuration files then waf may have no way to notice a change.

However, waf provides a ”step” command which will rerun an isolated step or steps without regards to dependencies. To indicate the step on uses the --files options. Waf finds the step that has been declared to produce the given file(s) and reruns it.

In general, one must have detailed understanding of the implementation of a feature and its steps in order to know what to give to the --files option. However, worch consistently creates a special “control” file after the successful completion of each step. This control file is consistently named like:


The control_dir may be defined in the configuration but defaults to simply ”controls/” and is found in the “out” directory.


As an example, in the ORKA build it was found that the Geant4VMC package requires Geant4 to include the G3toG4.hh header (despite that we try telling the package NO_G3TOG4). To reconfigure Geant4 to include this header in the install requires adding -DGEANT4_USE_G3TOG4=ON to the CMake command line. In order to avoid rebuilding the entire suite and just rerunning prepare, build and install steps for Geant4 one can do:

# rerun the configure step to pick up 
# the changes to the configuration
$ waf [...] configure  

# manually have waf (re)run each Geant4 step
$ waf step --files=tmp/controls/geant_prepare
$ waf step --files=tmp/controls/geant_build
$ waf step --files=tmp/controls/geant_install

# ditto for g4vmc
$ waf step --files=tmp/controls/geant4_prepare
$ waf step --files=tmp/controls/geant4_build
$ waf step --files=tmp/controls/geant4_install

# sop up any collateral changes, or continue with steps not yet run
$ waf

Debugging info

Worch can produce a lot of debugging information. It has the concept of “zones” of logging. To add some verbosity just for worch logs one can do:

$ waf --zones=orch [...]

Log files

Every step which involves running an executable produces a log file in:


The log file is composed of sections beginning with the following:

the command line run
the current working directory in which the command ran
the step’s dependencies (input and output files) followed by a detailed dump of internal waf information
a dump of the shell environment variables
WORCH command output
the last part of the log file shows any output from the command itself

The log file for long-running steps may be found and monitored “live” by doing something similar to the following commands:

# Find the updating log
$ ls -ltr tmp/logs/ | tail

$ tail -f tmp/logs/worch_ilcroot_build.log.txt

Here ”tmp/” is the directory specified by the ”waf --out=tmp” flag.

Reproducing failures

If a command that is run by a step fails a shell script will be produced with everything that should reproduce the failure in-place (it is very much not portable). The location of the shell script is the current working directory where the command ran and is reported by waf. It should be run from the directory that holds it in order to reproduce the failure.

Others in this space

A truly unique project is rare and worch is no exception. This section lists some projects that are similar to worch that I’ve come across.

The GNU package manager (more details in ./doc/guix.org)