Page MenuHomec4science

SConstruct
No OneTemporary

File Metadata

Created
Tue, Apr 30, 20:24

SConstruct

# ------------------------------------------------------------------------------
# Imports
# ------------------------------------------------------------------------------
from __future__ import print_function
import os
from os.path import join, abspath, basename
from version import write_info_file
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Helper functions
# ------------------------------------------------------------------------------
def detect_fftw(env):
"""Detect fftw on clusters"""
fftw_include = ""
fftw_library = ""
# If FFTW is provided by module system (on clusters)
if 'FFTW_ROOT' in env['ENV']:
fftw_include = join(env['ENV']['FFTW_ROOT'], 'include')
fftw_library = join(env['ENV']['FFTW_ROOT'], 'lib')
# Setting up FFTW
env['FFTW_LIBRARY_WISH'] = ['main', 'omp']
env['FFTW_INCLUDE_DIR'] = fftw_include
env['FFTW_LIBRARY_DIR'] = fftw_library
env.Tool(fftw)
# ------------------------------------------------------------------------------
def detect_cuda(env):
"""Detect cuda on clusters"""
if 'CUDA_ROOT' in env['ENV']:
env['CUDA_TOOLKIT_PATH'] = env['ENV']['CUDA_ROOT']
else:
env['CUDA_TOOLKIT_PATH'] = '/opt/cuda'
env['CUDA_COMPONENTS'] = ['cufft']
env['CUDA_ARCH_FLAG'] = '-arch=sm_35'
colors = env['COLOR_DICT']
if not env['verbose']:
env['NVCCCOMSTR'] = u'{0}[Compiling (cuda)] {1}$SOURCE{2}'.format(colors['green'],
colors['blue'],
colors['end'])
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
env.AppendUnique(CXXFLAGS="-expt-relaxed-constexpr") # experimental lambda support
if env['build_type'] == 'debug':
env.AppendUnique(CXXFLAGS="-G")
env.Tool('nvcc')
# ------------------------------------------------------------------------------
def detect_boost(env):
"""Detect boost on clusters"""
if 'BOOST_ROOT' in env['ENV']:
env['BOOST_INCLUDE_DIR'] = join(env['ENV']['BOOST_ROOT'], 'include')
env.Tool(boost)
# ------------------------------------------------------------------------------
def detect_thrust(env):
"""Detect cuda on clusters"""
if 'CUDA_ROOT' in env['ENV']:
env['THRUST_INCLUDE_DIR'] = join(env['ENV']['CUDA_ROOT'], 'include')
else:
env['THRUST_INCLUDE_DIR'] = '/opt/cuda/include'
if basename(env['CXX']) == "clang++":
env.AppendUnique(CXXFLAGS=["-Wno-unused-local-typedef"])
env.Tool(thrust)
# ------------------------------------------------------------------------------
def gen_print(action_string, color_string, env):
"""Generic function for creating pretty compile output"""
if env['verbose']:
return None
def print_fun(command, target, source, env):
colors = env['COLOR_DICT']
print("{}[{}] {}{}{}".format(colors[color_string],
action_string,
colors['blue'],
target[0],
colors['end']))
return print_fun
# ------------------------------------------------------------------------------
# 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'
}
# Inherit all environment variables (for CXX detection, etc.)
main_env = Environment(ENV=os.environ)
main_env['COLOR_DICT'] = colors
# Compiler detection
compiler_default = 'g++'
if 'CXX' in os.environ:
compiler_default = os.environ['CXX']
# Build variables
vars = Variables('build-setup.conf')
vars.Add(EnumVariable('build_type', 'Build type', 'release',
allowed_values=('release', 'profiling', 'debug'),
ignorecase=2))
vars.Add(EnumVariable('backend', 'Thrust backend', 'omp',
allowed_values=('omp', 'cuda'),
ignorecase=2))
vars.Add(EnumVariable('sanitizer', 'Sanitizer type', 'none',
allowed_values=('none', 'memory', 'leaks'),
ignorecase=2))
vars.Add('prefix', 'Prefix where to install', '/usr/local')
vars.Add('CXX', 'Compiler', compiler_default)
vars.Add('py_exec', 'Python executable', 'python')
vars.Add(BoolVariable('verbose', 'Activate verbosity', False))
vars.Add(BoolVariable('build_doc', 'Build documentation', False))
vars.Add(BoolVariable('color', 'Color the non-verbose compilation output', False))
vars.Update(main_env)
Help(vars.GenerateHelpText(main_env))
# Save all options, not just those that differ from default
with open('build-setup.conf', 'w') as setup:
for key in vars.keys():
setup.write("{} = '{}'\n".format(key, main_env[key]))
build_type = main_env['build_type']
build_dir = 'build-' + main_env['build_type']
print("Building in " + build_dir)
verbose = main_env['verbose']
# Remove colors if not set
if not main_env['color']:
for key in colors:
colors[key] = ''
# Setting object suffix
main_env['SHOBJSUFFIX'] = '.o'
if not verbose:
main_env['SHCXXCOMSTR'] = u'{0}[Compiling] {1}$SOURCE'.format(colors['green'],
colors['end'])
main_env['SHLINKCOMSTR'] = u'{0}[Linking] {1}$TARGET'.format(colors['purple'],
colors['end'])
main_env['SWIGCOMSTR'] = u'{0}[Swig] {1}$SOURCE'.format(colors['yellow'],
colors['end'])
# Include paths
main_env.AppendUnique(CPPPATH=['#/src',
'#/src/core',
'#/src/bem',
'#/src/surface',
'#/src/python',
'#/src/percolation',
'#/src/model',
'#/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":
main_env['CXX'] = "g++"
# OpenMP flags - compiler dependent
omp_libs = {
"g++": ["gomp"],
"clang++": [],
"icpc": []
}
omp_flags = {
"g++": ["-fopenmp"],
"clang++": ["-fopenmp=libomp"],
"icpc": ["-qopenmp"]
}
omp_lib = omp_libs[main_env['CXX']]
omp_flag = omp_flags[main_env['CXX']]
main_env.AppendUnique(LIBS=omp_lib)
main_env.AppendUnique(LINKFLAGS=omp_flag)
# Flags and options
main_env.AppendUnique(CXXFLAGS=['-std=c++11',
'-Wall',
omp_flag])
if main_env['backend'] == 'omp':
main_env.AppendUnique(CPPDEFINES=["THRUST_DEVICE_SYSTEM=THRUST_DEVICE_SYSTEM_OMP"])
elif main_env['backend'] == 'cuda':
main_env.AppendUnique(CPPDEFINES=["THRUST_DEVICE_SYSTEM=THRUST_DEVICE_SYSTEM_CUDA"])
main_env.AppendUnique(CPPDEFINES=['USE_CUDA'])
# Adding compile flags defined in evironment
if 'CXXFLAGS' in os.environ:
main_env.AppendUnique(CXXFLAGS=Split(os.environ['CXXFLAGS']))
if build_type == 'debug':
main_env.AppendUnique(CPPDEFINES=['TAMAAS_DEBUG'])
# Compilation flags
cxxflags_dict = {
"debug": Split("-g -O0"),
"profiling": Split("-g -pg -O2 -fno-omit-frame-pointer"),
"release": Split("-O3")
}
# Link flags for shared libs
shlinkflags_dict = {
"debug": Split(""),
"profiling": ['-pg'],
"release": []
}
if main_env['sanitizer'] != 'none':
cxxflags_dict[build_type].append('-fsanitize={}'.format(main_env['sanitizer']))
shlinkflags_dict[build_type].append('-fsanitize={}'.format(main_env['sanitizer']))
main_env.AppendUnique(CXXFLAGS=cxxflags_dict[build_type])
main_env.AppendUnique(SHLINKFLAGS=shlinkflags_dict[build_type])
main_env.AppendUnique(LINKFLAGS=shlinkflags_dict[build_type])
main_env['LIBPATH'] = [abspath(join(build_dir, 'src'))]
main_env['RPATH'] = "$LIBPATH"
detect_fftw(main_env)
detect_boost(main_env)
detect_thrust(main_env)
# Activate cuda if needed
if main_env['backend'] == 'cuda':
detect_cuda(main_env)
# Writing information file
write_info_file("src/tamaas_info.cpp")
# Saving the env file
env_content = """export PYTHONPATH=$PYTHONPATH:{0}/python
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:{0}/src
"""
def write_env_file(target, source, env):
"""Builder to write content to file"""
with open(str(target[0]), 'w') as env_file:
env_file.write(env_content.format(abspath(build_dir)))
main_env['gen_print'] = gen_print
env_file_env = main_env.Clone(PRINT_CMD_LINE_FUNC=gen_print("Writing", "cyan", main_env))
# Need to have a command and manage tamaas_environement.sh as target because
# the build directory does not always exist
env_file_env.Command(join(build_dir, 'tamaas_environement.sh'), None, write_env_file)
Export('main_env')
# Building subdirs
def subdir(dir):
return SConscript(join(dir, 'SConscript'),
variant_dir=join(build_dir, dir),
duplicate=True)
subdirs2target = {'src': "tamaas",
'python': "wrapper",
'tests': "tests"}
subdirs2target = {'src': "tamaas",
'python': "wrapper",
'tests': "tests"}
for dir in subdirs2target:
target = subdir(dir)
main_env.Alias(subdirs2target[dir], target)
# Building documentation
if main_env['build_doc']:
subdir('doc')

Event Timeline