diff --git a/SConstruct b/SConstruct
index 4668e7fd..479aad9f 100644
--- a/SConstruct
+++ b/SConstruct
@@ -1,438 +1,445 @@
 # -*- mode:python; coding: utf-8 -*-
 # vim: set ft=python:
 
 # @file
 # @section LICENSE
 #
 # Copyright (©) 2016-2020 EPFL (École Polytechnique Fédérale de Lausanne),
 # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Affero General Public License as published
 # by the Free Software Foundation, either version 3 of the License, or
 # (at your option) any later version.
 #
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU Affero General Public License for more details.
 #
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 # ------------------------------------------------------------------------------
 # Imports
 # ------------------------------------------------------------------------------
 from __future__ import print_function
 
 import os
 
 import SCons
 
 from os.path import join, abspath
 
 # Import below not strictly necessary, but good for pep8
 from SCons.Script import (
     EnsurePythonVersion,
     EnsureSConsVersion,
     Help,
     Environment,
     Variables,
     EnumVariable,
     PathVariable,
     BoolVariable,
     Split,
     SConscript,
     Export,
     Dir
 )
 
 from version import get_git_subst
 from detect import (
     FindFFTW,
     FindBoost,
     FindThrust,
     FindCuda,
     FindExpolit,
     FindPybind11
 )
 
 # ------------------------------------------------------------------------------
 
 EnsurePythonVersion(2, 7)
 EnsureSConsVersion(2, 4)
 
 # ------------------------------------------------------------------------------
 
 tamaas_info = dict(
     version="2.1.2",
     authors=[
         u'Lucas Frérot',
         'Guillaume Anciaux',
         'Valentine Rey',
         'Son Pham-Ba',
         u'Jean-François Molinari'
     ],
     maintainer=u'Lucas Frérot',
     email='lucas.frerot@protonmail.com',
     copyright=u"Copyright (©) 2016-2020 EPFL "
     + u"(École Polytechnique Fédérale de Lausanne), "
     + u"Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)"
 )
 
 
 # ------------------------------------------------------------------------------
 def detect_dependencies(env):
     """Detect all dependencies"""
     FindFFTW(env, ['omp'], precision=env['real_type'])
     FindBoost(env, ['boost/preprocessor/seq.hpp'])
     FindExpolit(env)
 
     thrust_var = 'THRUST_ROOT'
 
     # Take cuda version of thrust if available
     if 'CUDA_ROOT' in env['ENV']:
         thrust_var = 'CUDA_ROOT'
 
     FindThrust(env, env['backend'], thrust_var)
 
     # Activate cuda if needed
     if env['backend'] == 'cuda':
         FindCuda(env)
 
     if env['build_python']:
         FindPybind11(env)
 
 
 # ------------------------------------------------------------------------------
 # Main compilation
 # ------------------------------------------------------------------------------
 
 # Compilation colors
 colors = {
-  'cyan': '\033[96m',
-  'purple': '\033[95m',
-  'blue': '\033[94m',
-  'green': '\033[92m',
-  'yellow': '\033[93m',
-  'red': '\033[91m',
-  'end': '\033[0m'
+    'cyan': '\033[96m',
+    'purple': '\033[95m',
+    'blue': '\033[94m',
+    'green': '\033[92m',
+    'yellow': '\033[93m',
+    'gray': '\033[38;5;8m',
+    'orange': '\033[38;5;208m',
+    'red': '\033[91m',
+    'end': '\033[0m'
 }
 
 # Inherit all environment variables (for CXX detection, etc.)
 main_env = Environment(
     ENV=os.environ,
 )
 
 # Set tamaas information
 for k, v in tamaas_info.items():
     main_env[k] = v
 
 main_env['COLOR_DICT'] = colors
 
 # Compiler detection
 compiler_default = os.getenv('CXX', 'g++')
 
 # Build variables
 vars = Variables('build-setup.conf')
 vars.AddVariables(
     EnumVariable('build_type', 'Build type', 'release',
                  allowed_values=('release', 'profiling', 'debug'),
                  ignorecase=2),
     EnumVariable('backend', 'Thrust backend', 'omp',
                  allowed_values=('omp', 'tbb'),
                  # allowed_values=('omp', 'cuda'),
                  ignorecase=2),
     EnumVariable('sanitizer', 'Sanitizer type', 'none',
                  allowed_values=('none', 'memory', 'leaks', 'address'),
                  ignorecase=2),
 
     PathVariable('prefix',
                  'Prefix where to install', '/usr/local'),
 
     # Dependencies paths
     PathVariable('FFTW_ROOT',
                  'FFTW custom path', os.getenv('FFTW_ROOT', ''),
                  PathVariable.PathAccept),
     PathVariable('THRUST_ROOT',
                  'Thrust custom path', os.getenv('THRUST_ROOT', ''),
                  PathVariable.PathAccept),
     PathVariable('BOOST_ROOT',
                  'Boost custom path', os.getenv('BOOST_ROOT', ''),
                  PathVariable.PathAccept),
     PathVariable('CUDA_ROOT',
                  'Cuda custom path', os.getenv('CUDA_ROOT', ''),
                  PathVariable.PathAccept),
     # Dependencies provided as submodule get different default
     PathVariable('GTEST_ROOT',
                  'Googletest custom path',
                  os.getenv('GTEST_ROOT', '#third-party/googletest/googletest'),
                  PathVariable.PathAccept),
     PathVariable('PYBIND11_ROOT',
                  'Pybind11 custom path',
                  os.getenv('PYBIND11_ROOT', '#third-party/pybind11/include'),
                  PathVariable.PathAccept),
     PathVariable('EXPOLIT_ROOT',
                  'Expolit custom path',
                  os.getenv('EXPOLIT_ROOT', '#third-party/expolit/include'),
                  PathVariable.PathAccept),
 
     # Executables
     ('CXX', 'Compiler', compiler_default),
     ('py_exec', 'Python executable', 'python3'),
 
     # Compiler flags
     ('CXXFLAGS', 'C++ compiler flags', os.getenv('CXXFLAGS', "")),
 
     # Compile legacy code
     BoolVariable('legacy_bem', 'Compile legacy BEM code', False),
     # Cosmetic
     BoolVariable('verbose', 'Activate verbosity', False),
     BoolVariable('color', 'Color the non-verbose compilation output', False),
 
     # Tamaas components
     BoolVariable('build_doc', 'Build documentation', False),
     BoolVariable('build_tests', 'Build test suite', False),
     BoolVariable('build_python', 'Build python wrapper', True),
 
     # Dependencies
     BoolVariable('use_googletest', 'Build tests using GTest', False),
 
     # Distribution options
     BoolVariable('strip_info', 'Strip binary of added information', False),
     BoolVariable('packaging_setup', "Modify setup.py and python wrapper "
                  "RPATHs for packaging to PyPI (maintainer only)", False),
 
     # Type variables
     EnumVariable('real_type', 'Type for real precision variables', 'double',
                  allowed_values=('double', 'long double')),
     EnumVariable('integer_type', 'Type for integer variables', 'int',
                  allowed_values=('int', 'long')),
 )
 
 # Set variables of environment
 vars.Update(main_env)
 help_text = vars.GenerateHelpText(main_env)
 help_text += """
 Commands:
     scons [build] [options]...                            Compile Tamaas (and additional modules/tests)
     scons install [prefix=/your/prefix] [options]...      Install Tamaas to prefix
     scons dev                                             Install symlink to Tamaas python module (useful to development purposes)
     scons test                                            Run tests with pytest
     scons doc                                             Compile documentation with Doxygen and Sphinx+Breathe
     scons archive                                         Create a gzipped archive from source
 """  # noqa
 Help(help_text)
 
 # Save all options, not just those that differ from default
 with open('build-setup.conf', 'w') as setup:
     for option in vars.options:
         setup.write("# " + option.help + "\n")
         setup.write("{} = '{}'\n".format(option.key, main_env[option.key]))
 
 main_env['should_configure'] = \
     not main_env.GetOption('clean') and not main_env.GetOption('help')
 
 build_type = main_env['build_type']
 build_dir = 'build-' + main_env['build_type']
 main_env['build_dir'] = build_dir
 
 if main_env['should_configure']:
     print("Building in " + build_dir)
 
 if main_env['packaging_setup']:
     main_env['strip_info'] = True
 
 verbose = main_env['verbose']
 
 # Remove colors if not set
 if not main_env['color']:
     for key in colors:
         colors[key] = ''
 
 if not verbose:
     main_env['CXXCOMSTR'] = main_env['SHCXXCOMSTR'] = \
         u'{0}[Compiling ($SHCXX)] {1}$SOURCE'.format(colors['green'],
                                                      colors['end'])
     main_env['LINKCOMSTR'] = main_env['SHLINKCOMSTR'] = \
         u'{0}[Linking] {1}$TARGET'.format(colors['purple'],
                                           colors['end'])
+    main_env['ARCOMSTR'] = u'{}[Ar]{} $TARGET'.format(colors['purple'],
+                                                      colors['end'])
+    main_env['RANLIBCOMSTR'] = \
+        u'{}[Randlib]{} $TARGET'.format(colors['purple'],
+                                        colors['end'])
     main_env['PRINT_CMD_LINE_FUNC'] = pretty_cmd_print
 
 # Include paths
 main_env.AppendUnique(CPPPATH=['#/src',
                                '#/src/core',
                                '#/src/bem',
                                '#/src/surface',
                                '#/src/python',
                                '#/src/percolation',
                                '#/src/model',
                                '#/src/model/elasto_plastic',
                                '#/src/solvers',
                                '#/src/gpu',
                                '#/python'])
 
 # Changing the shared object extension
 main_env['SHOBJSUFFIX'] = '.o'
 
 # Back to gcc if cuda is activated
 if main_env['backend'] == "cuda" and "g++" not in main_env['CXX']:
     raise SCons.Errors.StopError('GCC should be used when compiling with CUDA')
 
 # OpenMP flags - compiler dependent
 omp_flags = {
     "g++": ["-fopenmp"],
     "clang++": ["-fopenmp"],
     "icpc": ["-qopenmp"]
 }
 
 
 def cxx_alias(cxx):
     for k in omp_flags.keys():
         if k in cxx:
             return k
 
     raise SCons.Errors.StopError('Unsupported compiler: ' + cxx)
 
 
 cxx = cxx_alias(main_env['CXX'])
 main_env['CXXFLAGS'] = Split(main_env['CXXFLAGS'])
 main_env.AppendUnique(CXXFLAGS='-std=c++14 -Wall -Wextra -pedantic'.split())
 
 # Append openmp flags regardless of backend for fftw_omp
 main_env.AppendUnique(CXXFLAGS=omp_flags[cxx])
 main_env.AppendUnique(LINKFLAGS=omp_flags[cxx])
 
 # Correct bug in clang?
 if main_env['backend'] == 'omp' and cxx == "clang++":
     main_env.AppendUnique(LIBS=["atomic"])
 elif main_env['backend'] == 'tbb':
     main_env.AppendUnique(LIBS=['tbb'])
 
 # Force deactivate legacy when using intel
 # Intel does not like old openmp loops
 if cxx == 'icpc' and main_env['legacy_bem']:
     print("Using intel compiler => deactivating legacy code")
     main_env['legacy_bem'] = False
 
 # Flags and options
 if main_env['build_type'] == 'debug':
     main_env.AppendUnique(CPPDEFINES=['TAMAAS_DEBUG'])
 
 # Define the scalar types
 main_env.AppendUnique(CPPDEFINES={'REAL_TYPE': '${real_type}',
                                   'INT_TYPE': '${integer_type}'})
 
 # Compilation flags
 cxxflags_dict = {
     "debug": Split("-g -O0"),
     "profiling": Split("-g -O3 -fno-omit-frame-pointer"),
     "release": Split("-O3")
 }
 
 if main_env['sanitizer'] != 'none':
     if main_env['backend'] == 'cuda':
         raise SCons.Errors.StopError(
             "Sanitizers with cuda are not yet supported!")
     cxxflags_dict[build_type].append('-fsanitize=${sanitizer}')
 
 main_env.AppendUnique(CXXFLAGS=cxxflags_dict[build_type])
 main_env.AppendUnique(SHLINKFLAGS=cxxflags_dict[build_type])
 main_env.AppendUnique(LINKFLAGS=cxxflags_dict[build_type])
 
 if main_env['should_configure']:
     detect_dependencies(main_env)
 
 # Writing information file
 main_env.Tool('textfile')
 main_env['SUBST_DICT'] = get_git_subst()
 
 # Empty values if requested
 if main_env['strip_info']:
     for k in main_env['SUBST_DICT']:
         main_env['SUBST_DICT'][k] = ""
 
 # Substitution of environment file
 main_env['SUBST_DICT'].update({
     '@build_type@': '$build_type',
     '@build_dir@': abspath(build_dir),
 })
 
 # Environment file content
 env_content = """export PYTHONPATH=@build_dir@/python:$$PYTHONPATH
 export LD_LIBRARY_PATH=@build_dir@/src:$$LD_LIBRARY_PATH
 """
 
 # Writing environment file
 env_file = main_env.Textfile(join(build_dir, 'tamaas_environment.sh'),
                              env_content)
 
 
 # Building sub-directories
 def subdir(dir):
     return SConscript(join(dir, 'SConscript'),
                       variant_dir=join(build_dir, dir),
                       duplicate=True)
 
 
 # Building Tamaas library
 Export('main_env')
 subdir('src')
 
 build_targets = ['build-cpp', env_file]
 install_targets = ['install-lib']
 
 # Building Tamaas extra components
 for dir in ['python', 'tests']:
     if main_env['build_{}'.format(dir)] and not main_env.GetOption('help'):
         subdir(dir)
         build_targets.append('build-{}'.format(dir))
 
 # Building API + Sphinx documentation if requested
 if main_env['build_doc']:
     doc_env = main_env.Clone()
     doc = doc_env.Command('#.phony_doc', '',
                           'make -C {doc} clean && make -C {doc}'
                           .format(doc=Dir('#/doc')))
     if doc_env['build_python']:
         doc_env.PrependENVPath('PYTHONPATH',
                                doc_env.subst('../${build_dir}/python'))
 
         doc_env.Depends(doc, 'build-python')
     main_env.Alias('doc', doc)
 else:
     dummy_command(main_env, 'doc', 'Command "doc" does not do anything'
                   ' without documentation activated ("build_doc=True")')
 
 # Define dummy dev command when python is deactivated
 if not main_env['build_python']:
     dummy_command(main_env, 'dev', 'Command "dev" does not do anything'
                   + ' without python activated ("build_python=True")')
 else:
     install_targets.append('install-python')
 
 # Define dummy test command when tests are deactivated
 if not main_env['build_tests']:
     dummy_command(main_env, 'test', 'Command "test" does not do anything'
                   + ' without tests activated ("build_tests=True")')
 
 # Definition of target aliases, a.k.a. sub-commands
 main_env.Alias('build', build_targets)
 
 # Define proper install targets
 main_env.Alias('install', install_targets)
 
 # Default target is to build stuff
 main_env.Default('build')
 
 # Building a tar archive
 archive = main_env.Command(
     '../tamaas-{}.tar.gz'.format(main_env['version']),
     '',
     ('tar --exclude-vcs --exclude-vcs-ignores '
      '--exclude=third-party/googletest '
      '--exclude=third-party/pybind11 '
      '--exclude=joss '
      '-czf $TARGET .'),
 )
 main_env.Alias('archive', archive)
diff --git a/site_scons/site_init.py b/site_scons/site_init.py
index c80730e5..3a80aa4d 100644
--- a/site_scons/site_init.py
+++ b/site_scons/site_init.py
@@ -1,126 +1,126 @@
 # -*- coding: utf-8 -*-
 
 # @file
 # @section LICENSE
 #
 # Copyright (©) 2016-2020 EPFL (École Polytechnique Fédérale de Lausanne),
 # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Affero General Public License as published
 # by the Free Software Foundation, either version 3 of the License, or
 # (at your option) any later version.
 #
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU Affero General Public License for more details.
 #
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 import subprocess
 
 from detect import FindPybind11
 
 
 # ------------------------------------------------------------------------------
 def pybind11(env):
     """A tool to configure pybind11"""
     def execute(command):
         return [line for line in subprocess.check_output(
             command, universal_newlines=True).split('\n')
                 if line != ""]
 
     # Create a clone so we do not modify env
     clone = env.Clone()
 
     # Set variables for clone
     FindPybind11(clone)
     includes = clone['CPPPATH']
 
     # Extension of shared library for python
     try:
         extension = execute(
             '{}-config --extension-suffix'.format(env['py_exec']).split())[0]
     except subprocess.CalledProcessError:
         extension = ".so"
 
     def pybind11_builder(env, target, source, **kwargs):
         """Create a pybind11 module"""
         clone = env.Clone()
         clone.AppendUnique(CPPPATH=includes)
         clone['SHLIBSUFFIX'] = extension
         clone.AppendUnique(SHLINKFLAGS=['-fvisibility=hidden'])
         return clone.SharedLibrary(target, source, **kwargs)
 
     # Add pseudo-builder to master environment
     env.AddMethod(pybind11_builder, 'Pybind11Module')
 
 
 # ------------------------------------------------------------------------------
 def pretty_cmd_print(command, target, source, env):
     colors = env['COLOR_DICT']
     if 'Copy' in command:
-        color = colors['red']
+        color = colors['gray']
         action = 'Copying'
     elif 'Creating' in command:
         color = colors['yellow']
         action = 'Generating'
     else:
         print(command)
         return
 
     print("{color}[{action}] {end}{target}".format(
         color=color,
         end=colors['end'],
         target=target[0],
         action=action
     ))
 
 
 # ------------------------------------------------------------------------------
 def CheckPythonModule(context, module):
     """Checks the existence of a python module"""
     context.Message('Checking for Python module {}... '.format(module))
     env = context.sconf.env
     command = [env.subst('${py_exec}'), '-c', 'import {}'.format(module)]
 
     context.Log('Executing external command: {}\n'.format(command))
 
     try:
         subprocess.check_output(command, stderr=subprocess.STDOUT)
         result = True
     except subprocess.CalledProcessError as e:
         result = False
         context.Log(e.output + '\n')
 
     context.Result(result)
     return result
 
 
 # ------------------------------------------------------------------------------
 def dummy_command(env, command, error_msg):
     """Creates a dummy scons command"""
     def print_error(*args, **kwargs):
         print(error_msg)
 
     def print_cmd(*args, **kwargs):
         pass
 
     comm = env.Command('#.phony_{}'.format(command),
                        '', print_error, PRINT_CMD_LINE_FUNC=print_cmd)
     env.Alias(command, comm)
 
 
 # ------------------------------------------------------------------------------
 def get_python_version(env):
     versions_script = """
 from __future__ import print_function
 from sysconfig import get_python_version
 print(get_python_version())"""
     version = subprocess.check_output([env['py_exec'], "-c", versions_script],
                                       universal_newlines=True).replace('\n',
                                                                        '')
     print(version)
     return version
diff --git a/tests/SConscript b/tests/SConscript
index 44a6e2da..474e783f 100644
--- a/tests/SConscript
+++ b/tests/SConscript
@@ -1,217 +1,208 @@
 # -*- mode:python; coding: utf-8 -*-
 # vim: set ft=python:
 
 # @file
 # @section LICENSE
 #
 # Copyright (©) 2016-2020 EPFL (École Polytechnique Fédérale de Lausanne),
 # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Affero General Public License as published
 # by the Free Software Foundation, either version 3 of the License, or
 # (at your option) any later version.
 #
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU Affero General Public License for more details.
 #
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 from __future__ import print_function
 
 from os.path import join
 
 from SCons.Script import Split, Copy, Dir, Import
 from detect import FindGTest, FindPybind11
 
 
 # ------------------------------------------------------------------------------
 def copyComStr(env, main):
     if 'SHCXXCOMSTR' in main:
         env['CXXCOMSTR'] = main['SHCXXCOMSTR']
     if 'SHLINKCOMSTR' in main:
         env['LINKCOMSTR'] = main['SHLINKCOMSTR']
 
 
 # ------------------------------------------------------------------------------
 def make_python_tests(env):
     """Copy python tests to build directory"""
     test_env = env.Clone()
 
     test_files = Split("""
     test_hertz.py
     test_westergaard.py
     test_patch_westergaard.py
     test_patch_plasticity.py
     test_surface.py
     test_hertz_disp.py
     test_hertz_kato.py
     test_saturated_pressure.py
     test_flood_fill.py
     test_integral_operators.py
     test_dumper.py
     test_tangential.py
     test_boussinesq_surface.py
     test_voigt.py
     test_memory.py
     test_epic.py
     fftfreq.py
     conftest.py
     """)
 
     if env['legacy_bem']:
         test_files += ['test_bem_grid.py', 'test_autocorrelation.py']
 
     src_dir = "#/tests"
 
     targets = [
         test_env.Command(file, join(src_dir, file),
                          Copy("$TARGET", "$SOURCE"))
         for file in test_files
     ]
 
     test_env = env.Clone(tools=[pybind11])
     # Helper module for integral operators
     test_env['SHLIBPREFIX'] = ''
     register = test_env.Pybind11Module(
         target="register_integral_operators",
         source=["register_integral_operators.cpp"],
         LIBS=['Tamaas'])
 
     Import('libTamaas')
     test_env.Depends(register, libTamaas)
     targets.append(register)
 
     return targets
 
 
 # ------------------------------------------------------------------------------
 def compile_google_test(env, gtest_path):
     gtest_obj = env.Object('gtest.o', [join(gtest_path, "src/gtest-all.cc")])
     return env.StaticLibrary('gtest', gtest_obj)
 
 
 # ------------------------------------------------------------------------------
 def make_google_tests(env):
     gtest_dir = Dir(env['GTEST_ROOT'])
 
     gtest_env = env.Clone(CPPPATH=[gtest_dir],
                           CXXFLAGS=['-pthread', '-isystem',
                                     join(str(gtest_dir), "include")])
 
-    colors = env['COLOR_DICT']
-
-    if not env['verbose']:
-        gtest_env['ARCOMSTR'] = u'{}[Ar]{} $TARGET'.format(colors['purple'],
-                                                           colors['end'])
-        gtest_env['RANLIBCOMSTR'] = \
-            u'{}[Randlib]{} $TARGET'.format(colors['purple'],
-                                            colors['end'])
-
     FindGTest(gtest_env)
 
     libgtest = None
     # Hugly hack to detect if we need to compile gtest submodule
     if env['GTEST_ROOT'] == '#third-party/googletest/googletest':
         gtest_path = str(gtest_dir)
         libgtest = compile_google_test(gtest_env, gtest_path)
 
     env.AppendUnique(LIBS=['Tamaas'],
                      CXXFLAGS=gtest_env['CXXFLAGS'])
 
     google_test_files = Split("""
                               test_fft.cpp
                               test_grid.cpp
                               test_loop.cpp
                               test_model.cpp
                               test_static_types.cpp
                               test_integration.cpp
                               """)
 
     # Necessary for the tests that use pybind11 calls to python
     use_python = []
     if env['build_python']:
         google_test_files.append('test_fftfreq.cpp')
         use_python = ['USE_PYTHON']
 
     defines = env['CPPDEFINES']
     if type(defines) is not list:
         defines = [defines]
 
     gtest_main = env.Object("tamaas_gtest_main.o", 'tamaas_gtest_main.cc',
                             CPPDEFINES=defines + use_python)
     gtest_all = env.Program('test_gtest_all', google_test_files + [gtest_main],
                             LIBS=(env['LIBS'] + ['gtest']))
     Import('libTamaas')
     env.Depends(gtest_all, libTamaas)
     env.Depends(gtest_all, libgtest)
 
     return [gtest_all]
 
 
 # ------------------------------------------------------------------------------
 def make_bare_tests(env):
     rough = env.Program("test_rough_surface.cpp")
     Import('libTamaas')
     env.Depends(rough, libTamaas)
 
     return [rough]
 
 
 # ------------------------------------------------------------------------------
 Import('main_env')
 
 # Setup of test environment
 test_env = main_env.Clone()
 test_env.AppendUnique(
     LIBS=['Tamaas'],
     LIBPATH=['.', Dir(join('#${build_dir}', 'src'))],
     RPATH=["'$$$$ORIGIN/../src'"]
 )
 
 # Building tests that do not require any third party
 targets = make_bare_tests(test_env)
 
 # Build tests that required python bindings
 if test_env['build_python']:
     FindPybind11(test_env)
     test_env.Tool(pybind11)
     test_env.ParseConfig("${py_exec}-config --ldflags")
     test_env['CCFLAGS'] = []
 
     targets += make_python_tests(test_env)
 
 # Building google tests
 if test_env['use_googletest']:
     targets += make_google_tests(test_env)
     targets.append(test_env.Command('test_gtest.py', '#tests/test_gtest.py',
                                     Copy('$TARGET', '$SOURCE')))
 
 # Target alias to build tests
 main_env.Alias('build-tests', targets)
 
 # Check if pytest is installed
 conf = Configure(main_env,
                  custom_tests={'CheckPythonModule': CheckPythonModule})
 
 has_pytest = conf.CheckPythonModule('pytest')
 conf.Finish()
 
 # Define a command to execute tests
 if has_pytest:
     pytest_env = main_env.Clone()
     pytest_env.PrependENVPath('PYTHONPATH',
                               pytest_env.subst('${build_dir}/python'))
     pytest_env.PrependENVPath('LD_LIBRARY_PATH',
                               pytest_env.subst('${build_dir}/src'))
     test_target = pytest_env.Command('#/.phony_test', targets,
                                      '${py_exec} -m pytest ${build_dir}/tests')
     main_env.Alias('test', test_target)
 
 else:
     # We still define a target here so that `scons test` still works
     dummy_command(main_env, 'test',
                   'Cannot run tests: pytest is not installed')