diff --git a/site_scons/detect.py b/site_scons/detect.py index 11a032d..4ce3fae 100644 --- a/site_scons/detect.py +++ b/site_scons/detect.py @@ -1,243 +1,248 @@ # -*- 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 . from __future__ import print_function import SCons from os.path import join, abspath, exists, isdir from SCons.Script import Configure # ------------------------------------------------------------------------------ def _get_path(env, ext, module_var): path = "" if module_var in env and env[module_var] != "": root = abspath(env[module_var]) if not exists(root) or not isdir(root): raise RuntimeError("{} is set to a non-existing path '{}'".format( module_var, root)) path = join(root, ext) if not exists(path) or not isdir(path): raise RuntimeError("{} does not contain '{}' directory".format( module_var, ext)) return [path] # ------------------------------------------------------------------------------ def FindFFTW(env, components=[], precision='double', module_var='FFTW_ROOT'): """Find FFTW3 and set relevant environment variables""" if not env.get('should_configure', True): return fftw_vars = {} fftw_vars['CPPPATH'] = _get_path(env, 'include', module_var) fftw_vars['LIBPATH'] = _get_path(env, 'lib', module_var) + try: + fftw_vars['LIBPATH'] += _get_path(env, 'lib64', module_var) + except RuntimeError: + pass + # Setting up FFTW wishes = ['main'] + components fftw_name = "fftw3{}" # Components lib_names = {'main': fftw_name, 'thread': fftw_name + '_threads', 'omp': fftw_name + '_omp'} inc_names = ['fftw3.h'] # Checking list of wishes try: libs = [lib_names[i].format("") for i in wishes] except KeyError: raise SCons.Errors.StopError( 'Incompatible FFTW wishlist {0}'.format(wishes)) fftw_vars['LIBS'] = libs # Add long precision libraries if precision == 'long double': fftw_vars['LIBS'] += [lib_names[i].format("l") for i in wishes] conf_env = env.Clone(**fftw_vars) conf = Configure(conf_env) if not conf.CheckLibWithHeader(libs, inc_names, 'c++'): raise SCons.Errors.StopError( 'Failed to find libraries {0} or ' 'headers {1}.'.format( str([lib_names[i].format("") for i in wishes]), str(inc_names))) conf_env = conf.Finish() # Update modified variables env.AppendUnique(**fftw_vars) # ------------------------------------------------------------------------------ def FindBoost(env, headers=['boost/version.hpp'], module_var='BOOST_ROOT'): """Find Boost and set relevant environment variables""" if not env.get('should_configure', True): return boost_vars = {} boost_vars['CPPPATH'] = _get_path(env, 'include', module_var) conf_env = env.Clone(**boost_vars) conf = Configure(conf_env) if not conf.CheckCXXHeader(headers): raise SCons.Errors.StopError( 'Failed to find Boost headers {}'.format(headers)) conf_env = conf.Finish() # Update modified variables env.AppendUnique(**boost_vars) # ------------------------------------------------------------------------------ def FindThrust(env, backend='omp', module_var='THRUST_ROOT'): """Find Thrust and set relevant environment variables""" if not env.get('should_configure', True): return if backend not in ('omp', 'cuda', 'tbb'): raise SCons.Errors.StopError( 'Unknown thrust backend "{}"'.format(backend)) thrust_vars = {} thrust_vars['CPPPATH'] = _get_path(env, 'include', module_var) if "clang++" in env['CXX']: thrust_vars['CXXFLAGS'] = ["-Wno-unused-local-typedef"] thrust_vars['CPPDEFINES'] = [ "THRUST_DEVICE_SYSTEM=THRUST_DEVICE_SYSTEM_{}".format(backend.upper()) ] if backend == 'cuda': thrust_vars['CPPDEFINES'].append("USE_CUDA") conf_env = env.Clone(**thrust_vars) conf = Configure(conf_env) if not conf.CheckCXXHeader('thrust/version.h'): raise SCons.Errors.StopError( 'Failed to find Thrust') conf_env = conf.Finish() # Update modified variables env.AppendUnique(**thrust_vars) # ------------------------------------------------------------------------------ def FindPybind11(env, module_var='PYBIND11_ROOT'): """Detech Pybind11 and set appropriate build variables""" if not env.get('should_configure', True) \ or env.get("PYBIND11_FOUND", False): return pybind11_vars = {} clone = env.Clone(CPPPATH=[]) clone.ParseConfig('${py_exec}-config --includes') clone.AppendUnique(CPPPATH=['$PYBIND11_ROOT']) pybind11_vars['CPPPATH'] = clone['CPPPATH'] conf = Configure(clone) if not conf.CheckCXXHeader('pybind11/pybind11.h'): raise SCons.Errors.StopError( 'Failed to find pybind11 header\n' + "Run 'git submodule update --init --recursive " + "third-party/pybind11'") conf.Finish() pybind11_vars['PYBIND11_FOUND'] = True # Update variables env.AppendUnique(**pybind11_vars) # ------------------------------------------------------------------------------ def FindCuda(env, module_var="CUDA_ROOT"): """Detect cuda on clusters""" if not env.get('should_configure', True): return if 'CUDA_ROOT' in env: env['CUDA_TOOLKIT_PATH'] = _get_path(env, '', module_var) else: env['CUDA_TOOLKIT_PATH'] = '/opt/cuda' env['CUDA_COMPONENTS'] = ['cufft'] env['CUDA_ARCH_FLAG'] = '-arch=sm_60' colors = env['COLOR_DICT'] if not env['verbose']: env['NVCCCOMSTR'] = env['SHCXXCOMSTR'] env['SHLINKCOMSTR'] = \ u'{0}[Linking (cuda)] {1}$TARGET{2}'.format(colors['purple'], colors['blue'], colors['end']) env.AppendUnique(CXXFLAGS=[ "-expt-extended-lambda", # experimental lambda support "-expt-relaxed-constexpr", # experimental constexpr ]) if env['build_type'] == 'debug': env.AppendUnique(CXXFLAGS="-G") env.Tool('nvcc') # ------------------------------------------------------------------------------ def FindGTest(env): """A tool to configure GoogleTest""" if not env.get('should_configure', True): return conf = Configure(env) if not conf.CheckCXXHeader('gtest/gtest.h'): raise SCons.Errors.StopError( 'Failed to find GoogleTest header\n' + "Run 'git submodule update --init --recursive " + "third-party/googletest'") env = conf.Finish() # ------------------------------------------------------------------------------ def FindExpolit(env): """A tool to configure Expolit""" if not env.get('should_configure', True): return expolit_vars = {"CPPPATH": "#/third-party/expolit/include"} conf_env = env.Clone(**expolit_vars) conf = Configure(conf_env) if not conf.CheckCXXHeader('expolit/expolit'): raise SCons.Errors.StopError( 'Failed to find Expolit header\n' + "Run 'git submodule update --init " + "third-party/expolit'") conf_env = conf.Finish() env.AppendUnique(**expolit_vars)