Page MenuHomec4science

site_init.py
No OneTemporary

File Metadata

Created
Thu, Mar 28, 22:48

site_init.py

# -*- coding: utf-8 -*-
#
# Copyright (©) 2016-2022 EPFL (École Polytechnique Fédérale de Lausanne),
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
# Copyright (©) 2020-2022 Lucas Frérot
#
# 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
from SCons.Script import Configure
from SCons.Errors import StopError
# ------------------------------------------------------------------------------
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(
env.subst('${py_exec}-config --extension-suffix').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['gray']
action = 'Copying'
elif 'Creating' in command:
color = colors['yellow']
action = 'Generating'
elif 'database' in command:
color = colors['yellow']
action = 'Generating'
elif 'pytest' in command:
color = colors['green']
action = 'Running tests'
target[0] = target[0].dir
elif 'pip' in command:
color = colors['blue']
if 'user' in command:
action = 'Symlinking'
target[0] = target[0].dir
elif 'prefix' in command:
action = 'Installing'
target[0] = env.subst(target[0].dir.path + ' to ${prefix}')
elif 'tar' in command:
color = colors['blue']
action = 'Archiving'
target[0] = '../' + target[0].path
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
output = bytes(e.output)
context.Log(output.decode() + '\n')
context.Result(result)
return result
# ------------------------------------------------------------------------------
def CheckCompilerFlag(context, flag):
"Check compiler provides flag"
context.Message('Checking compiler flag {}... '.format(
context.sconf.env.subst(flag)))
test_file = """
int main() {
return 0;
}
"""
env = context.sconf.env.Clone(CXXFLAGS=[flag],
LINKFLAGS=[flag])
context.sconf.env = env
result = context.TryLink(test_file, '.cpp')
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
# ------------------------------------------------------------------------------
def basic_checks(env):
custom_tests = {
'CheckCompilerFlag': CheckCompilerFlag,
}
conf = Configure(env, custom_tests=custom_tests)
if not conf.CheckCXX():
raise StopError('Could not find working C++ compiler')
for flag in env['CXXFLAGS']:
if not conf.CheckCompilerFlag(flag):
raise StopError(
env.subst('Compiler does not support flag "${CXXFLAGS}"'))
# flags are overwritten by CheckCompilerFlag
conf.env['CXXFLAGS'] = env['CXXFLAGS']
def check_type(cpp_type, stl_header):
if not conf.CheckType(
cpp_type,
'#include <{stl_header}>'.format(stl_header=stl_header),
'C++'
):
raise StopError(
'Standard type "{cpp_type}" is not available'
.format(cpp_type=cpp_type))
check_type(env['real_type'], 'cstdlib')
check_type(env['integer_type'], 'cstdlib')
check_type('std::multiplies<void>', 'functional')
check_type('std::unique_ptr<void>', 'memory')
conf.Finish()

Event Timeline