Source code for openalea.sconsx.config

# -*- python -*-
#--------------------------------------------------------------------------------
#
#       OpenAlea.SConsX: SCons extension package for building platform
#                        independant packages.
#
#       Copyright 2006-2022 INRIA - CIRAD - INRAE
#
#       File author(s): Christophe Pradal <christophe.prada@cirad.fr>
#                       Pierre Barbier de Reuille <pierre.barbier@sophia.inria.fr>
#                       Samuel Dufour-Kowalski <samuel.dufour@sophia.inria.fr>
#
#       Distributed under the Cecill-C License.
#       See accompanying file LICENSE.txt or copy at
#           http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html
#
#       OpenAlea WebSite : http://openalea.gforge.inria.fr
#
#------------------------------------------------------------------------------
""" See OpenAlea WebSite / Packages / SConsX """
from __future__ import print_function

import os
import sys

from os.path import exists, join
pj = os.path.join

from SCons.Script import SConsignFile, Help, GetOption
try:
    from SCons.Script import VariantDir
except ImportError:
    from SCons.Script import BuildDir as VariantDir

from SCons.Variables import PathVariable
from SCons.Variables import BoolVariable
from SCons.Variables import EnumVariable
from SCons.Variables import Variables
from SCons.Util import Split, WhereIs
from SCons.Tool import Tool
from SCons.SConf import SConf
from SCons.Environment import Environment
from SCons.Builder import Builder
from SCons.Node.FS import Dir, File


__license__ = "Cecill-C"
__revision__ = "$Id$"

# Errors

[docs] class ToolNotFound(UserWarning): pass
[docs] class CircularDependency(Exception): pass
# Utilitaries
[docs] def import_tool(name, import_dir): """ Import a module based on its name from a list of directories. """ old_syspath = list(sys.path) #if tool_path not in sys.path: # sys.path.insert(0, tool_path) sys.path = import_dir + sys.path sconsx_tools = os.path.dirname(__file__) sys.path.insert(0, sconsx_tools) try: mod = __import__('sconsx_ext.'+name) print("import local definition of tool '"+name+"' at "+ repr(mod.__path__)) mod = getattr(mod, name) except ImportError: try: mod = __import__('tools.'+name) mod = getattr(mod, name) except ImportError: sys.path = old_syspath raise ToolNotFound(name) sys.path = old_syspath return mod
[docs] def exist(s, path): """ Test if the file s exist in the path """ files = os.listdir(path) for f in files: if f.find(s) != -1: return True return False
[docs] def getLocalPath(): """ Return the absolute path of this package """ return os.path.dirname(__file__)
#------------------------------------------------------------------------------ # Global Path settings #tool_path = os.path.join(getLocalPath() , 'tools') #sys.path = [tool_path] + sys.path #------------------------------------------------------------------------------ # Method to build bison and flex files for AMAPmod software
[docs] def BisonFlex(env, bison, flex, prefix): """ Smart autoscan function. """ LEXFLAGS = env.get("LEXFLAGS")[:] YACCFLAGS = env.get("YACCFLAGS")[:] if prefix : LEXFLAGS += ["-P" + prefix] YACCFLAGS += ["-p " + prefix] targets = [] bison_ext = ".hpp" if not env.get("BISON_HPP"): bison_ext = ".cpp.h" (bison_name, _ext) = os.path.splitext(bison) h = env.CXXFile(source=bison, target= [bison_name+".cpp", bison_name + bison_ext], LEXFLAGS=LEXFLAGS, YACCFLAGS=YACCFLAGS) targets.append(h[0]) (flex_name, _ext) = os.path.splitext(flex) cpp = env.CXXFile(source=flex, LEXFLAGS=LEXFLAGS, YACCFLAGS=YACCFLAGS) targets.append(cpp) return targets
#---------------------------------- # Platform class
[docs] class Platform(object): def __init__(self): self.name = "" self.sharedlibextension = ''
[docs] class Posix(Platform): def __init__(self): self.name = "posix" self.sharedlibextension = 'so'
[docs] class Linux(Posix): def __init__(self): self.name = "linux"
[docs] def distribution(self): import platform return platform.linux_distribution()[0].lower()
[docs] class Irix(Posix): def __init__(self): self.name = "irix"
[docs] class Cygwin(Posix): def __init__(self): self.name = "cygwin" self.sharedlibextension = 'dll'
[docs] class Darwin(Posix): def __init__(self): self.name = "darwin" self.sharedlibextension = 'dylib'
[docs] class Win32(Platform): def __init__(self): self.name = "win32" self.sharedlibextension = 'dll'
[docs] def GetPlatform(): """ Factory function returning the correct platform instance. """ osname = os.name.lower() pfname = sys.platform.lower() if osname == "posix" : if pfname.find("linux") >= 0 : return Linux() elif pfname.find("cygwin") >= 0 : return Cygwin() elif pfname.find("darwin") >= 0 : return Darwin() elif pfname.find("irix") >= 0 : return Irix() else: return Posix() elif osname == "nt" and pfname.startswith("win"): return Win32() else: raise ValueError("Unknown Platform (%s,%s)" % (osname, pfname))
# Create a static instance ... # (very pythonic way, isn't it?) platform = GetPlatform() #------------------------------------------------------------------------------ # User Configuration class default_tools = ['compiler', 'builddir', 'multicpu', 'install']
[docs] class Config(object): def __init__(self, tools=[], dir=[]): self.init_tools = default_tools + tools self.tools = [] self.tools_dict = {} self._walk = [] self.dir = [os.getcwd()] + dir self.custom_tests = { } for t in self.init_tools: self.add_tool(t)
[docs] def add_tool(self, tool): """ Add a specific tool and its dependencies recursively in the tool set. Check the circular dependencies. """ if not tool: return if tool in self.tools: return if tool in self._walk: raise CircularDependencies(tool) self._walk.append(tool) try: mod = import_tool(tool, self.dir) t = mod.create(self) except Exception as e: # Try to import EGG LIB print("trying egglib import", e) mod = import_tool("egglib", self.dir) t = mod.create(tool, self) self._walk.pop() self.tools.append(t)
[docs] def find_tool(self, toolname): """ Search for a specific tool """ for tool in self.tools: if tool.name == toolname: return tool
def __str__(self): return str([t.name for t in self.tools])
[docs] def Options(self, *args, **kwds): """ Add each tool options """ opts = Options(*args, **kwds) self.UpdateOptions(opts) return opts
[docs] def UpdateOptions(self, opts): for tool in self.tools: tool.option(opts)
[docs] def Configure(self, env): """ Configure each tools """ # Create Configure self.conf = SConf(env, self.custom_tests) for tool in self.tools: try: tool.configure(self,env) except: tool.configure(self) env = self.conf.Finish() return env
[docs] def Update(self, env): """ Update the environment for each tools. """ # Create Configure import traceback, sys import warnings for tool in self.tools: try: tool.update(env) except: traceback.print_exception(*sys.exc_info()) warnings.warn("Cannot update correctly tool "+repr(tool.name))
#------------------------------------------------------------------------------ # Specific OpenAlea facilities.
[docs] class ALEAConfig(Config): def __init__(self, package_name, *args, **kwds): Config.__init__(self, *args, **kwds) self.package_name = package_name
[docs] def Update(self, env): Config.Update(self, env) env["package_name"] = self.package_name
[docs] def ALEAEnvironment(conf, *args, **kwds): if 'options' in kwds: opts = kwds['options'] conf.UpdateOptions(opts) else: opts = conf.Options(*args, **kwds) env = Environment(options=opts) conf.Update(env) env.Prepend(CPPPATH='$build_includedir') env.Prepend(LIBPATH='$build_libdir') return env
[docs] def ALEASolution(options, tools=[], dir=[]): from copy import deepcopy SConsignFile() env_compiler_options = {} if isinstance(platform, Win32): # Checking for compiler info first compileroptions = deepcopy(options) compilerconf = Config([],dir) compilerconf.UpdateOptions(compileroptions) compilerenv = Environment() compileroptions.Update(compilerenv) compilerconf.Update(compilerenv) if compilerenv['compiler'] == 'msvc': if compilerenv['MSVC_VERSION'] != '': env_compiler_options['MSVC_VERSION'] = compilerenv['MSVC_VERSION'] env_compiler_options['TARGET_ARCH'] = compilerenv['TARGET_ARCH'] elif compilerenv['compiler'] == 'mingw': env_compiler_options['tools'] = ['mingw'] env_compiler_options['ENV'] = {'PATH': [find_executable_path_from_env('gcc.exe', strip_bin=False)],'TMP': os.environ['TMP']} conf = Config(tools, dir) conf.UpdateOptions(options) if len(env_compiler_options) > 0: print('Force environment with compiler options : '+str(env_compiler_options)) env = Environment(options=options, **env_compiler_options) else: env = Environment(options=options) options.Update(env) conf.Update(env) Help(options.GenerateHelpText(env)) prefix = env['build_prefix'] VariantDir(prefix, '.') env.Prepend(CPPPATH='$build_includedir') env.Prepend(LIBPATH='$build_libdir') # If scons is run in a conda environment, append paths if CONDA_ENV: PREFIX = CONDA_PREFIX env.Prepend(CPPPATH=pj(PREFIX, 'include')) env.Prepend(LIBPATH=pj(PREFIX, 'lib')) return env
from .util.lib_check import * from .util.env_check import * CONDA_ENV = is_conda() CONDA_PREFIX = conda_prefix() CONDA_LIBRARY_PREFIX = conda_library_prefix()