Gigi Sayfan specializes in cross-platform object-oriented programming in C/C++/ C#/Python/Java with emphasis on large-scale distributed systems. He is currently trying to build intelligent machines inspired by the brain at Numenta (www.numenta.com).
A Build System for Complex Projects: Part 1
A Build System for Complex Projects: Part 2
A Build System for Complex Projects: Part 3
A Build System for Complex Projects: Part 4
A Build System for Complex Projects: Part 5
This is the second in a series of articles that explores an innovative build system for complicated projects. Part 1 discussed build systems in general, problems with existing build systems in particular, and presented an ideal/invisible build system -- ibs. In Part 2, I dive into the internals of ibs and explain how it works.
To recap: Ibs is an invisible build system that doesn't require any build files. It relies on a regular directory and conventions to infer build rules and it detects dependencies automatically. It generates build files for other IDEs or build systems like Makefiles, Visual Studio solutions, and NetBeans projects. It is focused on C/C++ projects, but can be extended to additional languages and other projects types.
Ibs has a generic core, an object model, and build-system-specific code (helper modules and templates). There is a clear separation between the common generation code and the build-system-specific parts. The object model includes the following classes:
- Project. The Project class is the unit of work. Each software system is just a list of projects with some dependencies between them. In the ibs world, a project always has an associated project directory and contains files that reside under its root directory, and possibly subdirectories too. Project maintains information such as the project name, its root directory, its dependencies, and its templates (see below). The files are discovered automatically.
- Template. Ibs can generate build files for multiple build systems. Each build system has its own set of build files. In some cases, it is just a single file such as a Visual Studio .vcproj file, and in other cases such as NetBeans nbproject, it can be a build directory that contains multiple files. Each project is associated with a set of templates that can be used to generate all the necessary build files.
The Template class has a skeleton text file with placeholders and a substitution dictionary that can be applied to generate the target build file.
- BaseHelper. The generic part of ibs doesn't know anything about the particular build systems it can generate, but it knows what it needs to know. BaseHelper is a base class that encapsulates this meta-knowledge. For each build system you want to support, you need to write a proper helper subclass that can provide the necessary information along with specific build file templates.The helper is responsible for getting all the necessary templates, preparing the substitution dictionary, and collecting files for each project.
- Generator. The generator is the engine of ibs. It understands the regular directory structure and knows how to build every top-level directory and all its subdirectories. Once it populates a project list and generates proper build files for each project, it maintains a map of top-level directories to project [template] types.
- Dependency Analyzer. The dependency analyzer module is C/C++-specific. It analyzes #include files and calculates the dependency graph of the various projects. In general, the only dependencies (at the C/C++ level) are static libraries that must be built before they can be linked with executables and dynamic libraries that depend on them.