OASIS

Architecture for building OCaml libraries and applications

Introduction

OASIS is a tool to help OCaml developers to integrate configure, build and install systems in their projects. It should help to create standard entry points in the source code build system, allowing external tools to analyse projects easily.

This tool is freely inspired by Cabal which is the same kind of tool for Haskell.

Everything starts with a single text file, named _oasis, at the root of the project source directory. It contains semi-colon separated fields and sections that describe what is contained in the project and what to do with it.

This file is used to generate a skeleton for build, configure and install systems. Generation can be customized through extra fields or directly inside generated files.

The main entry point is an OCaml script setup.ml. It is self contained. Once generated there is no additional dependencies (just like an autoconf configure script).

OASIS has been created with OCamlbuild in mind. So there is probably some features/bugs that are oriented toward this build system.

Features:

Planned features:

Writing _oasis file

Syntax

The _oasis must be a valid UTF-8 text file. This file identify the toplevel directory of the project.

Identifiers are just like variable names in OCaml, it cannot contains "-" or numbers at the beginning. Strings follow OCaml convention. For extra information on the parser/lexer see Genlex.

A line beginning by # is a comment and is ignored. Blank line are ignored.

The file contains semi-colon fields and sections.

Fields

Fields are defined as field_name: field_value:

The separator ':' can be replaced by '+:' which appends the field_value to the previous value of the value (rather than erasing it). Beware that appending is value dependent, some fields can concatenate, some cannot.

The ':' can also be replaced by '$:', see Conditional value.

Sections

Sections can be an identifier or a string:

Library foo

or

Library "foo".

Section name can be : Library, Executable, Document, Test and SourceRepository. Content of a section is indented relative to the section begin.

Example: # Toplevel fields OASISFormat: 1.0

Library "foo"
  # Library fields
  Path: src/

# Back to toplevel fields
Synopsis: bar

Conditional value

It is possible to define some fields conditionally. Not all fields can be specified this way, only fields that have no good default values and that must be evaluated at runtime is defined.

For example:

A condition is defined using a if ... else ... construct.

Example:

Library bar
  if os_type(Win32)
    Build: true
  else
    Build: false

Available tests are :

The values from these tests are extracted from theoutput of ocamlc -config.

An additional flag test is available which check that the a Flag is defined. See the chapter on the Flag section.

Tests and flags can be combined using standard boolean operation:

For boolean fields, you can replace the if ... else ... construct by $:.

For example:

Library bar
  if os_type(Win32)
    Build: true
  else
    Build: false

is equivalent to:

    Build$: os_type(Win32)

Features

OASIS allows to experiment with non-official, experimental features. These features are included in the code but are not activated by default. In order to activate them. You need to list them in AlphaFeatures or BetaFeatures of your _oasis.

Alpha features are under development and may only be used for testing. They are not yet well defined, they are evolving quickly and may be removed in future release of OASIS.

Beta features are features almost ready to be shipped, they mostly need to be polished before release. You may use them as they will probably be ready for the next version of OASIS.

Once you have activated a features, you get access to more fields and some parts of the code maybe be activated as well.

Features allow the OASIS development team to release experiment early and should avoid long delay between release.

Available features:

Package

Package fields are defined outside sections. They apply to the whole project.

Fields:

BuildDepends and BuildTools are appended to all sections and not used directly in the package.

Sections

There are 6 possible sections:

None of these sections are mandatory. Library, Executable, Document and Test can be dependent on each other. This not a problem as long as there is no cycle inside the dependency graph. Dependencies can be expressed through BuildDepends and BuildTools fields.

Flag

A flag section defines a configure command line option. It will be translated to to --enable-XXX and --disable-XXX for the command line. It can be used inside conditional fields.

Fields:

Common fields

These fields are used inside Library and Executable.

Fields:

All files defined in the section are relative to Path.

Library

Define an OCaml library. OCaml API is generated using ocamldoc applied to Modules with BuildDepends required flags.

Fields:

Object

require BetaFeatures: section_object

Define an OCaml object file. It is very close to a library except that an object when linked will evaluate all its toplevel statement. This may be ideal if you want to call for example an initialisation function.

Fields:

Executable

Define an OCaml executable. If the executable is a bytecode that use internal library, an helper script can be generated to set library path.

Fields:

Document

Define a generated document.

Fields:

Test

Define a test to run.

Fields:

SourceRepository

Define VCS information. There are two special identified repositories:

Fields:

Supported VCS types are: darcs, git, svn, cvs, hg, bzr, arch, monotone.

License

We have adopted a DEP-5 license style description.

The reason of this format is to have machine-readable license description. Using this former work, we hope to be compatible with future standards of Debian.

We have limited the number of license to:

And license exception to:

You can specify a license version using a dash and only digits or dashes at the end of the license short name.

Examples :

Data files

DataFiles fields help to install extra data inside $datadir/$pkg_name. This field is a comma separated list of file, with optional value inside parenthesis. You can override target directory using fn ($datadir/other_location).

You can use wildcard * but only for a filename and followed by a single dot extension: dir/*.html is valid but dir/* and dir/*.tar.gz are not valid.

Substitution inside text

Substitution is performed using Buffer.add_substitute.

Variable are evaluated using environment. This is a mix of various data coming from _oasis file, ocamlc -config output and configure tests. So environment variables depends of each project. You can have a precise idea of what variables is available looking at the file setup.data.

Here is a list of standard variables:

Other variables are defined depending on your _oasis file:

It is also possible to apply transformation through functions. This is useful when you need to use properties that need to be determined at runtime:

For example $(utoh src/test.ml) will be replaced by src\test.ml on Windows.

Customization of generated files

When OASIS generates file, it always replace only lines between OASIS_START and OASIS_STOP. These keywords are commented and followed by data to check that content is unchanged.

If the file doesn't exist, OASIS will create the whole file using default header and footer.

If OASIS detects a change inside the section being replaced, it will create a backup of the file and issue a warning.

Customization of setup.ml

setup.ml as any generated files can be customized in its header and footer. Moreover it can be customized through hook in the code directly.

TODO: explains hook.

Using OASIS during software development

Since _oasis becomes a central place of information about the building process, it can be quite cumbersome to run again and again oasis. You can avoid it using the -dev flags when calling oasis for the first time. This way it will rebuilt very dependents build files each time you call ocaml setup.ml. A setup.ml built this way, should not be distributed. This intended for development purpose only.

Plugins

OASIS is basically built around plugins. They are used to define specific behavior for generating files and including their own code in setup.ml.

There are 6 categories of plugin:

Plugin Custom (doc, conf, test, install, build)

Version: 0.4

This plugin allow to define a set of three commands to perform each steps, associated with the following fields:

XXX stands for Conf, Build, Doc, Test, Install or Uninstall.

Action to run is a simple shell command. It can contain substitution variables as defined in [this section][#substitution].

Package fields:

Document fields:

Test fields:

The file setup.data remains mandatory, even when using the custom plugin. You must create it. A simple touch setup.data; ./configure should be enough, though.

Plugin None (install, test, build, doc, conf)

Version: 0.4

This plugin basically does nothing. It helps to replace mandatory step by nothing.

Plugin OCamlbuild (build, doc)

Version: 0.4

This plugin uses OCamlbuild to generate a build system. It is the default value for BuildType.

It is also possible to use this plugin for Document. In this case, OCamlbuild will also be involved in the generation of a particular document.

Package fields:

Document fields:

Plugin Internal (conf, install)

Version: 0.4

This plugin is the default value for the ConfType and InstallType. It represents a default behavior for configuring and installing OCaml project.

The configure part take care of checking:

The install part take care of installing executables, libraries and data files using standard environment variable ($bindir, $datadir et al).

Plugin META (extra)

Version: 0.4

This plugin is an helper to generate a META files that can be distributed and install with a library. It uses library name, version, synopsis and dependencies to generate matching fields in META.

Library fields:

Plugin StdFiles (extra)

Version: 0.4

This plugin generates standard files like README.txt, INSTALL.txt and AUTHORS.txt. These files will summarize data contains in _oasis.

The .txt extension has been added to allow easy editing/viewing under Windows and other system that look for extension to determine file type.

Package fields:

Plugin DevFiles (extra)

Version: 0.4

It helps to generate a toplevel Makefile and configure files which only invoke setup.ml. It aims to provide good old entry points.

Package fields:

Building and installing

The file setup.ml is the base system to run every targets. It contains a self contained OCaml script, that only depends on OCaml standard installation that doesn't require using stublibs (no Str or Unix). This constraint is required to be fully portable even on system that doesn't support dynamic loading.

The file setup.data is the result of the configure step and contains data that can be used for other step. It is removed only in distclean target. The format of this file is on variable and values per line: var="value". The value is an OCaml string. The file in this form can be read by make and sh. Once generated this file should not be modified.

The file setup.log contains a list of action done and is used and updated by action done and cancel (e.g. action install log files installed which action uninstall remove).

ocaml setup.ml -configure

This is the first step to perform. It is mandatory. It runs various test of the build environment to check that everything required is installed.

ocaml setup.ml -build

This step is mandatory. Build libraries and executables.

ocaml setup.ml -test

This step is optional. Run defined test. Need the build step before.

ocaml setup.ml -doc

This step is optional. It builds API documentation for library and extra documentation as defined in Document.

ocaml setup.ml -install

This step is mandatory. Install what has been built in build and doc step. Also install data files as defined in DataFiles fields.

ocaml setup.ml -uninstall

This step is optional. Remove files and libraries installed.

ocaml setup.ml -reinstall

This step is optional. Perform an uninstall and then an install step.

ocaml setup.ml -clean

This step is optional. Clean generated files during build and doc steps.

ocaml setup.ml -distclean

This step is optional. Try to go back to pristine source state.

ocaml setup.ml -all

This step is optional. Run configure, build, test and doc step in one run.

OASIS usage

Command line

OASIS v0.4.5 (C) 2009-2014 OCamlCore SARL, Sylvain Le Gall

oasis [global-options] subcommand [subcommand-options]

Environment variables:

OASIS_PAGER: pager to use to display long textual output.

Global command line options:

This program allows to manipulate OASIS enabled package, i.e. package that contains an _oasis file. It is made of several subcommands that provide features around this file. Some subcommands require the installation of third party plugins.

You need to specify a subcommand as defined in the following above.

-quiet

Run quietly

-info

Display information message

-debug

Output debug message

-ignore-plugins

Ignore plugin's field.

-C dir

Change directory before running.

-help|--help

Display this list of options

Available subcommands:

check

Check an _oasis file

help

Display help for a subcommand

manual

Display user manual

query

Query an _oasis file

quickstart

Launch an helper to write _oasis file

setup

Translate _oasis into a build system

setup-clean

Clean all template files from their content

version

Display the version of the OASIS program running

Subcommand check

This subcommand load an _oasis file and apply standard checks.

Usage: oasis [global-options] check [options]

Options:

-oasis fn
_oasis file to use.

Subcommand help

This subcommand display help of other subcommands or of all subcommands.

Usage: oasis [global-options*] help [subcommand|all]

Subcommand manual

This subcommand print the manual of OASIS. It uses the markdown syntax to print it and more precisely the pandoc extension of this syntax.

This manual describes the command line tool oasis, the _oasis file format and the generated setup.ml file.

Usage: oasis [global-options] manual [options]

Options:

-o fn
Output manual to filename.

Subcommand query

This subcommand load an _oasis file and search its content for information.

The query string follow this convention:

Query examples:

You can use multiple queries, they will be executed in order.

Usage: oasis [global-options] query [options] query*

Options:

-oasis fn

_oasis file to use.

-separator str

String to add between answers.

Subcommand quickstart

This subcommand is an helper to write _oasis file. It asks a serie of questions to create an initial _oasis file. The questions depend on the level of the user, you can set this level with the -level command line option.

At the end of the process, you have the possibility to edit, to display or to write the generated file.

Usage: oasis [global-options] quickstart [options]

Options:

-oasis fn

_oasis file to use.

-level {beginner|intermediate|expert}

Quickstart level, skip questions according to this level.

-machine

Computer readable questions for automatic completion.

-real-oasis

Use the real 'oasis' executable filename when generating setup.ml.

-setup-update {none|weak|dynamic}

Define the way setup.ml should update when _oasis change.

Subcommand setup

This is the main subcommand of oasis, it compiles the _oasis file into a self contained setup.ml. The generated file handle the various step to configure, build and install your project.

This command can generate 3 differents kind of setup.ml, depending on the -setup-update command line argument:

If you want contributor to checkout your VCS and be able to work without oasis installed, prefer the 'weak' mode. If you want to avoid VCS history pollution, use the 'dynamic' mode. Always distribute tarball with mode 'none'

Usage: oasis [global-options] setup [options]

Options:

-oasis fn

_oasis file to use.

-real-oasis

Use the real 'oasis' executable filename when generating setup.ml.

-setup-update {none|weak|dynamic}

Define the way setup.ml should update when _oasis change.

Subcommand setup-clean

This subcommand go through every generated files and remove the replaceable part in it. It also tries to clean backup files made by a failed SetupDev subcommand invocation.

The replaceable part of a generated file is everything between OASIS_START and OASIS_STOP.

Usage: oasis [global-options] setup-clean [options]

Options:

-oasis fn

_oasis file to use.

-replace-sections Empty

replace section in generated files (i.e. remove content between OASIS_START and OASIS_STOP).

-remove Empty

remove files which have unaltered header and footer.

Subcommand version

Display version of the oasis executable.

Usage: oasis [global-options*] version