CMakeCatchTemplate: A C++ template project

CMakeCatchTemplate (https://github.com/MattClarkson/CMakeCatchTemplate) is a project to provide a starting structure for C++ projects configured with CMake, that can be customised to work in a variety of scenarios, allowing developers to deploy new algorithms to users in a shorter timeframe. Main features include a SuperBuild to build optional dependencies; unit tests using Catch; support for CUDA, OpenMP and MPI; examples of command line and GUI applications; Doxygen integration; Continuous Integration templates and support for building/deploying Python modules.


Introduction
CMakeCatchTemplate was originally developed as a teaching aid for UCL's Research Computing with C++ course, to demonstrate how a complex C++ project might be structured, and provide a starting point for student's own projects. Subsequently, the project has been expanded upon and is now employed as a template project for a range of C+ + projects within the Wellcome/EPSRC Centre for Interventional and Surgical Sciences (WEISS), 1 -2 as part of the SNAPPY library. 3 By reducing the amount of boilerplate code and providing support for a range of common libraries for scientific computing, the template allows a developer to quickly prototype and release a new library.
In addition to scaffolding to provide the structure for a C++ project, particular features provided are:

1.
A Meta-Build, also known as a SuperBuild, to optionally download and build any of the following: Boost, Eigen, FLANN, OpenCV, glog, gflags, VTK, PCL and ArrayFire. This results in a top-level build folder containing the compiled dependencies, and then a sub-folder containing the compiled code of this project.

2.
A single library into which the user can code their main algorithms.

4.
A single command line application, to give the end user a minimalist runnable program.

5.
Basic examples of how to create a Qt+VTK, Qt+OpenGL or QML+VTK user interface, ensuring the VTK render engine works in Qt or QML framework, on Windows, Linux and Mac. Qt installation is not included, and must be carried out separately.

6.
CPack setup to produce installers for the GUI apps.

7.
KWStyle config, to check for consistent code style (requires KWStyle installed on user's system).

8.
CppCheck config, to check for performance, style and correctness issues (requires CppCheck installed on user's system).

9.
Doxygen config, so you can generate documentation via make docs, or a DOCS task in Visual Studio.

10.
GitHub CI, Travis and Appveyor examples, to register the code with a Continuous Integration service.

11.
An example of the CMake required to build Python interfaces to your C++ code, using Boost.Python.

12.
An example of the CMake required to build Python interfaces to your C++ code, using pybind11. 4 Also includes an example of passing numpy/OpenCV data through Boost.Python, thanks to Gregory Kramida's pyboostcvconverter. 5

13.
An example of the CMake required to export a C-style module into Unity.

14.
Support for OpenMP, which is passed through to FLANN and OpenCV.

15.
Support for CUDA, which is passed through to FLANN, OpenCV and PCL.

16.
Support for MPI, which by default sets up the C++ libraries.

17.
Support for Python Wheels, thanks to Matthew Brett's multibuild. 6 In practice, most developers will only require a subset of the available features for a particular project. We envisage a range of project types that might commonly be implemented: • C++ library, with C++ command line interfaces.
• C++ library with C++ user interface, using Qt or QML.
• C++ library deployed as a Python module to PyPI, with separate Python code written outside of the project to make use of the module.
• C++ library used in an environment such as Unity, which is developed outside of the project.
The template is a starting point for developers wishing to avoid some of the overheads associated with setting up a new project, but still requires input from the user to customise to their particular application, and a working knowledge of CMake to get the maximum benefit.
In addition to the combination of functionality listed above, which are not found in any single existing C++ project template, 7 particular features which differentiate CMakeCatchTemplate include the ability to generate Python wheels, support for CUDA/ OpenMP/MPI, and examples usage for Qt/QML applications. Further, the laborious process of manually renaming/editing files upon first creating a project, as is typically required when using other templates, is removed by the addition of the CMakeCatchTemplateRenamer 8 helper script. application and get it into the hands of their users, who may not themselves be familiar with C++.

Project Structure
The template provides a ready-made structure for C++ projects (Figures 1 and 2). The user can build on this structure by adding their own code, primarily in Code/Lib.

Build Options
Build options (Figure 3) can be passed to CMake depending on the external libraries required.

Python Wheels
Deploying cross-platform Python wheels from C++ code can be a difficult process.
To help, we have been inspired and assisted by Matthew Brett's multibuild, 9 with the included travis.yml and appveyor.yml used to deploy the example code included with CMakeCatchTemplate to PyPI. 9 Users can re-use, or modify these configurations as needed.

Further Customisation
We believe that it is preferable to provide tested code that may not be needed by all users, rather than requiring the user to spend time writing potentially complex CMake. However, once a user has established a working build for their particular needs, it is possible to pare down the codebase by removing segments that will no longer be needed.
For example:

•
In the Code directory, subfolders for GUIs or Python/Unity bindings can be deleted if not required.
• 3 rd party libraries can be removed from the top level CMakeLists.txt e.g. by removing references to mpAddBoost or mpIncludeBoost.
• Unused items from the Utilities folder can be removed.

Quality Control
Continous Integration (CI) is used to test a range of CMake build options, and provide example use cases.
GitHub workflows are used to build/test some common configurations (Boost, OpenCV, PyBoost, PyBind, Qt) on an Ubuntu VM, which also provide a starting point for users to build their own projects. Workflows are stored in the .github/workflows directory.
A more complex example, of building a project and deploying to PyPI, is tested using Travis (Mac/Linux) and AppVeyor (Windows). Users can find more details in the .travis.yml and appveyor.yml files in the top level directory.
Further examples can be found in projects which have been derived from CMakeCatchTemplate -scikitsurgery-opencvcpp[ 10 and scikit-surgerypclcpp, 11 which each implement new algorithms within the /Code/Lib folders, and unit tests in /Testing. Again, the Travis and AppVeyor configuration files detail an up-to-date build procedure.
The default project structure includes some rudimentary unit tests. Once built, these tests are placed in the MYPROJECT-build/bin folder. The CI examples demonstrate how to run tests.
The included tests serve to illustrate the structure/framework that has been implemented. Further unit tests should be added by the user once they have added their own code to the project.

Availability
Operating System