BASIS  version 1.2.3 (revision 2104)
Project Modularization

Introduction

This article details the design and implementation of the project modularization, where a project, also referred to as top-level project (note that BASIS only allows one level of submodularization), can have other projects as subprojects (referred to as modules in this context to distinguish them from the superproject/subproject relationship in case of the superbuild approach, see below). The project modules are conceptual cohesive groups of the project files.

A top-level project can also be described as a modularized project, where each module of this project may depend on other modules of the same project or external projects (also referred to as packages). Note that an external project can also be another top-level project which utilizes the same project modularization as discussed herein. The idea, and partly the CMake implementation, has been borrowed from the ITK 4 project. See the VTK Wiki for details on the ITK 4 Modularization.

Implementation

The modularization is mainly implemented by the ProjectTools.cmake module, in particular, the basis_project_modules() function which is called at the very top of the basis_project_impl() macro, which is the foundation for the root CMake configuration file (CMakeLists.txt) of every BASIS project. The basis_project_modules() function searches the subdirectories in the modules/ directory for the presence of the BasisProject.cmake file. It then loads this file, to retrieve the meta-data of each module, i.e., its name and dependencies. It then adds for each module a MODULE_<module> option to the build configuration. When this option is set to OFF, the module is excluded from both the project build and any package generated by CPack. Otherwise, if it is set to ON, the module is build as part of the top-level project. These options are superceded by the BUILD_ALL_MODULES option if this option is set to ON, however.

Besides adding these options, the basis_project_modules() function ensures that the modules are configured and build in the right order, such that a module which is needed by another module is build prior to this dependent module. Moreover, it helps the basis_find_package() function to find the other modules, in particular their configured package configuration files, which are either generated from the default Config.cmake.in file or a corresponding file found in the config/ directory of each module.

The other BASIS CMake functions may further change their actual behaviour depending on the PROJECT_IS_MODULE variable which specifies whether the project that is currently being configured is a module of another project (i.e., PROJECT_IS_MODULE is TRUE) or a top-level project (i.e., PROJECT_IS_MODULE is FALSE).

As modules are more or less independent subprojects, which might even be maintained by different persons, it is desireable that naming conflicts are handled automatically by the top-level project. Therefore, if the CMake variable BASIS_USE_MODULE_NAMESPACES is set to ON, BASIS will take actions to avoid naming conflicts. For example, the CMake build target names are prepended by the name of the module in lowercase followed by a dot (.) as namespace separator. By default, the BASIS_USE_MODULE_NAMESPACES option is, however, set to OFF. Even though modules shall be developed as independent from each other or the top-level project as applicable, are they yet considered to be closely related and their sources kept in the same repository. If a more loose coupling of projects is desired, these should be separate projects with separate repositories. These may then be distributed, configured, and build as part of a common superproject.

Todo:
Add reference to documentation of superbuild approach, which is yet not implemented as part of BASIS.