CMake for Geant4 Developers

Geant4 developers can make use of several powerful features of CMake to help with their work. The key concept and working practice is the separation of the source directory, which is where the sources you edit reside, and the build directory, where the buildscripts and compiled products reside. The reason for enforcing this separation is twofold:

  • It provides separation of CMake generated files (e.g. Makefiles) from the Geant4 sources under revision control.
  • It allows multiple builds against a single source directory, giving fast incremental builds without having to reconfigure.

Using an Initial Cache File for Build Options

As Geant4, and CMake in general, has many configurable options, remembering and typing out the CMake command line can be tedious and potentially error prone once you start to use a significant number of options. To ease this task and provide reproducible builds, you can write options as a sequence of CMake set() commands into a so-called initial cache script. For example, to select Clang as the compiler and enable Qt support, we could write the following

set(CMAKE_C_COMPILER clang CACHE STRING "")
set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")
set(GEANT4_USE_QT ON CACHE BOOL "")

into a file named, say, mysettings.cmake. We could then pass this file to CMake to configure the build with these settings:

$ cmake -C /path/to/mysettings.cmake <otherargs>

Any settings in the supplied script will take priority over the defaults, so this can be a useful way to manage different builds in a reproducible way. Note that the set() commands must use the CACHE argument to ensure they are loaded into the CMake cache.

Using Different CMake Generators

CMake is a buildsystem generator that can create scripts for many buildsystems including Make, Ninja, Xcode, Visual Studio and Eclipse, among others. To find out which systems your install of CMake can generate scripts for, consult the “GENERATORS” section of the CMake man page, or click on the “Generate” button in the CMake GUI. The resulting scripts can be used within the buildsystem of choice to perform the actual build, install and packaging.

Whilst we only support Make and Visual Studio for Unix and Windows user builds respectively, Geant4 developers are welcome, and encouraged, to use their buildsystem of choice. On Unix system we in fact recommend use of Ninja due to the significant performanace advantages it has over traditional Make. On the command line, one can select the buildsystem using the -G argument of CMake. For example, to generate and run a Ninja build:

$ mkdir -p /path/to/build-ninja
$ cd /path/to/build-ninja
$ cmake -G Ninja /path/to/geant4-dev.git
$ ninja

On macOS, an Xcode project for Geant4 using the example from On Unix Platforms may be generated via:

$ mkdir -p /path/to/build-xcode
$ cd /path/to/build-xcode
$ cmake -G Xcode /path/to/geant4-dev.git

The resulting /path/to/build-xcode/Geant4.xcodeproj project may be opened with Xcode.

In the CMake GUI, the generator will be asked for the first time you click on Configure button (see On Windows Platforms), where it can be selected from a drop down list.

Note that in all cases, you can only have one buildsystem configuration in a given build directory (e.g. you cannot have Unix Makefiles alongside an Xcode project).

Support for these buildtools is still preliminary, so feedback is welcome, whether bug reports, guides or general comments.

Using the Eclipse IDE

Eclipse projects using Makefiles can be generated via the command:

$ cmake -G"Eclipse CDT4 - <TYPE> Makefiles" <otherargs>

where <TYPE> is platform dependent and one of Unix, MinGW or NMake. Note that only a single build mode is supported here because the projects are Makefile based. This means that you will need to supply CMake with the command line argument -DCMAKE_BUILD_TYPE=<MODE>, where <MODE>, is the required mode if you want to change the default mode. By default, Geant4 is built in “Release” mode.

With out-of-source builds enforced in Geant4, there are two issues that need to be worked around due to the way Eclipse expects project directories to be organised. These are to do with the integration of version control support and code editing/navigation/autocompletion. Both issues, together with their resolution are described in the CMake Wiki entry on Eclipse CDT4 under the “Out-ofSource Builds” section.

Command Line Help with Ninja/Make

If you develop using the command line and Ninja or Make, you can get information on the targets available by “building” the help target in your build directory, e.g.:

$ make help
The following are some of the valid targets for this Makefile:
... all (the default if no target is provided)
... clean
... depend
<furthertargets>

You may build any listed target individually, and it will be built together with all of its dependencies. CMake’s generated Make/Ninja files only output minimal information by default, so if you need to see the full commands used, you can run make with the extra VERBOSE argument:

$ make VERBOSE=1

or ninja with the -v flag:

$ ninja -v

to output every command in full.

In Make only, if you want to quickly check that your target compiles, without checking and rebuilding any of its dependencies, you can append /fast to the target name, e.g:

$ make G4run/fast

This will finish with an error if any dependents of the target do not exist, but can be useful for rapidly checking that your sources simply compile.

Building Quickly and Efficiently with Multiple Build Directories

The many ways in which Geant4 can be configured with optional components can make compilation and testing under different configurations time consuming.

As the CMake generated scripts live in a build directory isolated from the source directory, one can create several build directories configured against the same source directory. Each directory can have a different configuration, for example:

$ cd /path/to
$ ls
geant4-dev.git
$ mkdir build-release build-debug
$ cd build-release
$ cmake -DCMAKE_BUILD_TYPE=Release ../geant4-dev.git

...output...

$ make -j8

...output...

$ cd ../build-debug
$ cmake -DCMAKE_BUILD_TYPE=Debug ../geant4-dev.git

...output...

$ make -j8

...output...

The above example uses Makefiles, but the same technique also works with Ninja. It may not seem to have gained you much, but when you edit and develop code that is living under /path/to/geant4-dev.git, you only need to rebuild in each directory:

... work on code ...
$ cd /path/to/build-release
$ make -j8

... incremental build ...

$ cd /path/to/build-debug
$ make -j8

... incremental build ...

The builds pick up the changes you make to the source and build separately without needing reconfiguration. This is particularly powerful if the different configurations you need to test (for example, different versions of an external package) would require significant recompilation if the configuration were changed. Naturally, this power comes at the cost of some disk space, so may not be ideal in all cases.

Note that whilst this technique works on all platforms and buildtools, some IDEs (Xcode or Visual Studio for example) automatically support multiple build modes such as Release and Debug. In this case, you do not need separate build directories as the IDE handles this for you. However, you would still need two separate build directories if you, for example, wanted to develop and test against two versions of an external package such as Xerces-C.

Building Test Applications Against Your Development Build

A key feature of Geant4’s CMake scripts is that you do not need to install your current build to be able to use it. A typical use case here is that you have a simple testing application which you want to build against your latest development build of Geant4.

Versions of the Geant4Config.cmake (see CMake Build System: Geant4Config.cmake) and geant4-config (described in Other Unix Build Systems: geant4-config) scripts are created in the build directory. These versions are all configured to use the libraries as they exist in the build directory, and headers from the source directory, without installation.

You can therefore use these scripts as described earlier in How to Use the Geant4 Toolkit Libraries to build your test applications against a specific build tree. You therefore don’t need to install Geant4 everytime you make a small update. In the CMake case, simply set Geant4_DIR to the directory where you configured and built Geant4.