Build Model

The first thing to get to grips with is the build model - how a build is structure, as everything else follows from it. What do we mean by this? Well EBuild is a structured build system, where the primary element is the project. EBuild imposes a system on how projects are named, layed out and organised within source control. This has been described as opinionated software and is done for 3 reasons

Projects are organised into what is known as a DAG. In almost any software system this structure exists, even if it is not formally acknowledged. In complex build systems the DAG can become quite extensive and unless it is formally managed this rapidly becomes a development issue. In fact there is more than one DAG to be considered. A project will have its own DAG, but the build code (in EBuild, builders and assemblers, more on that later) also has its own DAG.

Projects are given two part names <organisation>-<name>. The organisation provides a unique namespace to prevent namespace clashes (important for reuseable projects), but is also generally just a good idea as it makes the structure of the build more self documenting.

 org.acme-library.net
	

From this project, just looking at its name, we know the organisation and can have a good idea about its purpose (reusable library code, related to networking).

Projects are organised in a flat, non-hierarchical way. Even if a formal hierarchy made sense it would make interoperating with IDEs problematic as they generally work with flat workspaces (e.g. eclipse). A 'soft hierarchy' can be described, and is even to be encouraged when naming a project. So continuing with our example we may have:

 org.acme-library.net
	 org.acme-library.util
	 org.acme-main
	

Build tasks and relationships between projects are defined within the meta/ directory within the project. The layout, syntax and specifics of this will be described later. Here the projects describe the following dependency graph (org.acme has been omitted):

 main                -> library.net
	                     -> library.util
	

Modules, Components ... etc.

EBuild distinguishes between 2 types of project. Modules and components. A module contains source code and describes the dependencies it requires. A component describes the packaging of modules and other files. In EBuild end products are components (although not all components are end products). This division gives flexibility on how code is packaged (combined, seperated into libraries, both).

So far our example only contains modules. We can further elaborate our example by adding a component 'org.acme-download'. An extra module has been added containing some extra files we will package with our component. It contains other files we may wish to have in our download (as the download component does not actually contain any files), such as run scripts, readmes, licenses, a basic manual ... etc.

 org.acme-library.net
	 org.acme-library.util
	 org.acme-main
	 org.acme-download.files
	 org.acme-download
	

Shared Build Part Projects

There is a third type of project. Tentatively called a 'Shared Build Part' these projects contain build information that we wish to share between projects. This configuration is then imported into

Currently the only shared information is references to other repositories.

Builders, Assemblers

So far we have managed to not even discuss how a module is built, or a component assembled. Lets say in our example all our code modules are java modules and are built with the standard ebuild java builder. The java builder will use the dependency information provided to construct its build time class path. We could describe the build dependency graphs although they are not hugely interesting. In the simple case, for one module we have something like:

   library.util ---built-by---> ebuild-build.java.compile 
	

In this example we decide that we need to have some custom rpc stubs generated in our main project. This requires us to have our own builder org.acme-build.stubgen. Builders are java modules, with a class that implements the interface in the ebuild plugin api. We do not need to worry about components for them as they are run and executed by ebuild. The build dependency of the main project now looks like

 main (build)  ---built-by---> build.stubgen
	               ---built-by---> ebuild-build.java.compile 
	

Our project list now looks like:

 org.acme-build.stubgen
	 org.acme-library.net
	 org.acme-library.util
	 org.acme-main
	 org.acme-download.files
	 org.acme-download
	

Here, for quite a simple project there has been quite a proliferation on projects. Although crucially most of the projects are quite trivial. Might we consider this to be a bad thing? No, in reality, if we were to use a different build system to build essentially the same outputs, but with fewer projects, we would still have all of the same elements, only they would not all be named (which is inconvenient for technical thought/discussion) and formally managed.

Repositories

Repositories contain either source projects or released artifacts. EBuild also supports sourcing dependencies from maven & ivy repositories.

Versioning

Projects can be versioned in two ways, which we term

In branch & revision the default revision is trunk. When declaring a dependency it is also possible to target the head revision of a given branch. In this case the latest revision of a given branch of a repository is what is used. This revision gets updated whenever ebuild is run on the workspace (either build or ide setup) and stored alongside the repository definition. This is done like this so that a build is reproducible, but can also reference the head revision.

Scopes

EBuild contains the notion of a scope. Within a module, code can exist in different scopes. Currently the following scopes are supported:

ScopeExtendsDescription
main-The principle scope. Exported code that will be reused in other.
pokemainThe poke scope is for associated development code, ad-hoc tests... etc.
testpokeThe test scope is for automated tests - unit tests and otherwise.

The easiest way to view scopes is as a convenience. If we did not have scopes then we would still need somewhere to put tests, for example. Putting in the module would be dirty as we do not want the test code to be exported, so the alternative is to put them in their own module. We might prefix .test to the module being tested, e.g. org.acme-main.test. This would double the number of modules, and add a bunch of unintresting relationships that we would have to define.

Configurations

Many projects will have no need for configurations, but sometimes it becomes necessary to build slightly different versions of code. Such as in the following scenarios:

// TODO document how configurations work

Installation

EBuild does not install globally on a machine. One of its tasks is dependency version management, and it is important that it itself does not become a dependency versioning issue. So each 'build' will have its own version of ebuild. This much reduces the risk of builds not being reproducible due to changes in the tool chain, and affords more flexibility when evolving EBuild.

EBuild exists within the 'workspace'. In this example we are developing, but only need to make modifications to 2 of our modules. So only 2 modules are checked out at the workspace level.

 _ebuild
	 org.acme-build.stubgen
	 org.acme-main
	

The _ebuild directory is, not fully checked into source control. Rather only the subdirectory _ebuild/seed. The seed directory contains the ebuild version and typically an ant script which can be used to complete the installation by downloading and expanding an ebuild distribution.

 _ebuild/seed/
	              build.xml
	              version
	

After executing the build.xml the following directory structure should materialise

 _ebuild/
	         seed/ 
	         credentials/
	         interface/
	         library/
	         system/
	
DirectoryDescription
credentialsDirectory contains any username/password combinations which are required for any actions which require authentication. Typically this will be one of the following
interfaceContains the ant interface. Ant tasks which can be used to run ebuild. (It can also quite be run quite satisfactorily as a java project.
libraryLibrary contains versioned dependencies, which have been fetched, and if they come from a source repository, built. Built projects are only built once since they are a static version and should not change. Projects are organised in the following manner:
systemContains the core ebuild jars. Builders, Assemblers are plugins which exist in the library/workspace. At some point Repository and IDE integration will be done as plugins as well.

Credentials

Library

IDE Support

Eclipse

EBuild supports in the following ways:

Source Control Support

Subversion

EBuild supports subversion integration. It expects the following layout in subversion

 trunk/
	       _ebuild/
	       org.x-proj.a/
	       org.x-proj.b/
	       ...
	 branches/
	          1.0/
	              _ebuild/
	              org.x-proj.a/
	              org.x-proj.b/
	              ...
	          1.1/
	              ...