BASIS  version 1.2.3 (revision 2104)
How to Create/Modify a Project

Introduction

This how-to guide introduces the basisproject command-line tool which is installed as part of BASIS. This tool, also simply referred to as "project tool", is used to create a new project based on BASIS or to modify an existing BASIS project. The creation of a new project based on BASIS is occasionally also referred to as instantiating the Software Project Template.

For a detailed description and overview of the available command options, please refer to the output of the following command:

basisproject --help

How to Create a New Project

The fastest way to create a new project is to call the project tool with the name of the new project and a brief project description as arguments.

basisproject --name MyProject --description "This is a brief description of the project."

This will create a subdirectory called "MyProject" under the current working directory and populate it with the standard project directory structure and BASIS configuration. No CMake commands to resolve dependencies to other software packages will be added. These can be added later either manually or as described below. However, if you know already that your project will depend, for example, on ITK and optionally make use of VTK if available, you can specify these dependencies when creating the project using the --use or --useopt option, respectivley.

basisproject --name MyProject --description "This is a brief description of the project." --use ITK --useopt VTK

The basisproject tool will in turn modify the BasisProject.cmake file to add the named packages to the corresponding lists of dependencies. Note that in order for the project tool to be able to find the correct place where to insert the new dependencies, the #<dependency> et al. placeholders have to be present.

How to Modify an Existing Project

The project tool allows a detailed selection of the features included in the project template for a particular BASIS project. Which of these features are needed will often not be known during the creation of the project, but change during the work on the project. Therefore, an existing BASIS project which was created as described above can be modified using the project tool to add or remove certain project features and to conveniently add CMake commands to resolve further dependencies on other software packages. How this is done is described in the following.

General Notes

The two project attributes which cannot be modified using the project tool are the project name and its description. These attributes need to be modified manually by editing the project files. Be aware that changing the project name may require the modification of several project files including source files. Furthermore, the project name is used to identify the project within the lab and possibly even externally. Therefore, it should be fixed as early as possible. In order to change the project description, simply edit the BasisProject.cmake file which you can find in the top directory of the source tree. Specifically, the argument for the DESCRIPTION option of the basis_project() function.

Hence, in order to modify an existing project, the --name and --description options cannot be used. Instead, use the --root option to specify the root directory of the source tree of the project you want to modify or run the command without either of these options with the root directory as current working directory.

Adding Features

By features, we refer here to the set of directories and contained CMake/BASIS configuration files for which template files exist in the BASIS project template. For a list of available project features, please have a look at the help output of the project tool. You can either select a pre-configured project template consisting of a certain set of directories and configuration files and optionally modify these sets by removing features from them and/or adding other features, or you can simply remove and/or add selected features only from/to the current set of directories and configuration files which already exist in the project's source tree.

For example, if you created a project using the standard project template (i.e., by supplying no particular option or the option --standard during the project creation), but your software requires auxiliary data such as a pre-computed lookup table or a medical image atlas, you can add the data/ directory in which these auxiliary files should be stored in the source tree using the command

basisproject --data

As another example, if you want to extend the default script configuration file which is used to configure the build of scripts written in Python, Perl, BASH, or any other scripting language (even though not currently supported by BASIS will it likely still be able to "build" these), use the command

basisproject --config-script

Removing Features

In order to remove the conf/Settings.cmake file and the example/ directory tree, run the command

basisproject --noconfig-settings --noexample

If any of the project files which were initially added during the project creation differ from the original project file, the removal of such files will fail with an error message. If you are certain that the changes are not important and still want to remove those files from the project, use the --force option. Moreover, if a directory is not empty, it will only be removed if the --force option is given. Note that a directory is also considered empty if it only contains hidden subdirectories which are used by the revision control software to manage the revisions of the files inside this directory, i.e., the .svn subdirectory in case of Subversion or the .git subdirectory in case of Git. Before using the --force option, you should be certain which directories would be removed and if their content is no longer needed. Thus, run any command first without the --force option, and only if it failed consider to add the --force option.

Adding Dependencies

A dependency is either a program required by your software at runtime or an external software package such as the nifticlib or ITK. The project tool can be used to add the names of packages your project depends on to the lists of dependencies which are given as arguments to the basis_project() command. For each named package in this list, the basis_find_package() command is called to look for a corresponding package installation. In order to understand how CMake searches for external software packages, please read the documentation of CMake's find_package().

The BASIS package provides so-called Find modules (e.g., FindMATLAB.cmake or FindNiftiCLib.cmake) for external software packages which are commonly used at SBIA and not (yet) part of CMake. If you have problems resolving the dependency on an external software package required by your software due to a missing corresponding Find module, please contact the manager of the BASIS project and state your interest in a support by BASIS for this particular software package.

As an example on how to add another dependency to an existing BASIS project, consider the following scenario. We created a project without any dependency and now notice that we would like to make use of ITK in our implementation. Thus, in order to add CMake code to the build configuration to resolve the dependency on ITK, which also includes the so-called Use file of ITK (UseITK.cmake) to import its build configuration, run the command

basisproject --use ITK

If your project can optionally make use of the features of a certain external software package, but will also built and run without this package being installed, you can use the --useopt option to exploit CMake code which tries to find the software package, but will not cause CMake to fail if the package was not found. In this case, you will need to consider the <Package>_FOUND variable in order to decide whether to make use of the software package or not. Note that the package name (<Package>) is case sensitive and that the case must match the one of the first argument of basis_find_package().

For example, let's assume your software can optionally make use of CUDA. Therefore, as CMake includes already a FindCUDA.cmake module, we can run the following command in order to have CMake look for an installation of the CUDA libraries.

basisproject --useopt CUDA

If this search was successful, the CMake variable CUDA_FOUND will be TRUE, and FALSE otherwise.

Another example of a dependency on an external package is the compilation of MATLAB source files using the MATLAB Compiler (MCC). In this case, you need to add a dependency on the MATLAB package. Please note that it is important to capitalize the package name and not to use Matlab as this would refer to the FindMatlab.cmake module included with CMake. The FindMATLAB.cmake module which we are using is included with BASIS. It improves the way CMake looks for a MATLAB installation and furthermore looks for executables required by BASIS, such as in particular matlab, mcc, and mex. Use the following command to add a dependency on MATLAB:

basisproject --use MATLAB

Removing Dependencies

The project tool does at the moment not support the removal of previously added dependencies. Therefore, please edit the BasisProject.cmake file manually and simply remove all CMake code referring to the particular package you do no longer require or use.

How to Add Modules

BASIS supports the modularization of a project similar to the ITK 4, where each module is itself a BASIS project which may depend on other modules of the top-level project or other external packages. As each module itself is a project, modules are created just the same way as projects are created. The only difference might be that modules may include different sets of features (directories and files) than the top-level project. A project which uses such modularization in turn often does not include source files by its own, but is an collection of the projects (i.e., subprojects) which are its modules.

Therefore, the top-level project often excludes the src/ subdirectory, but includes the modules/ directory instead, in which the project's modules reside. First create the top-level project as follows (or simply add a modules/ directory to an existing project):

basisproject --name MyToolkit --description "A modularized project." --toplevel

To now add modules to your modularized project, i.e., one which has a modules/ subdirectory, change to the modules/ subdirectory of the top-level project, and run the command:

basisproject --name MyModule --description "A module of MyToolkit." --module

How to Update a Project

Occasionally, the project template of BASIS may be modified as the development of BASIS progresses. In such case, you may want or need to update the files of a project which have been created from a previous version of the project template. In order to help updating a project to a newer project template version, the project tool uses a three-way file comparison similar to Subversion to merge changes in the template files with those changes you have made to the corresponding files of your project. If such merge fails because both the template as well as the project file have been changed at the same lines, a merge conflict occurs which has to be resolved manually. In no case, however, the project tool will discard your changes. There will always be a backup of your current project file, before the automatic file merge is performed.

To update the project files, run the following command in the root directory of your project's source tree:

basisproject --update

If the project template has not been changed since the last update, no files will be modified by this command.

Resolving Merge Conflicts

When the same lines of the template file as well as the project file have been modified since the creation or last update of the project, you will get a merge conflict. A merge conflict results in a merged project file which contains the changes of both the template and your current project file. Markers such as the following are used to highlight the lines of the merged file which are in conflict with each other.

Marker Description
<<<<<<< Marks the start of conflicting lines. This marker is followed by your changes from the corresponding lines of your project file.
||||||| Marks the start of the corresponding lines from the original template file which was used to create the project or which the project has been updated to last.
======= Marks the start of the corresponding lines from the current template file, i.e., the one the project file should be updated to.
>>>>>>> Marks the end of the conflicting lines.

In order to resolve the conflicts in one file, you have to edit the merged project file manually. For reference, the project tool writes the new template file to a file named like the project file in conflict with this project file, using .template as file name suffix. It further keeps a backup of your current project file before the update. The file name suffix for this backup file is .mine. For example, if conflicts occured when updating the README.txt file, the following files are written to your project's directory.

File Name Description
README.txt.mine A copy of the project file before the update.
README.txt.template A copy of the current template file which differs from the template file used to create the project or corresponds to the version of the template file of the last update.
README.txt The file containing changes from both the README.txt.template and README.txt.mine file, where conflicts have been highlighted using above markers.

After you edited the project files which contain conflicts, possibly using merge tools installed on your system, you need to remove the .template and .mine files to let the project tool know that the conflicts are resolved. Otherwise, when you run the update command again, it will fail with an error message indicating that there are unresolved merge conflicts. You can delete those files either manually or using the following command in the root directory of your project's source tree.

basisproject --cleanup