2.8.  How to Make an Executable Program

The code for the user examples in Geant4 is placed in the subdirectory examples of the main Geant4 source package. This directory is installed to the share/Geant4-X.Y.Z/examples (where X.Y.Z is the Geant4 version number) subdirectory under the installation prefix. In the following sections, a quick overview will be given on how to build a concrete example, "ExampleB1", which is part of the Geant4 distribution, using CMake and the older, and now deprecated, Geant4Make system.

2.8.1.  Building ExampleB1 Using CMake

Geant4 installs a file named Geant4Config.cmake located in:

      +- CMAKE_INSTALL_PREFIX/ (where you installed Geant4)
          +- lib/
             +- Geant4-10.1.0/
                +- Geant4Config.cmake
    

which is designed for use with the CMake scripting language find_package command. The example presented below will cover basic usage of Geant4Config.cmake, and you may find details on more advanced usage in Section 4.1. Building a Geant4 application using CMake thus involves writing a CMake script CMakeLists.txt using find_package and other CMake commands to locate Geant4 and describe the build of your application against it. Whilst it requires a bit of effort to write the script, CMake provides a very powerful and flexible tool, especially if you are working on multiple platforms. It is therefore the method we recommend for building Geant4 applications.

Moving to the concrete example of the ExampleB1 application, its source code is arranged in the following directory structure:

      +- B1/
         +- CMakeLists.txt
         +- exampleB1.cc
         +- exampleB1.in
         +- exampleB1.out
         +- include/
         |  +- B1DetectorConstruction.hh
         |  +- B1EventAction.hh
         |  +- B1PrimaryGeneratorAction.hh
         |  +- B1RunAction.hh
         |  +- B1SteppingAction.hh
         +- src/
         |  +- B1DetectorConstruction.cc
         |  +- B1EventAction.cc
         |  +- B1PrimaryGeneratorAction.cc
         |  +- B1RunAction.cc
         |  +- B1SteppingAction.cc
         +- init.mac
         +- init_vis.mac
         +- run1.mac
         +- run2.mac
         +- vis.mac
       

Here, exampleB1.cc contains main() for the application, with include/ and src/ containing the implementation class headers and sources respectively. The .mac files are scripts containing Geant4 UI commands for use at run time. This arrangement of source files is not mandatory when building with CMake, apart from the location of the CMakeLists.txt file in the root directory of the application.

The text file CMakeLists.txt is the CMake script containing commands which describe how to build the exampleB1 application:

      # (1)
      cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
      project(B1)

      # (2)
      option(WITH_GEANT4_UIVIS "Build example with Geant4 UI and Vis drivers" ON)
      if(WITH_GEANT4_UIVIS)
        find_package(Geant4 REQUIRED ui_all vis_all)
      else()
        find_package(Geant4 REQUIRED)
      endif()

      # (3)
      include(${Geant4_USE_FILE})
      include_directories(${PROJECT_SOURCE_DIR}/include)

      # (4)
      file(GLOB sources ${PROJECT_SOURCE_DIR}/src/*.cc)
      file(GLOB headers ${PROJECT_SOURCE_DIR}/include/*.hh)

      # (5)
      add_executable(exampleB1 exampleB1.cc ${sources} ${headers})
      target_link_libraries(exampleB1 ${Geant4_LIBRARIES})

      # (6)
      set(EXAMPLEB1_SCRIPTS
        exampleB1.in
        exampleB1.out
        init.mac
        init_vis.mac
        run1.mac
        run2.mac
        vis.mac
        )

      foreach(_script ${EXAMPLEB1_SCRIPTS})
        configure_file(
          ${PROJECT_SOURCE_DIR}/${_script}
          ${PROJECT_BINARY_DIR}/${_script}
          COPYONLY
          )
      endforeach()

      # (7)
      install(TARGETS exampleB1 DESTINATION bin)
    

For clarity, the above listing has stripped out the main comments (CMake comments begin with a "#") you'll find in the actual file to highlight each distinct task:

  1. Basic Configuration

    The cmake_minimum_required command simply ensures we're using a suitable version of CMake. The project command sets the name of the project and enables and configures C and C++ compilers.

  2. Find and Configure Geant4

    The aforementioned find_package command is used to locate and configure Geant4 (we'll see how to specify the location of the Geant4 installation to be used later when we run CMake), the REQUIRED argument being supplied so that CMake will fail with an error if it cannot find Geant4. The option command specifies a boolean variable which defaults to ON , and which can be set when running CMake via a -D command line argument, or toggled in the CMake GUI interfaces. We wrap the calls to find_package in a conditional block on the option value. This allows us to configure the use of Geant4 UI and Visualization drivers by exampleB1 via the ui_all vis_all "component" arguments to find_package . These components and their usage is described in detail in Section 4.1.

  3. Configure the Project to Use Geant4 and B1 Headers

    To automatically configure the header path, compiler flags and compiler definitions needed for linking to Geant4, we use the include command to load a CMake script supplied by Geant4. The CMake variable named Geant4_USE_FILE is set to the path to this module when Geant4 is located by find_package . We recommend the usage of this file as it will automatically set the compiler definitions and flags recommended for use with Geant4. We use the include_directories command to add the B1 header directory to the compiler's header search path. The CMake variable PROJECT_SOURCE_DIR points to the top level directory of the project and is set by the earlier call to the project command.

  4. List the Sources to Build the Application

    Use the globbing functionality of the file command to prepare lists of the B1 source and header files.

    Note however that CMake globbing is only used here as a convenience. The expansion of the glob only happens when CMake is run, so if you later add or remove files, the generated build scripts will not know a change has taken place. Kitware strongly recommend listing sources explicitly as CMake automatically makes the build depend on the CMakeLists.txt file. This means that if you explicitly list the sources in CMakeLists.txt, any changes you make will be automatically picked when you rebuild. This is most useful when you are working on a project with sources under version control and multiple contributors.

  5. Define and Link the Executable

    The add_executable command defines the build of an application, outputting an executable named by its first argument, with the sources following. Note that we add the headers to the list of sources so that they will appear in IDEs like Xcode.

    After adding the executable, we use the target_link_libraries command to link it with the Geant4 libraries. The Geant4_LIBRARIES variable is set by find_package when Geant4 is located, and is a list of all the libraries needed to link against to use Geant4.

  6. Copy any Runtime Scripts to the Build Directory

    Because we want to support out of source builds so that we won't mix CMake generated files with our actual sources, we copy any scripts used by the B1 application to the build directory. We use foreach to loop over the list of scripts we constructed, and configure_file to perform the actual copy.

    Here, the CMake variable PROJECT_BINARY_DIR is set by the earlier call to the project command and points to the directory where we run CMake to configure the build.

  7. If Required, Install the Executable

    Use the install command to create an install target that will install the executable to a bin directory under the CMAKE_INSTALL_PREFIX set for your application (NB: This is not necessarily the same as the prefix for your Geant4 install!).

    If you don't intend your application to be installable, i.e. you only want to use it locally when built, you can leave this out.

This sequence of commands is the most basic needed to compile and link an application with Geant4. The Geant4Config.cmake is highly flexible, and you can find documentation on more advanced usage in Section 4.1. The flexibility of CMake itself also allows you to easily extend the very basic CMakeLists.txt presented above to support use cases such as using other third party packages (via find_package ) or platform specific configuration. If any of the above is still unclear, we recommend you study the Kitware CMake Tutorial for an in depth introduction to writing CMake scripts. Please also ask any questions on our HyperNews Forum.

With the CMake script in place, using it to build an application is a two step process. First CMake is run to generate buildscripts that describe the build in the language of a specific tool such as make. By default, these will be Makefiles on Unix platforms and Visual Studio solutions on Windows, but you can generate scripts for other tools like Xcode and Eclipse if you wish. Second, the buildscripts are run by the chosen build tool to compile and link the application.

A key concept with CMake is that we generate the buildscripts and run the build in a separate directory, the so-called build directory, from the directory in which the sources reside, the so-called source directory. This is the exact same technique you'll have used when when building Geant4 itself. Whilst this may seem awkward to begin with, it is a very useful technique to employ. It prevents mixing of CMake generated files with those of your application, and allows you to have multiple builds against a single source without having to clean up, reconfigure and rebuild.

We'll illustrate this configure and build process on Linux/Mac using Makefiles, and on Windows using Visual Studio. The example script and Geant4's Geant4Config.cmake script are vanilla CMake, so you should be able to use other Generators (such as Xcode and Eclipse) without issue.

2.8.1.1.  Building ExampleB1 with CMake on Unix with Makefiles

We'll assume, for illustration only, that you've copied the exampleB1 sources into a directory under your home area so that we have

          +- /home/you/B1/
             +- CMakeLists.txt
             +- exampleB1.cc
             +- include/
             +- src/
             +- ...
        

Here, our source directory is /home/you/B1, in other words the directory holding the CMakeLists.txt file for the B1 project.

Let's also assume that you have already installed Geant4 in your home area under, for illustration only, /home/you/geant4-install.

Our first step is to create a build directory in which build the example. We will create this alongside our B1 source directory as follows:

        $ cd $HOME
        $ mkdir B1-build
      

We now change to this build directory and run CMake to generate the Makefiles needed to build the B1 application. We pass CMake two arguments:

        $ cd $HOME/B1-build
        $ cmake -DGeant4_DIR=/home/you/geant4-install/lib64/Geant4-10.1.0 $HOME/B1
      

Here, the first argument points CMake to our install of Geant4. Specifically, it is the directory holding the Geant4Config.cmake file that Geant4 installs to help CMake find and use Geant4. You should of course adapt the value of this variable to the location of your actual Geant4 install.

The second argument is the path to the source directory of the project we want to build. Here it's just the B1 source directory as discussed earlier. You should of course adapt the value of that variable to where you copied the B1 source directory.

CMake will now run to configure the build and generate Makefiles. On Linux, you will see the output

        $ cmake -DGeant4_DIR=/home/you/geant4-install/lib64/Geant4-10.1.0 $HOME/B1
        -- The C compiler identification is GNU
        -- The CXX compiler identification is GNU
        -- Check for working C compiler: /usr/bin/gcc
        -- Check for working C compiler: /usr/bin/gcc -- works
        -- Detecting C compiler ABI info
        -- Detecting C compiler ABI info - done
        -- Check for working CXX compiler: /usr/bin/c++
        -- Check for working CXX compiler: /usr/bin/c++ -- works
        -- Detecting CXX compiler ABI info
        -- Detecting CXX compiler ABI info - done
        -- Configuring done
        -- Generating done
        -- Build files have been written to: /home/you/B1-build
      

On Mac OS X, you will see slightly different output, but the last three lines should be identical.

If you now list the contents of you build directory, you can see the files generated:

        $ ls
        CMakeCache.txt       exampleB1.in   init_vis.mac  run2.mac
        CMakeFiles           exampleB1.out  Makefile      vis.mac
        cmake_install.cmake  init.mac       run1.mac
      

Note the Makefile and that all the scripts for running the exampleB1 application we're about to build have been copied across. With the Makefile available, we can now build by simply running make:

        $ make -jN
      

CMake generated Makefiles support parallel builds, so can set N suitable for the number of cores on your machine (e.g. on a dual core processor, you could set N to 2). When make runs, you should see the output

        $ make
        Scanning dependencies of target exampleB1
        [ 16%] Building CXX object CMakeFiles/exampleB1.dir/exampleB1.cc.o
        [ 33%] Building CXX object CMakeFiles/exampleB1.dir/src/B1PrimaryGeneratorA
        ction.cc.o
        [ 50%] Building CXX object CMakeFiles/exampleB1.dir/src/B1EventAction.cc.o
        [ 66%] Building CXX object CMakeFiles/exampleB1.dir/src/B1RunAction.cc.o
        [ 83%] Building CXX object CMakeFiles/exampleB1.dir/src/B1DetectorConstruct
        ion.cc.o
        [100%] Building CXX object CMakeFiles/exampleB1.dir/src/B1SteppingAction.cc
        .o
        Linking CXX executable exampleB1
        [100%] Built target exampleB1
      

CMake Unix Makefiles are quite terse, but you can make them more verbose by adding the VERBOSE argument to make:

        $ make VERBOSE=1
      

If you now list the contents of your build directory you will see the exampleB1 application executable has been created:

        $ ls
        CMakeCache.txt       exampleB1      init.mac      run1.mac
        CMakeFiles           exampleB1.in   init_vis.mac  run2.mac
        cmake_install.cmake  exampleB1.out  Makefile      vis.mac
      

You can now run the application in place:

        $ ./exampleB1
        Available UI session types: [ GAG, tcsh, csh ]

        *************************************************************
         Geant4 version Name: geant4-10-01-ref-00 [MT]   (5-December-2014)
          << in Multi-threaded mode >>
                              Copyright : Geant4 Collaboration
                              Reference : NIM A 506 (2003), 250-303
                                    WWW : http://cern.ch/geant4
        *************************************************************

        <<< Reference Physics List QBBC
        Visualization Manager instantiating with verbosity "warnings (3)"...
        Visualization Manager initialising...
        Registering graphics systems...

      

Note that the exact output shown will depend on how both Geant4 and your application were configured. Further output and behaviour beyond the Registering graphics systems... line will depend on what UI and Visualization drivers your Geant4 install supports. If you recall the use of the ui_all vis_all in the find_package command, this results in all available UI and Visualization drivers being activated in your application. If you didn't want any UI or Visualization, you could rerun CMake as:

$ cmake -DWITH_GEANT4_UIVIS=OFF -DGeant4_DIR=/home/you/geant4-install/lib64/Geant4-10.1.0 $HOME/B1
      

This would switch the option we set up to false, and result in find_package not activating any UI or Visualization for the application. You can easily adapt this pattern to provide options for your application such as additional components or features.

Once the build is configured, you can edit code for the application in its source directory. You only need to rerun make in the corresponding build directory to pick up and compile the changes. However, note that due to the use of CMake globbing to create the source file list, if you add or remove files, you need to rerun CMake to pick up the changes! This is another reason why Kitware recommend listing the sources explicitly.

2.8.1.2.  Building ExampleB1 with CMake on Windows with Visual Studio

We'll assume, for illustration only, that you've copied the exampleB1 sources into a directory

        C:\Users\Ben\Documents\examples\basic\B1
      

Let's now use the CMake GUI to configure the build and generate a Visual Studio solution for it, and then use Visual Studio to build the application from this solution. This process involves several steps, which we break down as follows.

  1. If you browse the contents of the source directory, you can see that it contains the CMakeLists.txt file. So our source directory is C:\Users\Ben\Documents\examples\basic\B1, in other words the directory holding the CMakeLists.txt file.

  2. Open the CMake (cmake-gui) executable, and click on the Browse Source... button in the top right hand corner of the window.

  3. Use the file browser popup to locate the B1 source directory, and click OK.

  4. Now we create the build directory in which to create the Visual Studio project files and hold the build products. This directory should not be the same as, or inside, the source directory. Therefore, let's create this build directory alongside our source directory.

    Click on the Browse Build... button in the top right hand side of the CMake GUI window. Use the file browser popup to browse back to C:\Users\Ben\Documents\examples\basic, and click on the Make New Folder button. Rename the created folder to B1-build, and click on the OK button. The two text entries at the top of the GUI should now contain C:/Users/Ben/Documents/examples/basic/B1 and C:/Users/Ben/Documents/examples/basic/B1-build respectively (Note: CMake always represents Windows paths with forward slashes).

  5. Before we can configure the project, we need to tell CMake where to find Geant4. To do this, click on the Add Entry button in the top right corner of the CMake GUI.

  6. In the Add Cache Entry window that pops up, set the Name of the entry to Geant4_DIR. Set the Type to PATH.

  7. In the Add Cache Entry window, click the browse button on the right hand side of the Value to pop up the Browse For Folder window. Browse to find your install of Geant4, and select the folder which contains the Geant4Config.cmake file. This is generally located in the lib/Geant4-X.Y.Z (where X.Y.Z is the Geant4 version number) folder inside the directory in which you installed Geant4.

  8. With Geant4_DIR set, click on the Configure button in the bottom left hand corner of the GUI.

  9. In the pop up window, select Visual Studio 12 (or 9 if you have that version installed) and ensure the Use default native compilers radio button is ticked. Click on the Finish button. CMake will run to check that your system can perform the build and that Geant4 can be found. It will output information on its status and any errors in the logging window at the bottom of the GUI.

  10. After a successful configuration, you will see Configuring done in the logging window at the bottom, and some red highlighted entries in the main window, including one for CMake. The red color does not always mean there has been an error, but denotes that CMake needs to rerun to resolve options it has found in the build. Simply reclick the Configure button to rerun CMake.

  11. After a further successful configuration, you will see Configuring done in the logging window at the bottom, and there should be no red colored entries in the main window. Now click on the Generate button to create the Visual Studio solution.

  12. After generation, you should see Configuring done, Generating done in the logging window at the bottom of the GUI. CMake has run successfully, and a Visual Studio solution has been created. You can now exit the CMake GUI.

  13. Now start up Visual Studio and choose Open Project. This guide is somewhat specific to Visual Studio 2010 Express, but the solution files should appear with the same names in both 2009 and 2013. Browse to your build directory and open the B1.sln Microsoft Visual Studio Solution file. It may take some time for Visual Studio to fully open the project and parse all the sources.

  14. In the Solution Explorer, you can click on the exampleB1 to view the sources for the project.

  15. Click on the Solution Configuration drop down, and change the configuration to Release. In general, it's best to build your application with the same configuration as your Geant4 installation. In this example, we built Geant4 in Release mode, so we build the B1 example in the same mode.

  16. To build the project, right click on ALL_BUILD in the Solution Explorer and click Build in the dialog box.

  17. Visual Studio will perform the build, and report on progress in Output.

  18. Whilst you can run the built application in Visual Studio, it can be tricky to set up all the paths correctly (see below). It's therefore easiest to open a cmd.exe window and cd to the build directory (the directory where the Visual Studio solution was generated). You can then run the built application directly from the command line. Note that because Visual Studio supports multiple configurations and we've built in Release mode, the application is located at Release\exampleB1.exe.

  19. On execution, the exampleB1 application should pop up a UI window, and a visualization window if your install of Geant4 was installed with OpenGL visualization.

  20. The exampleB1 can be controlled from the Geant4 CLI as normal, here we have run 10 events.

As noted above, you can also run the application through the Visual Studio debugger, although we have seen issues with setting the directory to run incorrectly. The executable locates the macro files by assuming they are in the current working directory, so the executable must be run from a directory containing the macros.

One key CMake related item to note goes back to our listing of the headers for the application in the call to add_executable. Whilst CMake will naturally ignore these for configuring compilation of the application, it will add them to the Visual Studio Solution. If you do not list them, they will not be editable in the Solution.

2.8.2.  Building ExampleB1 using Geant4Make

Geant4Make is the Geant4 GNU Make toolchain formerly used to build the toolkit and applications. If you have written Geant4 Applications which used a GNUmakefile and a "binmake.gmk" file, then Geant4Make is the system used behind the scenes to build your application. So whilst we now refer to this old system as "Geant4Make" the concepts should be familiar. This system, is still supplied so that your applications using Geant4Make will continue to build using the new CMake build and install of Geant4. However, due to incompatibilities between the way Geant4Make expects Geant4 to be installed and the standard install hierarchy now used, we do not support Geant4Make on Windows platforms. We encourage users to migrate to CMake to build their applications on Windows. Please also note that Geant4Make is deprecated and is not supported in Geant4 10.0 and later.

The Geant4Make GNUmake system is controlled by series of GNUmake modules which are installed under:

      +- CMAKE_INSTALL_PREFIX/ (where you installed Geant4)
         +- share/
            +- Geant4-10.1.0/
               +- geant4make/
                  +- geant4make.sh
                  +- geant4make.csh
                  +- config/
                     +- binmake.gmk
                     +- ...
    

The system is designed to form a self-contained GNUMake system which is configured primarily by environment variables (though you may manually replace these with variables in your GNUmakefile if you prefer). You may find more detailed documentation on this structure in Section 5. Building a Geant4 application using Geant4Make therefore involves configuring your environment followed by writing a GNUmakefile using the Geant4Make variables and GNUMake modules.

To configure your environment, simply source the relevant configuration script CMAKE_INSTALL_PREFIX/share/Geant4-10.1.0/geant4make/geant4make.(c)sh for your shell. Here, you should replace CMAKE_INSTALL_PREFIX with the actual directory you installed Geant4 under. Whilst both scripts can be sourced interactively, if you are using the C shell and need to source the script inside another script, you must use the commands:

      cd CMAKE_INSTALL_PREFIX/share/Geant4-10.1.0/geant4make
      source geant4make.csh
    

or alternatively

  source CMAKE_INSTALL_PREFIX/share/Geant4-10.1.0/geant4make/geant4make.csh \\
    CMAKE_INSTALL_PREFIX/share/Geant4-10.1.0/geant4make
    

In both cases, you should replace CMAKE_INSTALL_PREFIX with the actual directory you installed Geant4 under. Both of these commands work around a limitation in the C shell which prevents the script locating itself.

Please also note that due to limitations of Geant4Make, you should not rely on the environment variables it sets for paths into Geant4 itself. In particular, note that the G4INSTALL variable is not equivalent to CMAKE_INSTALL_PREFIX.

Once you have configured your environment, you can start building your application. Geant4Make enforces a specific organization and naming of your sources in order to simplify the build. Going back to our concrete application "ExampleB1", the sources are arranged just like before (so we have omitted some for clarity):

     +- B1/
         +- GNUmakefile
         +- exampleB1.cc
         +- include/
         |  ... headers.hh ...
         +- src/
            ... sources.cc ...
    

As before, exampleB1.cc contains main() for the application, with include/ and src/ containing the implementation class headers and sources respectively. You must organise your sources in this structure with these filename extensions to use Geant4Make as it will expect this structure when it tries to build the application.

With this structure in place, the GNUmakefile for exampleB1 is very simple:

      name := exampleB1
      G4TARGET := $(name)
      G4EXLIB := true

      .PHONY: all
      all: lib bin

      include $(G4INSTALL)/config/binmake.gmk
    

Here, name is set to the application to be built, and it must match the name of the file containing the main() program without the .cc extension. The rest of the variables are structural to prepare the build, and finally the core Geant4Make module is included. The G4INSTALL variable is set in the environment by the geant4make shell scripts to point to the root of the Geant4Make directory structure.

With this structure in place, simply run make in the same directory as the GNUmakefile to build your application:

      $ make
    

If you need extra detail on the build, you append CPPVERBOSE=1 to the make command to see a detailed log of the commands executed.

The application executable will be output to $(G4WORKDIR)/bin/$(G4SYSTEM)/exampleB1, where $(G4SYSTEM) is the system and compiler combination you are running on, e.g. Linux-g++. By default, $(G4WORKDIR) is set by the geant4make scripts to $(HOME)/geant4_workdir, and also prepends this directory to your PATH. You can therefore run the application directly once it's built:

      $ exampleB1
    

If you prefer to keep your application builds separate, then you can set G4WORKDIR in the GNUmakefile before including binmake.gmk. In this case you would have to run the executable by supplying the full path.

Further documentation of the usage of Geant4Make and syntax and extensions for the GNUMakefile is described in Section 5

Please note that the Geant4Make toolchain is deprecated and provided purely for convenience and backwards compatibility. We encourage you to use and migrate your applications to the CMake system or to use the geant4-config program with the buildsystem of your choice. Geant4Make is no longer supported in Geant4 10.0 and later.