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.
Geant4 installs a file named Geant4Config.cmake
located in:
+- CMAKE_INSTALL_PREFIX +- lib/ +- Geant4-10.3.0/ +- Geant4Config.cmake
which is designed for use with the CMake scripting language
find_package
command. Building a Geant4 application using CMake
therefore involves writing a CMake script
CMakeLists.txt
using this 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.
We'll use Basic Example B1, which you may find in the Geant4 source
directory under examples/basic/B1
, to demonstrate
the use of CMake to build a Geant4 application. You'll find
links to the latest CMake documentation for the commands used
throughout, so please
follow these for further information.
The application sources and scripts are arranged in the following
directory structure:
+- B1/ +- CMakeLists.txt +- exampleB1.cc +- include/ | ... headers.hh ... +- src/ ... sources.cc ...
Here, exampleB1.cc
contains
main()
for the application, with
include/
and src/
containing
the implementation class headers and sources respectively.
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_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:
Basic Configuration
The
cmake_minimum_required
command simply ensures we're using a suitable version of CMake.
Though the build of Geant4 itself requires CMake 3.3 and we recommend this version for your own projects,
Geant4Config.cmake
can support earlier
versions from 2.6.4 and the 2.8.X series.
The
project
command sets the name of the project and enables and configures
C and C++ compilers.
Find and Configure Geant4
The aforementioned
find_package
command is used to locate and configure Geant4 (we'll see how
to specify the location 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 later.
Configure the Project to Use Geant4 and B1 Headers
To automatically configure the header path, and force setting of compiler flags
and compiler definitions needed for compiling against 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 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.
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.
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.
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.
If Required, Install the Executable
Use the
install
command to create an install target that will install the
executable to a bin
directory under
CMAKE_INSTALL_PREFIX
.
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, and is easily extendable to
more involved use cases such as platform specific configuration or
using other third party packages
(via
find_package
).
With the CMake script in place, using it to build an application is a two step process. First CMake is run to generate buildscripts to describe the build. 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 we used 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/OS X 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.
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.
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.3.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. This provides the most specific way to point CMake to
the Geant4 install you want to use. You may also use the
CMAKE_PREFIX_PATH
variable, e.g.
$ cd $HOME/B1-build $ cmake -DCMAKE_PREFIX_PATH=/home/you/geant4-install $HOME/B1
This is most useful for system integrators as it may be extended with paths to the install prefixes of additional required software packages and also may be set as an environment variable that CMake will use at configuration time.
The second argument to CMake is the path to the source directory of the application we want to build. Here it's just the B1 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.3.0 $HOME/B1 -- The C compiler identification is GNU 4.9.2 -- The CXX compiler identification is GNU 4.9.2 -- Check for working C compiler: /usr/bin/gcc-4.9 -- Check for working C compiler: /usr/bin/gcc-4.9 -- works -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Detecting C compile features -- Detecting C compile features - done -- Check for working CXX compiler: /usr/bin/g++-4.9 -- Check for working CXX compiler: /usr/bin/g++-4.9 -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done -- Generating done -- Build files have been written to: /home/you/B1-build
On 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 Makefile vis.mac CMakeFiles exampleB1.out run1.mac cmake_install.cmake init_vis.mac run2.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/B1PrimaryGeneratorAction.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/B1DetectorConstruction.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_vis.mac run2.mac CMakeFiles exampleB1.in Makefile vis.mac cmake_install.cmake exampleB1.out run1.mac
You can now run the application in place:
$ ./exampleB1 Available UI session types: [ GAG, tcsh, csh ] ************************************************************* Geant4 version Name: geant4-10-03 [MT] (2-December-2016) << 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.3.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.
As with building Geant4 itself, the simplest system to use for building applications on Windows is a Visual Studio Developer Command Prompt, which can be started from Start → All Programs → Visual Studio 2015 → Visual Studio Tools → Developer Command Prompt for VS2015.
We'll assume, for illustration only, that
you've copied the exampleB1 sources into a directory
C:\Users\YourUsername\Geant4\B1
so that
we have
+- C:\Users\YourUsername\Geant4\B1 +- CMakeLists.txt +- exampleB1.cc +- include\ +- src\ +- ...
Here, our source directory is
C:\Users\YourUsername\Geant4\B1
, in other words the directory
holding the CMakeLists.txt
file.
Let's also assume that you have already installed Geant4 in your
home area under, for illustration only,
C:\Users\YourUsername\Geant4\geant4_10_03-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, working from the Visual Studio Developer Command Prompt:
> cd %HOMEPATH%\Geant4 > mkdir B1-build
We now change to this build directory and run CMake to generate the Visual Studio solution needed to build the B1 application. We pass CMake two arguments:
> cd %HOMEPATH%\Geant4\B1-build > cmake -DGeant4_DIR=%HOMEPATH%\geant4_10_03-install\lib\Geant4-10.3.0 %HOMEPATH%\Geant4\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. As with the examples above, you can also use the
CMAKE_PREFIX_PATH
variable.
The second argument is the path to the source directory of the application we want to build. Here it's just the B1 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 Visual Studio solutions and you will see the output
> cmake -DGeant4_DIR=%HOMEPATH%\geant4_10_03-install\lib\Geant4-10.3.0 %HOMEPATH%\Geant4\B1 -- Building for: Visual Studio 14 2015 -- The C compiler identification is MSVC 19.0.23026.0 -- The CXX compiler identification is MSVC 19.0.23026.0 -- Check for working C compiler using: Visual Studio 14 2015 -- Check for working C compiler using: Visual Studio 14 2015 -- works -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working CXX compiler using: Visual Studio 14 2015 -- Check for working CXX compiler using: Visual Studio 14 2015 -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done -- Generating done -- Build files have been written to: C:/Users/YourUsername/Geant4/B1-build
If you now list the contents of you build directory, you can see the files generated:
> dir /B ALL_BUILD.vcxproj ALL_BUILD.vcxproj.filters B1.sln B1.vcxproj B1.vcxproj.filters CMakeCache.txt CMakeFiles cmake_install.cmake exampleB1.in exampleB1.out exampleB1.vcxproj exampleB1.vcxproj.filters init_vis.mac INSTALL.vcxproj INSTALL.vcxproj.filters run1.mac run2.mac vis.mac ZERO_CHECK.vcxproj ZERO_CHECK.vcxproj.filters
Note the B1.sln
solution file and that all the
scripts for
running the exampleB1 application we're about to build have been
copied across. With the solution available, we can now build by
running cmake to drive MSBuild:
> cmake --build . --config Release
Solution based builds are quite verbose, but you should not see
any errors at the end. In the above, we have built the B1 program
in Release
mode, meaning that it is
optimized and has no debugging symbols. As with building Geant4 itself,
this is chosen to provide optimum performance. If you require debugging information
for your application, simply change the argument to RelWithDebInfo
.
Note that in both cases you must match the configuration of your application
with that of the Geant4 install, i.e. if you are building the application
in Release
mode, then ensure it uses a Release
build of Geant4. Link and/or runtime errors may result if mixed configurations
are used.
After running the build, if we list the contents of the build directory again we see
> dir /B ALL_BUILD.vcxproj ALL_BUILD.vcxproj.filters B1.sln B1.vcxproj B1.vcxproj.filters CMakeCache.txt CMakeFiles cmake_install.cmake exampleB1.dir exampleB1.in exampleB1.out exampleB1.vcxproj exampleB1.vcxproj.filters init_vis.mac INSTALL.vcxproj INSTALL.vcxproj.filters Release run1.mac run2.mac vis.mac Win32 ZERO_CHECK.vcxproj ZERO_CHECK.vcxproj.filters > dir /B Release exampleB1.exe ...
Here, the Release
subdirectory
contains the executable, and the main build directory contains
all the .mac
scripts for running the program.
If you build in different modes, the executable for that mode will
be in a directory named for that mode, e.g. RelWithDebInfo/exampleB1.exe
.
You can now run the application in place:
> .\Release\exampleB1.exe Available UI session types: [ Win32, GAG, csh ] ************************************************************* Geant4 version Name: geant4-10-03 (2-December-2016) 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.
Whilst the Visual Studio Developer Command prompt provides the
simplest way to build an application, the generated Visual Studio
Solution file (B1.sln
in the above example)
may also be opened directly in the Visual Studio IDE. This
provides a more comprehensive development and debugging
environment, and you should consult its documentation if you
wish to use this.
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 in the Visual Studio IDE.
Geant4Make is the Geant4 GNU Make toolchain formerly used to build
the toolkit and applications. It is installed on UNIX systems
(except for Cygwin) for backwards
compatibility with the Geant4 Examples and your existing
applications which use a GNUmakefile and the Geant4Make
binmake.gmk
file.
However, please note
that the system is now deprecated, meaning that it
is no longer supported and may be removed in future releases without
warning. You should migrate your application to be built using CMake
via the Geant4Config.cmake
script, or any other
build tool of your choice, using the geant4-config
program to query the relevant compiler/linker flags.
The files for Geant4Make are installed under:
+- CMAKE_INSTALL_PREFIX/ +- share/ +- 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 Make variables if you prefer). 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.3.0/geant4make/geant4make.(c)sh
for your shell. 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.3.0/geant4make source geant4make.csh
or alternatively
source CMAKE_INSTALL_PREFIX/share/Geant4-10.3.0/geant4make/geant4make.csh \\ CMAKE_INSTALL_PREFIX/share/Geant4-10.3.0/geant4make
In both cases, you should replace
CMAKE_INSTALL_PREFIX
with the actual prefix 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. We'll use
Basic Example B1, which you may find in the Geant4 source directory
under examples/basic/B1
, as the canonical
example again. Here, the sources are arranged as follows
+- 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
script to point to the root
of the Geant4Make directory structure.
With this structure in place, simply run make
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 command 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
the FAQ and Appendices of the Geant4 User's Guide for Application Developers.
Please note that the Geant4Make toolchain is provided purely for
conveniance and backwards compatibility. We encourage you to use
and migrate your applications to the new CMake and
geant4-config
tools. Geant4Make is deprecated in Geant4 10.0 and later.