Project Template

While you can create or use any custom template you like, it is highly recommended that templates follow the BASIS Standards. In addition to the other standards, for BASIS compliance templates must meet the requirements outlined below.

See also

The Using and Customizing Templates How-to explains how to make use of templates.

Benefits

Anyone familar with the standard will be able to quickly navigate the source tree and easily integrate your project into their own because the setup is designed for consistency and interoperability. The idea is to make projects easier for developers to create, share, and use.

BASIS Standardized Templates provide and automate the following steps:

  • Configuration of the build, testing, installation, and packaging.
  • Common directory structure which can be found at Filesystem Layout.
  • CMake‘s CMakeLists.txt file setup.
  • Basic build flags that are required.

Standard Project Files

File Formats

Standard project files utilize the following formats:

.txt A utf8 plain text file.
.md Markdown
.rst reStructuredText
CMakeLists.txt CMake listfile format.
.cmake CMake listfile format.

Required Project Files

The following files have to be part of any project which follows the Filesystem Layout. This is the minimal set of project files provided when instantiating a new software project. Besides these files, a project will have either a src/ directory or a modules/ directory, or even both of them. See below for a description of these directories.

README.md
This is the main (root) documentation file.
  • Every user is assumed to first read this file, which in turn will refer them to the more extensive documentation.
  • Briefly introduces the software package, including a summary of the package files.
  • Refer to the INSTALL.txt and COPYING.txt files for details on the build and installation and software license, respectively.
  • Include references to scientific articles related to the software package in this file.
AUTHORS.md
Names the authors of the software package and people who dirctly made notable contributions to the software, even if they did not actually edit any project files. Others who mostly contributed indirectly should be named in the README.txt file instead. It is not necessary to list author names in each source file, as these are generally edited by multiple people and updating the authors information within each source file is tedious.
COPYING.txt
Contains copyright and license information. If some files of the project were copied from other sources, the copyright and license information of these files shall be stated here as well. It is important to clearly state which copyright and license text corresponds to which project files.
INSTALL.md
Contains build and installation instructions. As the build of all projects which follow BASIS is very similar, this file shall only describe additional steps/CMake variables which are not described in the Install any Software guide.
BasisProject.cmake

Sets basic information about a BASIS Project and calls the basis_project() command.

The basic project information, also known as metadata, will typically include:
  • the project name and release version
  • a brief description which is used for the packaging
  • dependencies

Note that additional dependencies may optionally be specified using by the CMake code in the config/Depends.cmake file. If the project is a module of another project, this file is read by the top-level project to be able to identify its modules and the dependencies among them.

BasisProject.cmake explains using this file to configure your project.

CMakeLists.txt
The root CMake configuration file. Do not edit this file.

Common Project Files

CTestConfig.cmake
The CTest configuration file. This file specifies the URL of the CDash dashboard of the project where test results should be submitted to.
config/:apidoc:`Settings.cmake`

This is the main CMake script file used to configure the build system, and BASIS. Put CMake code required to configure the build system in this file.

You may want to:
  • Add common compiler flags
  • Add new variable definitions or modifying existing CMake BASIS variables
  • Write specialized code required to utilize dependencies
  • Make CMake configure_file() calls
Examples:
  • Setting the project directory variables. The line set(PROJECT_SUBDIRS random) will cause BASIS to call basis_add_subdirectory() on <source>/random at the appropriate time during the execution of BASIS.
  • See basis/config/Settings.cmake for more examples.
modules/

This directory contains independent project modules. If the project files are organized into conceptual cohesive groups, similar to the modularization goal of the ITK 4, this directory contains these conceptual modules of the project. The files of each module reside in a subdirectory named after the module. Note that each module itself is a project derived from this project template.

Project Modularization

CMakeLists.txt Build Files

build/CMakeLists.txt

CMake configuration file for performing super-build of external library components and requirements by utilizing the CMake ExternalProject_Add() call.

The source packages of the prerequisites are either:
  • downloaded during the bundle build
  • included with the distribution package.

In the latter case, these source packages should be placed in the build/ directory next to this CMake configuration file.

data/CMakeLists.txt
This CMake configuration file can contains code to acquire or simply install every data file and directory from the source tree into the INSTALL_DATA_DIR directory of the installation tree.
doc/CMakeLists.txt
This CMake configuration file adds rules to build the documentation. For example, the in-source comments using Doxygen or reStructuredText sources using Sphinx. Moreover, for every documentation file, such as the software manual, the basis_add_doc() command has to be added to this file.
example/CMakeLists.txt
This CMake configuration file contains code to install every file and directory from the source tree into the INSTALL_EXAMPLE_DIR directory of the installation tree. It may be modified to configure and/or build example programs if applicable or required.
src/CMakeLists.txt
This is the CMake file where your primary software packages are built.
  • Use the command basis_add_library() to add a shared, static, or module library, which can also be a module written in a scripting language.
  • Use the command basis_add_executable() to add an executable target, which can be either a binary or a script file.
  • All targets can added to the src/CMakeLists.txt file using relative paths.
  • If necessary, source code files may be organized in subdirectories of the src/ directory.
  • Typically subdirectories aren’t necessary for less than 20 files.
  • Separate CMakeLists.txt files can be used for each subdirectory.
test/CMakeLists.txt
Tests are added to this build configuration file using the basis_add_test() command. The test input files are usually put in a subdirectory named test/input/, while the baseline data of the expected test output is stored inside a subdirectory named test/baseline/. Generally, however, the Filesystem Layout of BASIS does not dictate how the test sources, input, and baseline data have to be organized inside the test/ directory.
test/internal/CMakeLists.txt

Tests for internal use only that require data specific to your work organization. These files are expected to be excluded from the public source distribution package are configured using this CMake configuration file.

Reasons for excluding tests from a public distribution include:
  • some tests may depend on the internal software environment
  • may require a particular machine architecture.
  • The size of the downloadable distribution packages my otherwise be excessively large.

Documenation Files

doc/manual.rst
The main page of the software manual.
doc/index.rst
The main page of the project web site.
doc/intro.rst
Introductory description of the project, will appear at top of website front page and at the beginning of the manual.
doc/features.rst
Page listing project features that will appear after the intro on website front page and at the beginning of the manual.

Advanced Project Files

The customization of the following files is usually not required, and hence, in most cases, most of these files need not to be part of a project.

config/ScriptConfig.cmake.in
See the documentation on the build of script targets for details on how this script configuration is used.
config/Components.cmake
Contains CMake code to configure the components used by component-based installers. Currently, component-based installers are not very well supported by BASIS, and hence this file is mostly unused and is currently subject to change.
config/Config.cmake.in
This is the template of the package configuration file. When the project is configured/installed using CMake, a configured version of this file is copied to the build or installation tree, respectively, where the information about the package configuration is substituted as appropriate for the actual build/installation of the package. For example, the configured file contains the absolute path to the installed public header files such that other packages can easily add this path to their include search path. The find_package() command of CMake will look for this file and automatically import the CMake settings when this software package was found. For many projects, the default package configuration file of BASIS which is used if this file is missing in the project’s config/ directory, is sufficient and thus this file is often not required.
config/ConfigSettings.cmake
This file sets CMake variables for use in the config/Config.cmake.in file. As the package configuration for the final installation differs from the one of the build tree, this file has to contain CMake code to set the variables used in the config/Config.cmake.in file differently depending on whether the variables are being set for use within the build tree or the installation tree. This file only needs to be present if the project uses a custom config/Config.cmake.in file, which in turn contains CMake variables whose value differs between build tree and installation.
config/ConfigUse.cmake.in

An optional convenience file for CMake code which uses the variables set by the standard CMake packageConfig.cmake file. BASIS generates a standard packageConfig.cmake file from config/Config.cmake.in, which is used by other packages to set all the CMake variables they need to utilize your package.

Example:
  • The package configuration sets a variable to a list of include directories have to be added to the include search path. ConfigUse.cmake.in would then contain CMake instructions to actually add these directories to the path.
config/ConfigVersion.cmake.in
This file accompanies the package configuration file generated from the config/Config.cmake.in file. It is used by CMake’s find_package() command to identify versions of this software package which are compatible with the version requested by the dependent project. This file needs almost never be customized by a project and thus should generally not be included in a project’s source tree.
config/Depends.cmake
If the generic code used by BASIS to resolve the dependencies on external packages is not sufficient, add this file to your project. CMake code required to find and make use of external software packages properly shall be added to this file. In order to only make use of the variables set by the package configuration of the found dependency, consider to add a dependency entry to the BasisProject.cmake file instead and code to use these variables to config/Settings.cmake.
config/Package.cmake
Configures CPack, the CMake package generator for CMake. The packaging of software using CPack is currently not completely supported by BASIS. This template file is subject to change.
CTestCustom.cmake.in
This file defines CTest variables which customize CTest.

Template Layout

- template_name/
    - 1.0/
        + _config.py
        + src/
        + config/
        + data/
        + doc/
        + example/
        + modules/
        + test/
    - 1.1/
    - 2.0/
    - 2.1/
    - .../

Note

Only the files which were modified or added have to be present in the new template. The basisproject tool will look in older template directories for any missing files.

Template Versions

The template system is designed to help automate updates of existing libraries to new template versions. Whenever a template file is modified or removed, the previous project template has to be copied to a new directory with an updated template version! Otherwise, the three-way diff merge used by the basisproject tool to update existing projects to this newer template will fail.

Custom Substitutions

The template configuration file named _config.py and located in the top directory of each project template defines not only which files constitute a project, but also the available substitution parameters and defaults used by basisproject. The template configuration file requires a basic understanding of Python syntax, but is fairly easy to understand even without much experience. To get an idea of the syntax, take a look at the example below. A complete example can be found in the BASIS source package in data/templates/basis/1.0/_config.py.

# project template configuration script for basisproject tool

# ------------------------------------------------------------------------------
# required project files
required = [
  'AUTHORS.txt',
  'README.txt',
  'INSTALL.txt',
  'COPYING.txt',
  'CMakeLists.txt',
  'BasisProject.cmake'
]

# ------------------------------------------------------------------------------
# optional project files
options = {
  'config-settings' : {
    'desc' : 'Include/exclude custom Settings.cmake file.',
    'path' : [ 'config/Settings.cmake' ]
  },
  'config' : {
    'desc' : 'Include/exclude all custom configuration files.',
    'deps' : [
               'config-settings'
             ]
  },
  'data' : {
    'desc' : 'Add/remove directory for auxiliary data files.',
    'path' : [ 'data/CMakeLists.txt' ]
  }
}

# ------------------------------------------------------------------------------
# preset template options
presets = {
  'minimal' : {
    'desc' : 'Choose minimal project template.',
    'args' : [ 'src' ]
  },
  'default' : {
    'desc' : 'Choose default project template.',
    'args' : [ 'doc', 'doc-rst', 'example', 'include', 'src', 'test' ]
  },
  'toplevel' : {
    'desc' : 'Create toplevel project.',
    'args' : [ 'doc', 'doc-rst', 'example', 'modules' ]
  },
  'module' : {
    'desc' : 'Create module of toplevel project.',
    'args' : [ 'include',   'src',   'test' ]
  }
}

# ------------------------------------------------------------------------------
# additional substitutions besides <project>, <template>,...
from datetime import datetime as date

substitutions = {
  # fixed computed substitutions
  'date'  : date.today().strftime('%x'),
  'day'   : date.today().day,
  'month' : date.today().month,
  'year'  : date.today().year,
  # substitutions which can be overridden using a command option
  'vendor' : {
    'help'    : "Package vendor ID (e.g., acronym of provider and/or division).",
    'default' : "SBIA"
  },
  'copyright' : {
    'help'    : "Copyrigth statement optionally including years.",
    'default' : str(date.today().year) + " University of Pennsylvania"
  },
  'license' : {
    'help'    : "Software license statement, e.g., \"Simplified BSD\".",
    'default' : "See http://www.cbica.upenn.edu/sbia/software/license.html or COPYING file."
  },
  'contact' : {
    'help'    : "Package contact information.",
    'default' : "<vendor> <<vendor>-software at uphs.upenn.edu>"
  }
}

Note

The substitutions are applied recursively up to a depth of 3. Hence, if the value of a substitution is another substitution tag, it will be replaced by the value of that respective substitution. See the contact substitution above for an example.

Binary Template Files

In general, template files are assumed to be binary and thus no substitution is performed, unless the template file is known to be a text file. Whether or not a template file is considered to be a text file for which subsitution takes place depends on its MIME type . The basisproject tool uses the Python MIME types module in order to determine the type of each template file. In addition to the default types known by this module, the file name extensions .cmake, .md, .mdown, .markdown, .rst, .dox, and .in are treated as text files.