Information for C++ Developers

The dune Python bindings rely on just in time (JIT) compilation which takes place in a special dune module dune-py. Which each C++ type a Python module is generated there. One can obtain information about and manipulate this module using the dune main script:

python -m dune
usage: dune [-h] {info,configure,list,remove,fix-dunepy,dunetype,checkbuilddirs}

remove              Remove generated modules
make                Remake already existing modules in parallel
info                Print information about dune-py
list                List all generated modules
dunetype            Show dune types for given modules

fix-dunepy          Find inconsistencies in dune-py and try to fix automatically. This will potentially delete all generated modules.
configure           Tag dune-py to be reconfigured before next use
checkbuilddirs      (internal use) Check build directories

Remove and rebuild existing modules

Probably the most important option here is remove which simplifies removing specific modules from dune-py. This is important to debug C++ code because a module can then be recompiled with debugging compiler flags.

python -m dune remove
usage: dune remove [-h] [--beforedate] [modules [modules ...]]

positional arguments:
  modules       Patterns of modules ("\*.cc" and dune-py path is added to each argument) or "all"

optional arguments:
  -h, --help    show this help message and exit
  --beforedate  Instead of a pattern provide a date to remove all modules not having been loaded
                after that date

In addition to providing a full module (without extension and path), one can provide the module prefix (e.g. hierarchicalgrid) and all modules with this prefix will be removed. If is quite easy to find the module name from a generated dune object in Python by using the __module__ magic attribute. The following script outputs

from dune.grid import structuredGrid
view = structuredGrid([0,0],[1,1],[10,10])
print(view.__module__)

dune.generated.hierarchicalgrid_966e2a5c8356c5b278ccd3acad180f0a. So removing this module can be achieved by calling

python -m dune remove hierarchicalgrid_966e2a5c8356c5b278ccd3acad180f0a

There are two options to compile a module that has not been generated yet (e.g. was removed) with different flags. Either by setting the CXXFLAGS environment variable, e.g.,

CXXFLAGS=-g python test.py

Alternatively, we can set the flags from within a Python script

import dune.generator as generator
generator.addToFlags("-DWANT_CACHED_COMM_MANAGER=0",noChecks=True)
algorithm(...)
generator.setFlags("-g -Wfatal-errors",noChecks=True)
algorithm(...)
generator.reset()

Another useful command is make which can be used to rebuild existing modules after some source code change. The modules argument is the same as for the remove command described above. In addition -jN can be used to fix the number of threads to use for making multiple modules in parallel. By default four threads are used. As described above CXXFLAGS can be specified. So for example

CXXFLAGS=-g python -m dune make -j8 hierarchicalgrid

will rebuild all hierarchicalgrid which are out of date with debug flags. One can force remaking, e.g., to change the compiler flags by providing the –force (or -B) flag. Note that after debugging the code one should rebuild to get optimized modules:

python -m dune make --force -j8 hierarchicalgrid

One can also remove or rebuild all modules used in a given script by first adding

dune.generated.requiredModules("moduleslist.txt")

to the end of the script. This will produce a file moduleslist.txt containing all dune jit modules loaded during the run of the script. Then one can rebuild (or remove) all modules by for example running

python -m dune remove --file moduleslist.txt

or to force rebuilding all required modules with debug flags

CXXFLAGS=-g python -m dune make -j12 -B --file moduleslist.txt

Finally, this rebuilding of the required modules can be carried out at the beginning of the script by adding for example

dune.commands.makegenerated(fileName="moduleslist.txt", threads=12)

The function also takes a boolean force argument.

Using a debugger

After rebuilding a module, which is producing an error, with debug flags as discussed above, we can use something like gdb to debug the C++ code

gdb python
(gdb) r test.py

List of build specific environment variables

Other available environment variables are

  • DUNE_LOG_LEVEL: set to info or debug to get more verbose output during module building.

  • DUNE_SAVE_BUILD: show full output from compiler during JIT compilation. Set to terminal to obtain output to console or set to write to obtain log files in current folder.

  • DUNE_PY_DIR: location of dune-py module

  • DUNE_CMAKE_FLAGS: cmake flags to use during configuration of a new dune-py module

  • DUNEPY_DISABLE_PLOTTING: disable plotting using the dune plotting functions

https://zenodo.org/badge/DOI/10.5281/zenodo.3706994.svg