Learn more  » Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Bower components Debian packages RPM packages NuGet packages

alkaline-ml / numpy   python

Repository URL to install this package:

Version: 1.19.1 

/ distutils / fcompiler / __init__.py

"""numpy.distutils.fcompiler

Contains FCompiler, an abstract base class that defines the interface
for the numpy.distutils Fortran compiler abstraction model.

Terminology:

To be consistent, where the term 'executable' is used, it means the single
file, like 'gcc', that is executed, and should be a string. In contrast,
'command' means the entire command line, like ['gcc', '-c', 'file.c'], and
should be a list.

But note that FCompiler.executables is actually a dictionary of commands.

"""
__all__ = ['FCompiler', 'new_fcompiler', 'show_fcompilers',
           'dummy_fortran_file']

import os
import sys
import re

from numpy.compat import open_latin1

from distutils.sysconfig import get_python_lib
from distutils.fancy_getopt import FancyGetopt
from distutils.errors import DistutilsModuleError, \
     DistutilsExecError, CompileError, LinkError, DistutilsPlatformError
from distutils.util import split_quoted, strtobool

from numpy.distutils.ccompiler import CCompiler, gen_lib_options
from numpy.distutils import log
from numpy.distutils.misc_util import is_string, all_strings, is_sequence, \
    make_temp_file, get_shared_lib_extension
from numpy.distutils.exec_command import find_executable
from numpy.distutils import _shell_utils

from .environment import EnvironmentConfig

__metaclass__ = type

class CompilerNotFound(Exception):
    pass

def flaglist(s):
    if is_string(s):
        return split_quoted(s)
    else:
        return s

def str2bool(s):
    if is_string(s):
        return strtobool(s)
    return bool(s)

def is_sequence_of_strings(seq):
    return is_sequence(seq) and all_strings(seq)

class FCompiler(CCompiler):
    """Abstract base class to define the interface that must be implemented
    by real Fortran compiler classes.

    Methods that subclasses may redefine:

        update_executables(), find_executables(), get_version()
        get_flags(), get_flags_opt(), get_flags_arch(), get_flags_debug()
        get_flags_f77(), get_flags_opt_f77(), get_flags_arch_f77(),
        get_flags_debug_f77(), get_flags_f90(), get_flags_opt_f90(),
        get_flags_arch_f90(), get_flags_debug_f90(),
        get_flags_fix(), get_flags_linker_so()

    DON'T call these methods (except get_version) after
    constructing a compiler instance or inside any other method.
    All methods, except update_executables() and find_executables(),
    may call the get_version() method.

    After constructing a compiler instance, always call customize(dist=None)
    method that finalizes compiler construction and makes the following
    attributes available:
      compiler_f77
      compiler_f90
      compiler_fix
      linker_so
      archiver
      ranlib
      libraries
      library_dirs
    """

    # These are the environment variables and distutils keys used.
    # Each configuration description is
    # (<hook name>, <environment variable>, <key in distutils.cfg>, <convert>, <append>)
    # The hook names are handled by the self._environment_hook method.
    #  - names starting with 'self.' call methods in this class
    #  - names starting with 'exe.' return the key in the executables dict
    #  - names like 'flags.YYY' return self.get_flag_YYY()
    # convert is either None or a function to convert a string to the
    # appropriate type used.

    distutils_vars = EnvironmentConfig(
        distutils_section='config_fc',
        noopt = (None, None, 'noopt', str2bool, False),
        noarch = (None, None, 'noarch', str2bool, False),
        debug = (None, None, 'debug', str2bool, False),
        verbose = (None, None, 'verbose', str2bool, False),
    )

    command_vars = EnvironmentConfig(
        distutils_section='config_fc',
        compiler_f77 = ('exe.compiler_f77', 'F77', 'f77exec', None, False),
        compiler_f90 = ('exe.compiler_f90', 'F90', 'f90exec', None, False),
        compiler_fix = ('exe.compiler_fix', 'F90', 'f90exec', None, False),
        version_cmd = ('exe.version_cmd', None, None, None, False),
        linker_so = ('exe.linker_so', 'LDSHARED', 'ldshared', None, False),
        linker_exe = ('exe.linker_exe', 'LD', 'ld', None, False),
        archiver = (None, 'AR', 'ar', None, False),
        ranlib = (None, 'RANLIB', 'ranlib', None, False),
    )

    flag_vars = EnvironmentConfig(
        distutils_section='config_fc',
        f77 = ('flags.f77', 'F77FLAGS', 'f77flags', flaglist, True),
        f90 = ('flags.f90', 'F90FLAGS', 'f90flags', flaglist, True),
        free = ('flags.free', 'FREEFLAGS', 'freeflags', flaglist, True),
        fix = ('flags.fix', None, None, flaglist, False),
        opt = ('flags.opt', 'FOPT', 'opt', flaglist, True),
        opt_f77 = ('flags.opt_f77', None, None, flaglist, False),
        opt_f90 = ('flags.opt_f90', None, None, flaglist, False),
        arch = ('flags.arch', 'FARCH', 'arch', flaglist, False),
        arch_f77 = ('flags.arch_f77', None, None, flaglist, False),
        arch_f90 = ('flags.arch_f90', None, None, flaglist, False),
        debug = ('flags.debug', 'FDEBUG', 'fdebug', flaglist, True),
        debug_f77 = ('flags.debug_f77', None, None, flaglist, False),
        debug_f90 = ('flags.debug_f90', None, None, flaglist, False),
        flags = ('self.get_flags', 'FFLAGS', 'fflags', flaglist, True),
        linker_so = ('flags.linker_so', 'LDFLAGS', 'ldflags', flaglist, True),
        linker_exe = ('flags.linker_exe', 'LDFLAGS', 'ldflags', flaglist, True),
        ar = ('flags.ar', 'ARFLAGS', 'arflags', flaglist, True),
    )

    language_map = {'.f': 'f77',
                    '.for': 'f77',
                    '.F': 'f77',    # XXX: needs preprocessor
                    '.ftn': 'f77',
                    '.f77': 'f77',
                    '.f90': 'f90',
                    '.F90': 'f90',  # XXX: needs preprocessor
                    '.f95': 'f90',
                    }
    language_order = ['f90', 'f77']


    # These will be set by the subclass

    compiler_type = None
    compiler_aliases = ()
    version_pattern = None

    possible_executables = []
    executables = {
        'version_cmd': ["f77", "-v"],
        'compiler_f77': ["f77"],
        'compiler_f90': ["f90"],
        'compiler_fix': ["f90", "-fixed"],
        'linker_so': ["f90", "-shared"],
        'linker_exe': ["f90"],
        'archiver': ["ar", "-cr"],
        'ranlib': None,
        }

    # If compiler does not support compiling Fortran 90 then it can
    # suggest using another compiler. For example, gnu would suggest
    # gnu95 compiler type when there are F90 sources.
    suggested_f90_compiler = None

    compile_switch = "-c"
    object_switch = "-o "   # Ending space matters! It will be stripped
                            # but if it is missing then object_switch
                            # will be prefixed to object file name by
                            # string concatenation.
    library_switch = "-o "  # Ditto!

    # Switch to specify where module files are created and searched
    # for USE statement.  Normally it is a string and also here ending
    # space matters. See above.
    module_dir_switch = None

    # Switch to specify where module files are searched for USE statement.
    module_include_switch = '-I'

    pic_flags = []           # Flags to create position-independent code

    src_extensions = ['.for', '.ftn', '.f77', '.f', '.f90', '.f95', '.F', '.F90', '.FOR']
    obj_extension = ".o"

    shared_lib_extension = get_shared_lib_extension()
    static_lib_extension = ".a"  # or .lib
    static_lib_format = "lib%s%s" # or %s%s
    shared_lib_format = "%s%s"
    exe_extension = ""

    _exe_cache = {}

    _executable_keys = ['version_cmd', 'compiler_f77', 'compiler_f90',
                        'compiler_fix', 'linker_so', 'linker_exe', 'archiver',
                        'ranlib']

    # This will be set by new_fcompiler when called in
    # command/{build_ext.py, build_clib.py, config.py} files.
    c_compiler = None

    # extra_{f77,f90}_compile_args are set by build_ext.build_extension method
    extra_f77_compile_args = []
    extra_f90_compile_args = []

    def __init__(self, *args, **kw):
        CCompiler.__init__(self, *args, **kw)
        self.distutils_vars = self.distutils_vars.clone(self._environment_hook)
        self.command_vars = self.command_vars.clone(self._environment_hook)
        self.flag_vars = self.flag_vars.clone(self._environment_hook)
        self.executables = self.executables.copy()
        for e in self._executable_keys:
            if e not in self.executables:
                self.executables[e] = None

        # Some methods depend on .customize() being called first, so
        # this keeps track of whether that's happened yet.
        self._is_customised = False

    def __copy__(self):
        obj = self.__new__(self.__class__)
        obj.__dict__.update(self.__dict__)
        obj.distutils_vars = obj.distutils_vars.clone(obj._environment_hook)
        obj.command_vars = obj.command_vars.clone(obj._environment_hook)
        obj.flag_vars = obj.flag_vars.clone(obj._environment_hook)
        obj.executables = obj.executables.copy()
        return obj

    def copy(self):
        return self.__copy__()

    # Use properties for the attributes used by CCompiler. Setting them
    # as attributes from the self.executables dictionary is error-prone,
    # so we get them from there each time.
    def _command_property(key):
        def fget(self):
            assert self._is_customised
            return self.executables[key]
        return property(fget=fget)
    version_cmd = _command_property('version_cmd')
    compiler_f77 = _command_property('compiler_f77')
    compiler_f90 = _command_property('compiler_f90')
    compiler_fix = _command_property('compiler_fix')
    linker_so = _command_property('linker_so')
    linker_exe = _command_property('linker_exe')
    archiver = _command_property('archiver')
    ranlib = _command_property('ranlib')

    # Make our terminology consistent.
    def set_executable(self, key, value):
        self.set_command(key, value)

    def set_commands(self, **kw):
        for k, v in kw.items():
            self.set_command(k, v)

    def set_command(self, key, value):
        if not key in self._executable_keys:
            raise ValueError(
                "unknown executable '%s' for class %s" %
                (key, self.__class__.__name__))
        if is_string(value):
            value = split_quoted(value)
        assert value is None or is_sequence_of_strings(value[1:]), (key, value)
        self.executables[key] = value

    ######################################################################
    ## Methods that subclasses may redefine. But don't call these methods!
    ## They are private to FCompiler class and may return unexpected
    ## results if used elsewhere. So, you have been warned..

    def find_executables(self):
        """Go through the self.executables dictionary, and attempt to
        find and assign appropriate executables.

        Executable names are looked for in the environment (environment
        variables, the distutils.cfg, and command line), the 0th-element of
        the command list, and the self.possible_executables list.

        Also, if the 0th element is "<F77>" or "<F90>", the Fortran 77
        or the Fortran 90 compiler executable is used, unless overridden
        by an environment setting.

        Subclasses should call this if overridden.
        """
        assert self._is_customised
        exe_cache = self._exe_cache
        def cached_find_executable(exe):
            if exe in exe_cache:
                return exe_cache[exe]
            fc_exe = find_executable(exe)
            exe_cache[exe] = exe_cache[fc_exe] = fc_exe
            return fc_exe
        def verify_command_form(name, value):
            if value is not None and not is_sequence_of_strings(value):
                raise ValueError(
                    "%s value %r is invalid in class %s" %
                    (name, value, self.__class__.__name__))
        def set_exe(exe_key, f77=None, f90=None):
            cmd = self.executables.get(exe_key, None)
            if not cmd:
                return None
            # Note that we get cmd[0] here if the environment doesn't
            # have anything set
            exe_from_environ = getattr(self.command_vars, exe_key)
            if not exe_from_environ:
                possibles = [f90, f77] + self.possible_executables
            else:
                possibles = [exe_from_environ] + self.possible_executables

            seen = set()
            unique_possibles = []
            for e in possibles:
                if e == '<F77>':
                    e = f77
                elif e == '<F90>':
                    e = f90
                if not e or e in seen:
                    continue
                seen.add(e)
                unique_possibles.append(e)

            for exe in unique_possibles:
                fc_exe = cached_find_executable(exe)
                if fc_exe:
                    cmd[0] = fc_exe
                    return fc_exe
            self.set_command(exe_key, None)
            return None

        ctype = self.compiler_type
        f90 = set_exe('compiler_f90')
        if not f90:
            f77 = set_exe('compiler_f77')
            if f77:
Loading ...