Page MenuHomec4science

SConstruct
No OneTemporary

File Metadata

Created
Sun, Apr 28, 09:02

SConstruct

# -*- mode:python; coding: utf-8 -*-
# vim: set ft=python:
# @file
# @section LICENSE
#
# Copyright (©) 2016-19 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
from os.path import join, abspath
from version import write_info_file
from detect import FindFFTW, FindBoost, FindThrust, FindCuda, FindExpolit
# ------------------------------------------------------------------------------
EnsurePythonVersion(2, 7)
EnsureSConsVersion(2, 4)
# ------------------------------------------------------------------------------
tamaas_info = dict(
version="1.0.0",
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@epfl.ch',
copyright=u"Copyright (©) 2016-20 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)
# ------------------------------------------------------------------------------
# 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)
# 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'),
# 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),
# Strip binary of extra info
BoolVariable('strip_info', 'Strip binary of added information', 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(vars.GenerateHelpText(main_env))
# 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']
if main_env['should_configure']:
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] = ''
if not verbose:
main_env['SHCXXCOMSTR'] = \
u'{0}[Compiling ($SHCXX)] {1}$SOURCE'.format(colors['green'],
colors['end'])
main_env['SHLINKCOMSTR'] = \
u'{0}[Linking] {1}$TARGET'.format(colors['purple'],
colors['end'])
# 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":
main_env['CXX'] = "g++"
compiler_aliases = {
"c++": "g++",
"g++-7": "g++",
"g++-6": "g++",
"clang++-6.0": "clang++",
}
def cxx_alias(alias):
return compiler_aliases.get(alias, alias)
# OpenMP flags - compiler dependent
omp_flags = {
"g++": ["-fopenmp"],
"clang++": ["-fopenmp"],
"icpc": ["-qopenmp"]
}
cxx = cxx_alias(main_env['CXX'])
main_env.Append(CXXFLAGS='-std=c++14 -Wall -pedantic')
if main_env['backend'] == 'omp':
main_env.AppendUnique(CXXFLAGS=omp_flags[cxx])
main_env.AppendUnique(LINKFLAGS=omp_flags[cxx])
# Correct bug in clang?
if main_env['CXX'] == "clang++":
main_env.AppendUnique(LIBS="atomic")
elif main_env['backend'] == 'tbb':
main_env.AppendUnique(LIBS=['tbb'])
# We have to keep OpenMP for the legacy parts of Tamaas
# and for the number of threads given to fftw_omp
main_env.AppendUnique(CXXFLAGS=omp_flags[cxx])
main_env.AppendUnique(LINKFLAGS=omp_flags[cxx])
# Flags and options
if main_env['build_python']:
main_env.AppendUnique(CPPDEFINES=['USE_PYTHON'])
if main_env['strip_info']:
main_env.AppendUnique(CPPDEFINES=['STRIP_INFO'])
# Define the scalar types
main_env.AppendUnique(CPPDEFINES={'REAL_TYPE': main_env['real_type'],
'INT_TYPE': main_env['integer_type']})
if main_env['real_type'] == 'long double':
main_env.AppendUnique(CPPDEFINES=['LONG_PRECISION'])
# Adding compile flags defined in evironment
main_env.AppendUnique(CXXFLAGS=Split(os.getenv('CXXFLAGS', "")))
if build_type == 'debug':
main_env.AppendUnique(CPPDEFINES=['TAMAAS_DEBUG'])
# Compilation flags
cxxflags_dict = {
"debug": Split("-g -O0"),
"profiling": Split("-g -O3 -fno-omit-frame-pointer"),
"release": Split("-O3")
}
# Link flags for shared libs
shlinkflags_dict = {
"debug": Split(""),
"profiling": Split("-g -O3 -fno-omit-frame-pointer"),
"release": []
}
if main_env['sanitizer'] != 'none':
if main_env['backend'] == 'cuda':
print("Sanitizers with cuda are not yet supported!")
Exit(1)
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"
if main_env['should_configure']:
detect_dependencies(main_env)
# Writing information file
write_info_file("src/tamaas_info.cpp", main_env['build_type'])
# Saving the env file
main_env['gen_print'] = gen_print
env_file_env = main_env.Clone(
PRINT_CMD_LINE_FUNC=gen_print("Writing", "cyan", main_env),
SUBST_DICT={"@build@": abspath(build_dir)},
tools=['textfile'],
)
# Environment file content
env_content = """
export PYTHONPATH=$$PYTHONPATH:@build@/python
export LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:@build@/src
""".format(abspath(build_dir)).split('\n')
# Writing environment file
env_file_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')
# Building Tamaas extra components
for dir in ['python', 'tests']:
if main_env['build_{}'.format(dir)] and not main_env.GetOption('help'):
subdir(dir)
# Building API + Sphinx documentation if requested
if main_env['build_doc'] and not main_env.GetOption('help'):
main_env.Command('dummy_doc_target', '', 'make -C {}'.format(Dir('#/doc')))
main_env.Alias('install', ['install-lib', 'install-python'])
main_env.Alias('dev', 'install-python-local')

Event Timeline