[Numpy-svn] r3824 - in trunk/numpy/distutils: . fcompiler

numpy-svn at scipy.org numpy-svn at scipy.org
Fri May 25 07:41:27 EDT 2007


Author: cookedm
Date: 2007-05-25 06:41:16 -0500 (Fri, 25 May 2007)
New Revision: 3824

Added:
   trunk/numpy/distutils/environment.py
Modified:
   trunk/numpy/distutils/fcompiler/__init__.py
   trunk/numpy/distutils/fcompiler/absoft.py
   trunk/numpy/distutils/fcompiler/compaq.py
   trunk/numpy/distutils/fcompiler/g95.py
   trunk/numpy/distutils/fcompiler/gnu.py
   trunk/numpy/distutils/fcompiler/hpux.py
   trunk/numpy/distutils/fcompiler/ibm.py
   trunk/numpy/distutils/fcompiler/intel.py
   trunk/numpy/distutils/fcompiler/lahey.py
   trunk/numpy/distutils/fcompiler/mips.py
   trunk/numpy/distutils/fcompiler/nag.py
   trunk/numpy/distutils/fcompiler/none.py
   trunk/numpy/distutils/fcompiler/pg.py
   trunk/numpy/distutils/fcompiler/sun.py
   trunk/numpy/distutils/fcompiler/vast.py
   trunk/numpy/distutils/interactive.py
Log:
merge from distutils-revamp branch (step 2)
- fcompiler changes. All flags, executables, etc., should be overridable
  by the user with config_fc (either command line or setup.cfg) or by
  environment variables


Added: trunk/numpy/distutils/environment.py
===================================================================
--- trunk/numpy/distutils/environment.py	2007-05-25 11:20:02 UTC (rev 3823)
+++ trunk/numpy/distutils/environment.py	2007-05-25 11:41:16 UTC (rev 3824)
@@ -0,0 +1,49 @@
+import os
+from distutils.dist import Distribution
+
+__metaclass__ = type
+
+class EnvironmentConfig:
+    def __init__(self, distutils_section='DEFAULT', **kw):
+        self._distutils_section = distutils_section
+        self._conf_keys = kw
+        self._conf = None
+        self._hook_handler = None
+
+    def __getattr__(self, name):
+        try:
+            conf_desc = self._conf_keys[name]
+        except KeyError:
+            raise AttributeError(name)
+        return self._get_var(name, conf_desc)
+
+    def get(self, name, default=None):
+        try:
+            conf_desc = self._conf_keys[name]
+        except KeyError:
+            return default
+        var = self._get_var(name, conf_desc)
+        if var is None:
+            var = default
+        return var
+
+    def _get_var(self, name, conf_desc):
+        hook, envvar, confvar = conf_desc
+        var = self._hook_handler(name, hook)
+        if envvar is not None:
+            var = os.environ.get(envvar, var)
+        if confvar is not None and self._conf:
+            var = self._conf.get(confvar, (None, var))[1]
+        return var
+
+    def clone(self, hook_handler):
+        ec = self.__class__(distutils_section=self._distutils_section,
+                            **self._conf_keys)
+        ec._hook_handler = hook_handler
+        return ec
+
+    def use_distribution(self, dist):
+        if isinstance(dist, Distribution):
+            self._conf = dist.get_option_dict(self._distutils_section)
+        else:
+            self._conf = dist

Modified: trunk/numpy/distutils/fcompiler/__init__.py
===================================================================
--- trunk/numpy/distutils/fcompiler/__init__.py	2007-05-25 11:20:02 UTC (rev 3823)
+++ trunk/numpy/distutils/fcompiler/__init__.py	2007-05-25 11:41:16 UTC (rev 3824)
@@ -10,6 +10,12 @@
 import os
 import sys
 import re
+import new
+try:
+    set
+except NameError:
+    from sets import Set as set
+
 from distutils.sysconfig import get_config_var, get_python_lib
 from distutils.fancy_getopt import FancyGetopt
 from distutils.errors import DistutilsModuleError,DistutilsArgError,\
@@ -18,12 +24,18 @@
 
 from numpy.distutils.ccompiler import CCompiler, gen_lib_options
 from numpy.distutils import log
-from numpy.distutils.command.config_compiler import config_fc
 from numpy.distutils.misc_util import is_string, is_sequence
+from numpy.distutils.environment import EnvironmentConfig
+from numpy.distutils.exec_command import find_executable
 from distutils.spawn import _nt_quote_args
 
+__metaclass__ = type
+
+class CompilerNotFound(Exception):
+    pass
+
 class FCompiler(CCompiler):
-    """ Abstract base class to define the interface that must be implemented
+    """Abstract base class to define the interface that must be implemented
     by real Fortran compiler classes.
 
     Methods that subclasses may redefine:
@@ -38,7 +50,7 @@
     DON'T call these methods (except get_version) after
     constructing a compiler instance or inside any other method.
     All methods, except get_version_cmd() and get_flags_version(), may
-    call get_version() method.
+    call the get_version() method.
 
     After constructing a compiler instance, always call customize(dist=None)
     method that finalizes compiler construction and makes the following
@@ -53,7 +65,55 @@
       library_dirs
     """
 
+    # These are the environment variables and distutils keys used.
+    # Each configuration descripition is
+    # (<hook name>, <environment variable>, <key in distutils.cfg>)
+    # 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()
 
+    distutils_vars = EnvironmentConfig(
+        noopt = (None, None, 'noopt'),
+        noarch = (None, None, 'noarch'),
+        debug = (None, None, 'debug'),
+        verbose = (None, None, 'verbose'),
+    )
+
+    command_vars = EnvironmentConfig(
+        distutils_section='config_fc',
+        compiler_f77 = ('exe.compiler_f77', 'F77', 'f77exec'),
+        compiler_f90 = ('exe.compiler_f90', 'F90', 'f90exec'),
+        compiler_fix = ('exe.compiler_fix', 'F90', 'f90exec'),
+        version_cmd = ('self.get_version_cmd', None, None),
+        linker_so = ('self.get_linker_so', 'LDSHARED', 'ldshared'),
+        linker_exe = ('self.get_linker_exe', 'LD', 'ld'),
+        archiver = (None, 'AR', 'ar'),
+        ranlib = (None, 'RANLIB', 'ranlib'),
+    )
+
+    flag_vars = EnvironmentConfig(
+        distutils_section='config_fc',
+        version = ('flags.version', None, None),
+        f77 = ('flags.f77', 'F77FLAGS', 'f77flags'),
+        f90 = ('flags.f90', 'F90FLAGS', 'f90flags'),
+        free = ('flags.free', 'FREEFLAGS', 'freeflags'),
+        fix = ('flags.fix', None, None),
+        opt = ('flags.opt', 'FOPT', 'opt'),
+        opt_f77 = ('flags.opt_f77', None, None),
+        opt_f90 = ('flags.opt_f90', None, None),
+        arch = ('flags.arch', 'FARCH', 'arch'),
+        arch_f77 = ('flags.arch_f77', None, None),
+        arch_f90 = ('flags.arch_f90', None, None),
+        debug = ('flags.debug', 'FDEBUG', None, None),
+        debug_f77 = ('flags.debug_f77', None, None),
+        debug_f90 = ('flags.debug_f90', None, None),
+        flags = ('self.get_flags', 'FFLAGS', 'fflags'),
+        linker_so = ('flags.linker_so', 'LDFLAGS', 'ldflags'),
+        linker_exe = ('flags.linker_exe', 'LDFLAGS', 'ldflags'),
+        ar = ('flags.ar', 'ARFLAGS', 'arflags'),
+    )
+
     language_map = {'.f':'f77',
                     '.for':'f77',
                     '.F':'f77',    # XXX: needs preprocessor
@@ -67,14 +127,15 @@
 
     version_pattern = None
 
+    possible_executables = []
     executables = {
-        'version_cmd'  : ["f77","-v"],
+        'version_cmd'  : ["f77", "-v"],
         'compiler_f77' : ["f77"],
         'compiler_f90' : ["f90"],
-        'compiler_fix' : ["f90","-fixed"],
-        'linker_so'    : ["f90","-shared"],
+        'compiler_fix' : ["f90", "-fixed"],
+        'linker_so'    : ["f90", "-shared"],
         'linker_exe'   : ["f90"],
-        'archiver'     : ["ar","-cr"],
+        'archiver'     : ["ar", "-cr"],
         'ranlib'       : None,
         }
 
@@ -103,6 +164,26 @@
     shared_lib_format = "%s%s"
     exe_extension = ""
 
+    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 ['version_cmd', 'compiler_f77', 'compiler_f90',
+                  'compiler_fix', 'linker_so', 'linker_exe', 'archiver',
+                  'ranlib']:
+            if e not in self.executables:
+                self.executables[e] = None
+
+    def __copy__(self):
+        obj = new.instance(self.__class__, 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
+
     # 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.
@@ -114,12 +195,72 @@
     ## results if used elsewhere. So, you have been warned..
 
     def find_executables(self):
-        """Modify self.executables to hold found executables, instead of
-        searching for them at class creation time."""
-        pass
+        """Go through the self.executables dictionary, and attempt to
+        find and assign appropiate 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.
+        """
+        exe_cache = {}
+        def cached_find_executable(exe):
+            if exe in exe_cache:
+                return exe_cache[exe]
+            fc_exe = find_executable(exe)
+            exe_cache[exe] = fc_exe
+            return fc_exe
+        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
+            return None
+
+        f90 = set_exe('compiler_f90')
+        if not f90:
+            raise CompilerNotFound('f90')
+        f77 = set_exe('compiler_f77', f90=f90)
+        if not f77:
+            raise CompilerNotFound('f90')
+        set_exe('compiler_fix', f90=f90)
+
+        set_exe('linker_so', f77=f77, f90=f90)
+        set_exe('linker_exe', f77=f77, f90=f90)
+        set_exe('version_cmd', f77=f77, f90=f90)
+
+        set_exe('archiver')
+        set_exe('ranlib')
+
     def get_version_cmd(self):
-        """ Compiler command to print out version information. """
+        """Compiler command to print out version information."""
         f77 = self.executables.get('compiler_f77')
         if f77 is not None:
             f77 = f77[0]
@@ -137,8 +278,8 @@
         return cmd
 
     def get_linker_so(self):
-        """ Linker command to build shared libraries. """
-        f77 = self.executables['compiler_f77']
+        """Linker command to build shared libraries."""
+        f77 = self.executables.get('compiler_f77')
         if f77 is not None:
             f77 = f77[0]
         ln = self.executables.get('linker_so')
@@ -155,8 +296,8 @@
         return ln
 
     def get_linker_exe(self):
-        """ Linker command to build shared libraries. """
-        f77 = self.executables['compiler_f77']
+        """Linker command to build shared libraries."""
+        f77 = self.executables.get('compiler_f77')
         if f77 is not None:
             f77 = f77[0]
         ln = self.executables.get('linker_exe')
@@ -173,54 +314,47 @@
         return ln
 
     def get_flags(self):
-        """ List of flags common to all compiler types. """
+        """List of flags common to all compiler types."""
         return [] + self.pic_flags
+
+    def _get_executable_flags(self, key):
+        cmd = self.executables.get(key, None)
+        if cmd is None:
+            return []
+        return cmd[1:]
+
     def get_flags_version(self):
-        """ List of compiler flags to print out version information. """
-        if self.executables.get('version_cmd'):
-            return self.executables['version_cmd'][1:]
-        return []
+        """List of compiler flags to print out version information."""
+        return self._get_executable_flags('version_cmd')
     def get_flags_f77(self):
-        """ List of Fortran 77 specific flags. """
-        if self.executables.get('compiler_f77'):
-            return self.executables['compiler_f77'][1:]
-        return []
+        """List of Fortran 77 specific flags."""
+        return self._get_executable_flags('compiler_f77')
     def get_flags_f90(self):
-        """ List of Fortran 90 specific flags. """
-        if self.executables.get('compiler_f90'):
-            return self.executables['compiler_f90'][1:]
-        return []
+        """List of Fortran 90 specific flags."""
+        return self._get_executable_flags('compiler_f90')
     def get_flags_free(self):
-        """ List of Fortran 90 free format specific flags. """
+        """List of Fortran 90 free format specific flags."""
         return []
     def get_flags_fix(self):
-        """ List of Fortran 90 fixed format specific flags. """
-        if self.executables.get('compiler_fix'):
-            return self.executables['compiler_fix'][1:]
-        return []
+        """List of Fortran 90 fixed format specific flags."""
+        return self._get_executable_flags('compiler_fix')
     def get_flags_linker_so(self):
-        """ List of linker flags to build a shared library. """
-        if self.executables.get('linker_so'):
-            return self.executables['linker_so'][1:]
-        return []
+        """List of linker flags to build a shared library."""
+        return self._get_executable_flags('linker_so')
     def get_flags_linker_exe(self):
-        """ List of linker flags to build an executable. """
-        if self.executables.get('linker_exe'):
-            return self.executables['linker_exe'][1:]
-        return []
+        """List of linker flags to build an executable."""
+        return self._get_executable_flags('linker_exe')
     def get_flags_ar(self):
-        """ List of archiver flags. """
-        if self.executables.get('archiver'):
-            return self.executables['archiver'][1:]
-        return []
+        """List of archiver flags. """
+        return self._get_executable_flags('archiver')
     def get_flags_opt(self):
-        """ List of architecture independent compiler flags. """
+        """List of architecture independent compiler flags."""
         return []
     def get_flags_arch(self):
-        """ List of architecture dependent compiler flags. """
+        """List of architecture dependent compiler flags."""
         return []
     def get_flags_debug(self):
-        """ List of compiler flags to compile with debugging information. """
+        """List of compiler flags to compile with debugging information."""
         return []
 
     get_flags_opt_f77 = get_flags_opt_f90 = get_flags_opt
@@ -228,18 +362,18 @@
     get_flags_debug_f77 = get_flags_debug_f90 = get_flags_debug
 
     def get_libraries(self):
-        """ List of compiler libraries. """
+        """List of compiler libraries."""
         return self.libraries[:]
     def get_library_dirs(self):
-        """ List of compiler library directories. """
+        """List of compiler library directories."""
         return self.library_dirs[:]
 
     ############################################################
 
     ## Public methods:
 
-    def customize(self, dist=None):
-        """ Customize Fortran compiler.
+    def customize(self, dist):
+        """Customize Fortran compiler.
 
         This method gets Fortran compiler specific information from
         (i) class definition, (ii) environment, (iii) distutils config
@@ -250,88 +384,71 @@
         instance is needed for (iii) and (iv).
         """
         log.info('customize %s' % (self.__class__.__name__))
-        from distutils.dist import Distribution
-        if dist is None:
-            # These hooks are for testing only!
-            dist = Distribution()
-            dist.script_name = os.path.basename(sys.argv[0])
-            dist.script_args = ['config_fc'] + sys.argv[1:]
-            dist.cmdclass['config_fc'] = config_fc
-            dist.parse_config_files()
-            dist.parse_command_line()
-        if isinstance(dist,Distribution):
-            conf = dist.get_option_dict('config_fc')
-        else:
-            assert isinstance(dist,dict)
-            conf = dist
-        noopt = conf.get('noopt',[None,0])[1]
+        self.distutils_vars.use_distribution(dist)
+        self.command_vars.use_distribution(dist)
+        self.flag_vars.use_distribution(dist)
+
+        self.find_executables()
+
+        noopt = self.distutils_vars.get('noopt', False)
         if 0: # change to `if 1:` when making release.
             # Don't use architecture dependent compiler flags:
-            noarch = 1
+            noarch = True
         else:
-            noarch = conf.get('noarch',[None,noopt])[1]
-        debug = conf.get('debug',[None,0])[1]
+            noarch = self.distutils_vars.get('noarch', noopt)
+        debug = self.distutils_vars.get('debug', False)
 
-        self.find_executables()
+        f77 = self.command_vars.compiler_f77
+        f90 = self.command_vars.compiler_f90
 
-        f77 = self.__get_cmd('compiler_f77','F77',(conf,'f77exec'))
-        f90 = self.__get_cmd('compiler_f90','F90',(conf,'f90exec'))
-        # Temporarily setting f77,f90 compilers so that
-        # version_cmd can use their executables.
-        if f77:
-            self.set_executables(compiler_f77=[f77])
-        if f90:
-            self.set_executables(compiler_f90=[f90])
-
         # Must set version_cmd before others as self.get_flags*
         # methods may call self.get_version.
-        vers_cmd = self.__get_cmd(self.get_version_cmd)
+        vers_cmd = self.command_vars.version_cmd
         if vers_cmd:
-            vflags = self.__get_flags(self.get_flags_version)
+            vflags = self.flag_vars.version
             self.set_executables(version_cmd=[vers_cmd]+vflags)
 
+        f77flags = []
+        f90flags = []
+        freeflags = []
+        fixflags = []
+
         if f77:
-            f77flags = self.__get_flags(self.get_flags_f77,'F77FLAGS',
-                                   (conf,'f77flags'))
+            f77flags = self.flag_vars.f77
         if f90:
-            f90flags = self.__get_flags(self.get_flags_f90,'F90FLAGS',
-                                       (conf,'f90flags'))
-            freeflags = self.__get_flags(self.get_flags_free,'FREEFLAGS',
-                                         (conf,'freeflags'))
+            f90flags = self.flag_vars.f90
+            freeflags = self.flag_vars.free
         # XXX Assuming that free format is default for f90 compiler.
-        fix = self.__get_cmd('compiler_fix','F90',(conf,'f90exec'))
+        fix = self.command_vars.compiler_fix
         if fix:
-            fixflags = self.__get_flags(self.get_flags_fix) + f90flags
+            fixflags = self.flag_vars.fix + f90flags
 
-        oflags,aflags,dflags = [],[],[]
+        oflags, aflags, dflags = [], [], []
+        def to_list(flags):
+            if is_string(flags):
+                return [flags]
+            return flags
+        # examine get_flags_<tag>_<compiler> for extra flags
+        # only add them if the method is different from get_flags_<tag>
+        def get_flags(tag, flags):
+            # note that self.flag_vars.<tag> calls self.get_flags_<tag>()
+            flags.extend(to_list(getattr(self.flag_vars, tag)))
+            this_get = getattr(self, 'get_flags_' + tag)
+            for name, c, flagvar in [('f77', f77, f77flags),
+                                     ('f90', f90, f90flags),
+                                     ('f90', fix, fixflags)]:
+                t = '%s_%s' % (tag, name)
+                if c and this_get is not getattr(self, 'get_flags_' + t):
+                    flagvar.extend(to_list(getattr(self.flag_vars, t)))
+            return oflags
         if not noopt:
-            oflags = self.__get_flags(self.get_flags_opt,'FOPT',(conf,'opt'))
-            if f77 and self.get_flags_opt is not self.get_flags_opt_f77:
-                f77flags += self.__get_flags(self.get_flags_opt_f77)
-            if f90 and self.get_flags_opt is not self.get_flags_opt_f90:
-                f90flags += self.__get_flags(self.get_flags_opt_f90)
-            if fix and self.get_flags_opt is not self.get_flags_opt_f90:
-                fixflags += self.__get_flags(self.get_flags_opt_f90)
+            get_flags('opt', oflags)
             if not noarch:
-                aflags = self.__get_flags(self.get_flags_arch,'FARCH',
-                                          (conf,'arch'))
-                if f77 and self.get_flags_arch is not self.get_flags_arch_f77:
-                    f77flags += self.__get_flags(self.get_flags_arch_f77)
-                if f90 and self.get_flags_arch is not self.get_flags_arch_f90:
-                    f90flags += self.__get_flags(self.get_flags_arch_f90)
-                if fix and self.get_flags_arch is not self.get_flags_arch_f90:
-                    fixflags += self.__get_flags(self.get_flags_arch_f90)
+                get_flags('arch', aflags)
         if debug:
-            dflags = self.__get_flags(self.get_flags_debug,'FDEBUG')
-            if f77  and self.get_flags_debug is not self.get_flags_debug_f77:
-                f77flags += self.__get_flags(self.get_flags_debug_f77)
-            if f90  and self.get_flags_debug is not self.get_flags_debug_f90:
-                f90flags += self.__get_flags(self.get_flags_debug_f90)
-            if fix and self.get_flags_debug is not self.get_flags_debug_f90:
-                fixflags += self.__get_flags(self.get_flags_debug_f90)
+            get_flags('debug', dflags)
 
-        fflags = self.__get_flags(self.get_flags,'FFLAGS') \
-                 + dflags + oflags + aflags
+        fflags = to_list(self.flag_vars.flags) + dflags + oflags + aflags
 
         if f77:
             self.set_executables(compiler_f77=[f77]+f77flags+fflags)
@@ -339,10 +456,11 @@
             self.set_executables(compiler_f90=[f90]+freeflags+f90flags+fflags)
         if fix:
             self.set_executables(compiler_fix=[fix]+fixflags+fflags)
+
         #XXX: Do we need LDSHARED->SOSHARED, LDFLAGS->SOFLAGS
-        linker_so = self.__get_cmd(self.get_linker_so,'LDSHARED')
+        linker_so = self.command_vars.linker_so
         if linker_so:
-            linker_so_flags = self.__get_flags(self.get_flags_linker_so,'LDFLAGS')
+            linker_so_flags = to_list(self.flag_vars.linker_so)
             if sys.platform.startswith('aix'):
                 python_lib = get_python_lib(standard_lib=1)
                 ld_so_aix = os.path.join(python_lib, 'config', 'ld_so_aix')
@@ -352,37 +470,32 @@
                 linker_so = [linker_so]
             self.set_executables(linker_so=linker_so+linker_so_flags)
 
-        linker_exe = self.__get_cmd(self.get_linker_exe,'LD')
+        linker_exe = self.command_vars.linker_exe
         if linker_exe:
-            linker_exe_flags = self.__get_flags(self.get_flags_linker_exe,'LDFLAGS')
+            linker_exe_flags = to_list(self.flag_vars.linker_exe)
             self.set_executables(linker_exe=[linker_exe]+linker_exe_flags)
-        ar = self.__get_cmd('archiver','AR')
+
+        ar = self.command_vars.archiver
         if ar:
-            arflags = self.__get_flags(self.get_flags_ar,'ARFLAGS')
+            arflags = to_list(self.flag_vars.ar)
             self.set_executables(archiver=[ar]+arflags)
 
-        ranlib = self.__get_cmd('ranlib','RANLIB')
+        ranlib = self.command_vars.ranlib
         if ranlib:
             self.set_executables(ranlib=[ranlib])
 
         self.set_library_dirs(self.get_library_dirs())
         self.set_libraries(self.get_libraries())
 
-
-        verbose = conf.get('verbose',[None,0])[1]
-        if verbose:
-            self.dump_properties()
-        return
-
     def dump_properties(self):
-        """ Print out the attributes of a compiler instance. """
+        """Print out the attributes of a compiler instance."""
         props = []
         for key in self.executables.keys() + \
                 ['version','libraries','library_dirs',
                  'object_switch','compile_switch']:
             if hasattr(self,key):
                 v = getattr(self,key)
-                props.append((key, None, '= '+`v`))
+                props.append((key, None, '= '+repr(v)))
         props.sort()
 
         pretty_printer = FancyGetopt(props)
@@ -429,7 +542,8 @@
 
         if os.name == 'nt':
             compiler = _nt_quote_args(compiler)
-        command = compiler + cc_args + extra_flags + s_args + o_args + extra_postargs
+        command = compiler + cc_args + extra_flags + s_args + o_args \
+                  + extra_postargs
 
         display = '%s: %s' % (os.path.basename(compiler[0]) + flavor,
                               src)
@@ -512,167 +626,145 @@
             log.debug("skipping %s (up-to-date)", output_filename)
         return
 
-
-    ## Private methods:
-
-    def __get_cmd(self, command, envvar=None, confvar=None):
-        if command is None:
-            var = None
-        elif is_string(command):
-            var = self.executables[command]
-            if var is not None:
-                var = var[0]
+    def _environment_hook(self, name, hook_name):
+        if hook_name is None:
+            return None
+        if is_string(hook_name):
+            if hook_name.startswith('self.'):
+                hook_name = hook_name[5:]
+                hook = getattr(self, hook_name)
+                return hook()
+            elif hook_name.startswith('exe.'):
+                hook_name = hook_name[4:]
+                var = self.executables[hook_name]
+                if var:
+                    return var[0]
+                else:
+                    return None
+            elif hook_name.startswith('flags.'):
+                hook_name = hook_name[6:]
+                hook = getattr(self, 'get_flags_' + hook_name)
+                return hook()
         else:
-            var = command()
-        if envvar is not None:
-            var = os.environ.get(envvar, var)
-        if confvar is not None:
-            var = confvar[0].get(confvar[1], [None,var])[1]
-        return var
+            return hook_name()
 
-    def __get_flags(self, command, envvar=None, confvar=None):
-        if command is None:
-            var = []
-        elif is_string(command):
-            var = self.executables[command][1:]
-        else:
-            var = command()
-        if envvar is not None:
-            var = os.environ.get(envvar, var)
-        if confvar is not None:
-            var = confvar[0].get(confvar[1], [None,var])[1]
-        if is_string(var):
-            var = split_quoted(var)
-        return var
-
     ## class FCompiler
 
-fcompiler_class = {'gnu':('gnu','GnuFCompiler',
-                          "GNU Fortran Compiler"),
-                   'gnu95':('gnu','Gnu95FCompiler',
-                            "GNU 95 Fortran Compiler"),
-                   'g95':('g95','G95FCompiler',
-                          "G95 Fortran Compiler"),
-                   'pg':('pg','PGroupFCompiler',
-                         "Portland Group Fortran Compiler"),
-                   'absoft':('absoft','AbsoftFCompiler',
-                             "Absoft Corp Fortran Compiler"),
-                   'mips':('mips','MipsFCompiler',
-                           "MIPSpro Fortran Compiler"),
-                   'sun':('sun','SunFCompiler',
-                          "Sun|Forte Fortran 95 Compiler"),
-                   'intel':('intel','IntelFCompiler',
-                            "Intel Fortran Compiler for 32-bit apps"),
-                   'intelv':('intel','IntelVisualFCompiler',
-                             "Intel Visual Fortran Compiler for 32-bit apps"),
-                   'intele':('intel','IntelItaniumFCompiler',
-                             "Intel Fortran Compiler for Itanium apps"),
-                   'intelev':('intel','IntelItaniumVisualFCompiler',
-                              "Intel Visual Fortran Compiler for Itanium apps"),
-                   'intelem':('intel','IntelEM64TFCompiler',
-                             "Intel Fortran Compiler for EM64T-based apps"),
-                   'nag':('nag','NAGFCompiler',
-                          "NAGWare Fortran 95 Compiler"),
-                   'compaq':('compaq','CompaqFCompiler',
-                             "Compaq Fortran Compiler"),
-                   'compaqv':('compaq','CompaqVisualFCompiler',
-                             "DIGITAL|Compaq Visual Fortran Compiler"),
-                   'vast':('vast','VastFCompiler',
-                           "Pacific-Sierra Research Fortran 90 Compiler"),
-                   'hpux':('hpux','HPUXFCompiler',
-                           "HP Fortran 90 Compiler"),
-                   'lahey':('lahey','LaheyFCompiler',
-                            "Lahey/Fujitsu Fortran 95 Compiler"),
-                   'ibm':('ibm','IbmFCompiler',
-                          "IBM XL Fortran Compiler"),
-                   'f':('f','FFCompiler',
-                        "Fortran Company/NAG F Compiler"),
-                   'none':('none','NoneFCompiler',"Fake Fortran compiler")
-                   }
-
 _default_compilers = (
     # Platform mappings
-    ('win32',('gnu','intelv','absoft','compaqv','intelev','gnu95','g95')),
-    ('cygwin.*',('gnu','intelv','absoft','compaqv','intelev','gnu95','g95')),
-    ('linux.*',('gnu','intel','lahey','pg','absoft','nag','vast','compaq',
+    ('win32', ('gnu','intelv','absoft','compaqv','intelev','gnu95','g95')),
+    ('cygwin.*', ('gnu','intelv','absoft','compaqv','intelev','gnu95','g95')),
+    ('linux.*', ('gnu','intel','lahey','pg','absoft','nag','vast','compaq',
                 'intele','intelem','gnu95','g95')),
-    ('darwin.*',('nag','absoft','ibm','gnu','gnu95','g95')),
-    ('sunos.*',('sun','gnu','gnu95','g95')),
-    ('irix.*',('mips','gnu','gnu95',)),
-    ('aix.*',('ibm','gnu','gnu95',)),
+    ('darwin.*', ('nag', 'absoft', 'ibm', 'intel', 'gnu', 'gnu95', 'g95')),
+    ('sunos.*', ('sun','gnu','gnu95','g95')),
+    ('irix.*', ('mips','gnu','gnu95',)),
+    ('aix.*', ('ibm','gnu','gnu95',)),
     # OS mappings
-    ('posix',('gnu','gnu95',)),
-    ('nt',('gnu','gnu95',)),
-    ('mac',('gnu','gnu95',)),
+    ('posix', ('gnu','gnu95',)),
+    ('nt', ('gnu','gnu95',)),
+    ('mac', ('gnu','gnu95',)),
     )
 
-def _find_existing_fcompiler(compilers, osname=None, platform=None, requiref90=None):
-    for compiler in compilers:
+fcompiler_class = None
+
+def load_all_fcompiler_classes():
+    """Cache all the FCompiler classes found in modules in the
+    numpy.distutils.fcompiler package.
+    """
+    from glob import glob
+    global fcompiler_class
+    if fcompiler_class is not None:
+        return
+    pys = os.path.join(os.path.dirname(__file__), '*.py')
+    fcompiler_class = {}
+    for fname in glob(pys):
+        module_name, ext = os.path.splitext(os.path.basename(fname))
+        module_name = 'numpy.distutils.fcompiler.' + module_name
+        __import__ (module_name)
+        module = sys.modules[module_name]
+        if hasattr(module, 'compilers'):
+            for cname in module.compilers:
+                klass = getattr(module, cname)
+                fcompiler_class[klass.compiler_type] = (klass.compiler_type,
+                                                        klass,
+                                                        klass.description)
+
+def _find_existing_fcompiler(compiler_types, osname=None, platform=None,
+                             requiref90=False):
+    from numpy.distutils.core import get_distribution
+    dist = get_distribution(always=True)
+    for compiler_type in compiler_types:
         v = None
         try:
-            c = new_fcompiler(plat=platform, compiler=compiler)
-            c.customize()
+            c = new_fcompiler(plat=platform, compiler=compiler_type)
+            c.customize(dist)
             v = c.get_version()
             if requiref90 and c.compiler_f90 is None:
                 v = None
                 new_compiler = c.suggested_f90_compiler
                 if new_compiler:
-                    log.warn('Trying %r compiler as suggested by %r compiler for f90 support.' % (compiler, new_compiler))
+                    log.warn('Trying %r compiler as suggested by %r '
+                             'compiler for f90 support.' % (compiler,
+                                                            new_compiler))
                     c = new_fcompiler(plat=platform, compiler=new_compiler)
-                    c.customize()
+                    c.customize(dist)
                     v = c.get_version()
                     if v is not None:
-                        compiler = new_compiler
+                        compiler_type = new_compiler
             if requiref90 and c.compiler_f90 is None:
-                raise ValueError,'%s does not support compiling f90 codes, skipping.' \
-                      % (c.__class__.__name__)
+                raise ValueError('%s does not support compiling f90 codes, '
+                                 'skipping.' % (c.__class__.__name__))
         except DistutilsModuleError:
             pass
-        except Exception, msg:
-            log.warn(msg)
+        except CompilerNotFound:
+            pass
         if v is not None:
-            return compiler
-    return
+            return compiler_type
+    return None
 
-def get_default_fcompiler(osname=None, platform=None, requiref90=None):
-    """ Determine the default Fortran compiler to use for the given platform. """
+def available_fcompilers_for_platform(osname=None, platform=None):
     if osname is None:
         osname = os.name
     if platform is None:
         platform = sys.platform
-    matching_compilers = []
-    for pattern, compiler in _default_compilers:
-        if re.match(pattern, platform) is not None or \
-               re.match(pattern, osname) is not None:
-            if is_sequence(compiler):
-                matching_compilers.extend(list(compiler))
-            else:
-                matching_compilers.append(compiler)
-    if not matching_compilers:
-        matching_compilers.append('gnu')
-    compiler =  _find_existing_fcompiler(matching_compilers,
-                                         osname=osname,
-                                         platform=platform,
-                                         requiref90=requiref90)
-    if compiler is not None:
-        return compiler
-    return matching_compilers[0]
+    matching_compiler_types = []
+    for pattern, compiler_type in _default_compilers:
+        if re.match(pattern, platform) or re.match(pattern, osname):
+            for ct in compiler_type:
+                if ct not in matching_compiler_types:
+                    matching_compiler_types.append(ct)
+    if not matching_compiler_types:
+        matching_compiler_types.append('gnu')
+    return matching_compiler_types
 
+def get_default_fcompiler(osname=None, platform=None, requiref90=False):
+    """Determine the default Fortran compiler to use for the given
+    platform."""
+    matching_compiler_types = available_fcompilers_for_platform(osname,
+                                                                platform)
+    compiler_type =  _find_existing_fcompiler(matching_compiler_types,
+                                              osname=osname,
+                                              platform=platform,
+                                              requiref90=requiref90)
+    return compiler_type
+
 def new_fcompiler(plat=None,
                   compiler=None,
                   verbose=0,
                   dry_run=0,
                   force=0,
-                  requiref90=0):
-    """ Generate an instance of some FCompiler subclass for the supplied
+                  requiref90=False):
+    """Generate an instance of some FCompiler subclass for the supplied
     platform/compiler combination.
     """
+    load_all_fcompiler_classes()
     if plat is None:
         plat = os.name
+    if compiler is None:
+        compiler = get_default_fcompiler(plat, requiref90=requiref90)
     try:
-        if compiler is None:
-            compiler = get_default_fcompiler(plat,requiref90=requiref90)
-        (module_name, class_name, long_description) = fcompiler_class[compiler]
+        module_name, klass, long_description = fcompiler_class[compiler]
     except KeyError:
         msg = "don't know how to compile Fortran code on platform '%s'" % plat
         if compiler is not None:
@@ -681,69 +773,67 @@
                   % (','.join(fcompiler_class.keys()))
         raise DistutilsPlatformError, msg
 
-    try:
-        module_name = 'numpy.distutils.fcompiler.'+module_name
-        __import__ (module_name)
-        module = sys.modules[module_name]
-        klass = vars(module)[class_name]
-    except ImportError:
-        raise DistutilsModuleError, \
-              "can't compile Fortran code: unable to load module '%s'" % \
-              module_name
-    except KeyError:
-        raise DistutilsModuleError, \
-              ("can't compile Fortran code: unable to find class '%s' " +
-               "in module '%s'") % (class_name, module_name)
-    compiler = klass(None, dry_run, force)
-    log.debug('new_fcompiler returns %s' % (klass))
+    compiler = klass(verbose=verbose, dry_run=dry_run, force=force)
     return compiler
 
-def show_fcompilers(dist = None):
-    """ Print list of available compilers (used by the "--help-fcompiler"
+def show_fcompilers(dist=None):
+    """Print list of available compilers (used by the "--help-fcompiler"
     option to "config_fc").
     """
     if dist is None:
         from distutils.dist import Distribution
+        from numpy.distutils.command.config_compiler import config_fc
         dist = Distribution()
         dist.script_name = os.path.basename(sys.argv[0])
         dist.script_args = ['config_fc'] + sys.argv[1:]
+        try:
+            dist.script_args.remove('--help-fcompiler')
+        except ValueError:
+            pass
         dist.cmdclass['config_fc'] = config_fc
         dist.parse_config_files()
         dist.parse_command_line()
     compilers = []
     compilers_na = []
     compilers_ni = []
-    for compiler in fcompiler_class.keys():
-        v = 'N/A'
+    if not fcompiler_class:
+        load_all_fcompiler_classes()
+    platform_compilers = available_fcompilers_for_platform()
+    for compiler in platform_compilers:
+        v = None
         log.set_verbosity(-2)
+        log.set_verbosity(-2)
         try:
-            c = new_fcompiler(compiler=compiler)
+            c = new_fcompiler(compiler=compiler, verbose=dist.verbose)
             c.customize(dist)
             v = c.get_version()
-        except DistutilsModuleError:
+        except (DistutilsModuleError, CompilerNotFound):
             pass
-        except Exception, msg:
-            log.warn(msg)
 
+
         if v is None:
             compilers_na.append(("fcompiler="+compiler, None,
                               fcompiler_class[compiler][2]))
-        elif v=='N/A':
-            compilers_ni.append(("fcompiler="+compiler, None,
-                                 fcompiler_class[compiler][2]))
         else:
+            c.dump_properties()
             compilers.append(("fcompiler="+compiler, None,
                               fcompiler_class[compiler][2] + ' (%s)' % v))
 
+    compilers_ni = list(set(fcompiler_class.keys()) - set(platform_compilers))
+    compilers_ni = [("fcompiler="+fc, None, fcompiler_class[fc][2])
+                    for fc in compilers_ni]
+
     compilers.sort()
     compilers_na.sort()
+    compilers_ni.sort()
     pretty_printer = FancyGetopt(compilers)
-    pretty_printer.print_help("List of available Fortran compilers:")
+    pretty_printer.print_help("Fortran compilers found:")
     pretty_printer = FancyGetopt(compilers_na)
-    pretty_printer.print_help("List of unavailable Fortran compilers:")
+    pretty_printer.print_help("Compilers available for this "
+                              "platform, but not found:")
     if compilers_ni:
         pretty_printer = FancyGetopt(compilers_ni)
-        pretty_printer.print_help("List of unimplemented Fortran compilers:")
+        pretty_printer.print_help("Compilers not available on this platform:")
     print "For compiler details, run 'config_fc --verbose' setup command."
 
 def dummy_fortran_file():

Modified: trunk/numpy/distutils/fcompiler/absoft.py
===================================================================
--- trunk/numpy/distutils/fcompiler/absoft.py	2007-05-25 11:20:02 UTC (rev 3823)
+++ trunk/numpy/distutils/fcompiler/absoft.py	2007-05-25 11:41:16 UTC (rev 3824)
@@ -13,9 +13,12 @@
 from numpy.distutils.fcompiler import FCompiler, dummy_fortran_file
 from numpy.distutils.misc_util import cyg2win32
 
+compilers = ['AbsoftFCompiler']
+
 class AbsoftFCompiler(FCompiler):
 
     compiler_type = 'absoft'
+    description = 'Absoft Corp Fortran Compiler'
     #version_pattern = r'FORTRAN 77 Compiler (?P<version>[^\s*,]*).*?Absoft Corp'
     version_pattern = r'(f90:.*?(Absoft Pro FORTRAN Version|FORTRAN 77 Compiler|Absoft Fortran Compiler Version|Copyright Absoft Corporation.*?Version))'+\
                        r' (?P<version>[^\s*,]*)(.*?Absoft Corp|)'
@@ -28,12 +31,12 @@
     # Note that fink installs g77 as f77, so need to use f90 for detection.
 
     executables = {
-        'version_cmd'  : ["f90", "-V -c %(fname)s.f -o %(fname)s.o" \
+        'version_cmd'  : ["<F90>", "-V -c %(fname)s.f -o %(fname)s.o" \
                           % {'fname':cyg2win32(dummy_fortran_file())}],
         'compiler_f77' : ["f77"],
         'compiler_fix' : ["f90"],
         'compiler_f90' : ["f90"],
-        'linker_so'    : ["f90"],
+        'linker_so'    : ["<F90>"],
         'archiver'     : ["ar", "-cr"],
         'ranlib'       : ["ranlib"]
         }

Modified: trunk/numpy/distutils/fcompiler/compaq.py
===================================================================
--- trunk/numpy/distutils/fcompiler/compaq.py	2007-05-25 11:20:02 UTC (rev 3823)
+++ trunk/numpy/distutils/fcompiler/compaq.py	2007-05-25 11:41:16 UTC (rev 3824)
@@ -7,9 +7,17 @@
 from numpy.distutils.cpuinfo import cpu
 from numpy.distutils.fcompiler import FCompiler
 
+compilers = ['CompaqFCompiler']
+if os.name != 'posix':
+    # Otherwise we'd get a false positive on posix systems with
+    # case-insensitive filesystems (like darwin), because we'll pick
+    # up /bin/df
+    compilers.append('CompaqVisualFCompiler')
+
 class CompaqFCompiler(FCompiler):
 
     compiler_type = 'compaq'
+    description = 'Compaq Fortran Compiler'
     version_pattern = r'Compaq Fortran (?P<version>[^\s]*).*'
 
     if sys.platform[:5]=='linux':
@@ -18,11 +26,11 @@
         fc_exe = 'f90'
 
     executables = {
-        'version_cmd'  : [fc_exe, "-version"],
+        'version_cmd'  : ['<F90>', "-version"],
         'compiler_f77' : [fc_exe, "-f77rtl","-fixed"],
         'compiler_fix' : [fc_exe, "-fixed"],
         'compiler_f90' : [fc_exe],
-        'linker_so'    : [fc_exe],
+        'linker_so'    : ['<F90>'],
         'archiver'     : ["ar", "-cr"],
         'ranlib'       : ["ranlib"]
         }
@@ -47,6 +55,7 @@
 class CompaqVisualFCompiler(FCompiler):
 
     compiler_type = 'compaqv'
+    description = 'DIGITAL or Compaq Visual Fortran Compiler'
     version_pattern = r'(DIGITAL|Compaq) Visual Fortran Optimizing Compiler'\
                       ' Version (?P<version>[^\s]*).*'
 
@@ -68,11 +77,11 @@
         ar_exe = m.lib
 
     executables = {
-        'version_cmd'  : ['DF', "/what"],
-        'compiler_f77' : ['DF', "/f77rtl","/fixed"],
-        'compiler_fix' : ['DF', "/fixed"],
-        'compiler_f90' : ['DF'],
-        'linker_so'    : ['DF'],
+        'version_cmd'  : ['<F90>', "/what"],
+        'compiler_f77' : [fc_exe, "/f77rtl","/fixed"],
+        'compiler_fix' : [fc_exe, "/fixed"],
+        'compiler_f90' : [fc_exe],
+        'linker_so'    : ['<F90>'],
         'archiver'     : [ar_exe, "/OUT:"],
         'ranlib'       : None
         }

Modified: trunk/numpy/distutils/fcompiler/g95.py
===================================================================
--- trunk/numpy/distutils/fcompiler/g95.py	2007-05-25 11:20:02 UTC (rev 3823)
+++ trunk/numpy/distutils/fcompiler/g95.py	2007-05-25 11:41:16 UTC (rev 3824)
@@ -6,9 +6,12 @@
 from numpy.distutils.cpuinfo import cpu
 from numpy.distutils.fcompiler import FCompiler
 
+compilers = ['G95FCompiler']
+
 class G95FCompiler(FCompiler):
+    compiler_type = 'g95'
+    description = 'G95 Fortran Compiler'
 
-    compiler_type = 'g95'
 #    version_pattern = r'G95 \((GCC (?P<gccversion>[\d.]+)|.*?) \(g95!\) (?P<version>.*)\).*'
     # $ g95 --version
     # G95 (GCC 4.0.3 (g95!) May 22 2006)
@@ -17,13 +20,12 @@
     # $ g95 --version
     # G95 (GCC 4.0.3 (g95 0.90!) Aug 22 2006)
 
-
     executables = {
-        'version_cmd'  : ["g95", "--version"],
+        'version_cmd'  : ["<F90>", "--version"],
         'compiler_f77' : ["g95", "-ffixed-form"],
         'compiler_fix' : ["g95", "-ffixed-form"],
         'compiler_f90' : ["g95"],
-        'linker_so'    : ["g95","-shared"],
+        'linker_so'    : ["<F90>","-shared"],
         'archiver'     : ["ar", "-cr"],
         'ranlib'       : ["ranlib"]
         }

Modified: trunk/numpy/distutils/fcompiler/gnu.py
===================================================================
--- trunk/numpy/distutils/fcompiler/gnu.py	2007-05-25 11:20:02 UTC (rev 3823)
+++ trunk/numpy/distutils/fcompiler/gnu.py	2007-05-25 11:41:16 UTC (rev 3824)
@@ -5,12 +5,14 @@
 
 from numpy.distutils.cpuinfo import cpu
 from numpy.distutils.fcompiler import FCompiler
-from numpy.distutils.exec_command import exec_command, find_executable
+from numpy.distutils.exec_command import exec_command
 from numpy.distutils.misc_util import mingw32, msvc_runtime_library
 
-class GnuFCompiler(FCompiler):
+compilers = ['GnuFCompiler', 'Gnu95FCompiler']
 
+class GnuFCompiler(FCompiler):
     compiler_type = 'gnu'
+    description = 'GNU Fortran 77 compiler'
 
     def gnu_version_match(self, version_string):
         """Handle the different versions of GNU fortran compilers"""
@@ -44,22 +46,23 @@
     #         GNU Fortran 0.5.25 20010319 (prerelease)
     # Redhat: GNU Fortran (GCC 3.2.2 20030222 (Red Hat Linux 3.2.2-5)) 3.2.2 20030222 (Red Hat Linux 3.2.2-5)
 
+    possible_executables = ['g77', 'f77']
     executables = {
-        'version_cmd'  : ["g77", "--version"],
-        'compiler_f77' : ["g77", "-g", "-Wall","-fno-second-underscore"],
+        'version_cmd'  : [None, "--version"],
+        'compiler_f77' : [None, "-g", "-Wall", "-fno-second-underscore"],
         'compiler_f90' : None, # Use --fcompiler=gnu95 for f90 codes
         'compiler_fix' : None,
-        'linker_so'    : ["g77", "-g", "-Wall"],
+        'linker_so'    : [None, "-g", "-Wall"],
         'archiver'     : ["ar", "-cr"],
         'ranlib'       : ["ranlib"],
-        'linker_exe'   : ["g77", "-g", "-Wall"]
+        'linker_exe'   : [None, "-g", "-Wall"]
         }
     module_dir_switch = None
     module_include_switch = None
 
     # Cygwin: f771: warning: -fPIC ignored for target (all code is
     # position independent)
-    if os.name != 'nt' and sys.platform!='cygwin':
+    if os.name != 'nt' and sys.platform != 'cygwin':
         pic_flags = ['-fPIC']
 
     # use -mno-cygwin for g77 when Python is not Cygwin-Python
@@ -71,13 +74,6 @@
 
     suggested_f90_compiler = 'gnu95'
 
-    def find_executables(self):
-        for fc_exe in [find_executable(c) for c in ['g77','f77']]:
-            if os.path.isfile(fc_exe):
-                break
-        for key in ['version_cmd', 'compiler_f77', 'linker_so', 'linker_exe']:
-            self.executables[key][0] = fc_exe
-
     #def get_linker_so(self):
     #    # win32 linking should be handled by standard linker
     #    # Darwin g77 cannot be used as a linker.
@@ -106,7 +102,7 @@
             opt.extend(['-undefined', 'dynamic_lookup', '-bundle'])
         else:
             opt.append("-shared")
-        if sys.platform[:5]=='sunos':
+        if sys.platform.startswith('sunos'):
             # SunOS often has dynamically loaded symbols defined in the
             # static library libg2c.a  The linker doesn't like this.  To
             # ignore the problem, use the -mimpure-text flag.  It isn't
@@ -178,13 +174,10 @@
 
     def get_flags_arch(self):
         opt = []
-        if sys.platform=='darwin':
-            if os.name != 'posix':
-                # this should presumably correspond to Apple
-                if cpu.is_ppc():
-                    opt.append('-arch ppc')
-                elif cpu.is_i386():
-                    opt.append('-arch i386')
+        if sys.platform == 'darwin':
+            # Since Apple doesn't distribute a GNU Fortran compiler, we
+            # can't add -arch ppc or -arch i386, as only their version
+            # of the GNU compilers accepts those.
             for a in '601 602 603 603e 604 604e 620 630 740 7400 7450 750'\
                     '403 505 801 821 823 860'.split():
                 if getattr(cpu,'is_ppc%s'%a)():
@@ -276,8 +269,8 @@
         return opt
 
 class Gnu95FCompiler(GnuFCompiler):
-
     compiler_type = 'gnu95'
+    description = 'GNU Fortran 95 compiler'
 
     def version_match(self, version_string):
         v = self.gnu_version_match(version_string)
@@ -293,17 +286,18 @@
     #       GNU Fortran 95 (GCC) 4.2.0 20060218 (experimental)
     #       GNU Fortran (GCC) 4.3.0 20070316 (experimental)
 
+    possible_executables = ['gfortran', 'f95']
     executables = {
-        'version_cmd'  : ["gfortran", "--version"],
-        'compiler_f77' : ["gfortran", "-Wall", "-ffixed-form",
+        'version_cmd'  : ["<F90>", "--version"],
+        'compiler_f77' : [None, "-Wall", "-ffixed-form",
                           "-fno-second-underscore"],
-        'compiler_f90' : ["gfortran", "-Wall", "-fno-second-underscore"],
-        'compiler_fix' : ["gfortran", "-Wall", "-ffixed-form",
+        'compiler_f90' : [None, "-Wall", "-fno-second-underscore"],
+        'compiler_fix' : [None, "-Wall", "-ffixed-form",
                           "-fno-second-underscore"],
-        'linker_so'    : ["gfortran", "-Wall"],
+        'linker_so'    : ["<F90>", "-Wall"],
         'archiver'     : ["ar", "-cr"],
         'ranlib'       : ["ranlib"],
-        'linker_exe'   : ["gfortran", "-Wall"]
+        'linker_exe'   : [None,"-Wall"]
         }
 
     # use -mno-cygwin flag for g77 when Python is not Cygwin-Python
@@ -317,14 +311,6 @@
 
     g2c = 'gfortran'
 
-    def find_executables(self):
-        for fc_exe in [find_executable(c) for c in ['gfortran','f95']]:
-            if os.path.isfile(fc_exe):
-                break
-        for key in ['version_cmd', 'compiler_f77', 'compiler_f90',
-                    'compiler_fix', 'linker_so', 'linker_exe']:
-            self.executables[key][0] = fc_exe
-
     def get_libraries(self):
         opt = GnuFCompiler.get_libraries(self)
         if sys.platform == 'darwin':
@@ -339,3 +325,6 @@
     compiler = GnuFCompiler()
     compiler.customize()
     print compiler.get_version()
+    compiler = Gnu95FCompiler()
+    compiler.customize()
+    print compiler.get_version()

Modified: trunk/numpy/distutils/fcompiler/hpux.py
===================================================================
--- trunk/numpy/distutils/fcompiler/hpux.py	2007-05-25 11:20:02 UTC (rev 3823)
+++ trunk/numpy/distutils/fcompiler/hpux.py	2007-05-25 11:41:16 UTC (rev 3824)
@@ -4,13 +4,16 @@
 from numpy.distutils.cpuinfo import cpu
 from numpy.distutils.fcompiler import FCompiler
 
+compilers = ['HPUXFCompiler']
+
 class HPUXFCompiler(FCompiler):
 
     compiler_type = 'hpux'
+    description = 'HP Fortran 90 Compiler'
     version_pattern =  r'HP F90 (?P<version>[^\s*,]*)'
 
     executables = {
-        'version_cmd'  : ["f90", "+version"],
+        'version_cmd'  : ["<F90>", "+version"],
         'compiler_f77' : ["f90"],
         'compiler_fix' : ["f90"],
         'compiler_f90' : ["f90"],

Modified: trunk/numpy/distutils/fcompiler/ibm.py
===================================================================
--- trunk/numpy/distutils/fcompiler/ibm.py	2007-05-25 11:20:02 UTC (rev 3823)
+++ trunk/numpy/distutils/fcompiler/ibm.py	2007-05-25 11:41:16 UTC (rev 3824)
@@ -7,13 +7,16 @@
 from distutils import log
 from distutils.sysconfig import get_python_lib
 
-class IbmFCompiler(FCompiler):
+compilers = ['IBMFCompiler']
 
+class IBMFCompiler(FCompiler):
     compiler_type = 'ibm'
+    description = 'IBM XL Fortran Compiler'
     version_pattern =  r'(xlf\(1\)\s*|)IBM XL Fortran ((Advanced Edition |)Version |Enterprise Edition V)(?P<version>[^\s*]*)'
     #IBM XL Fortran Enterprise Edition V10.1 for AIX \nVersion: 10.01.0000.0004
+
     executables = {
-        'version_cmd'  : ["xlf","-qversion"],
+        'version_cmd'  : ["<F77>", "-qversion"],
         'compiler_f77' : ["xlf"],
         'compiler_fix' : ["xlf90", "-qfixed"],
         'compiler_f90' : ["xlf90"],

Modified: trunk/numpy/distutils/fcompiler/intel.py
===================================================================
--- trunk/numpy/distutils/fcompiler/intel.py	2007-05-25 11:20:02 UTC (rev 3823)
+++ trunk/numpy/distutils/fcompiler/intel.py	2007-05-25 11:41:16 UTC (rev 3824)
@@ -9,8 +9,11 @@
 from numpy.distutils.cpuinfo import cpu
 from numpy.distutils.ccompiler import simple_version_match
 from numpy.distutils.fcompiler import FCompiler, dummy_fortran_file
-from numpy.distutils.exec_command import find_executable
 
+compilers = ['IntelFCompiler', 'IntelVisualFCompiler',
+             'IntelItaniumFCompiler', 'IntelItaniumVisualFCompiler',
+             'IntelEM64TFCompiler']
+
 def intel_version_match(type):
     # Match against the important stuff in the version string
     return simple_version_match(start=r'Intel.*?Fortran.*?%s.*?Version' % (type,))
@@ -18,19 +21,18 @@
 class IntelFCompiler(FCompiler):
 
     compiler_type = 'intel'
+    description = 'Intel Fortran Compiler for 32-bit apps'
     version_match = intel_version_match('32-bit')
 
-    for fc_exe in map(find_executable,['ifort','ifc']):
-        if os.path.isfile(fc_exe):
-            break
+    possible_executables = ['ifort', 'ifc']
 
     executables = {
-        'version_cmd'  : [fc_exe, "-FI -V -c %(fname)s.f -o %(fname)s.o" \
+        'version_cmd'  : ["<F77>", "-FI -V -c %(fname)s.f -o %(fname)s.o" \
                           % {'fname':dummy_fortran_file()}],
-        'compiler_f77' : [fc_exe,"-72","-w90","-w95"],
-        'compiler_fix' : [fc_exe,"-FI"],
-        'compiler_f90' : [fc_exe],
-        'linker_so'    : [fc_exe,"-shared"],
+        'compiler_f77' : [None,"-72","-w90","-w95"],
+        'compiler_f90' : [None],
+        'compiler_fix' : [None,"-FI"],
+        'linker_so'    : ["<F90>","-shared"],
         'archiver'     : ["ar", "-cr"],
         'ranlib'       : ["ranlib"]
         }
@@ -80,6 +82,7 @@
 
 class IntelItaniumFCompiler(IntelFCompiler):
     compiler_type = 'intele'
+    description = 'Intel Fortran Compiler for Itanium apps'
 
     version_match = intel_version_match('Itanium')
 
@@ -88,37 +91,34 @@
 #Copyright (C) 1985-2006 Intel Corporation.  All rights reserved.
 #30 DAY EVALUATION LICENSE
 
-    for fc_exe in map(find_executable,['ifort','efort','efc']):
-        if os.path.isfile(fc_exe):
-            break
+    possible_executables = ['ifort', 'efort', 'efc']
 
     executables = {
-        'version_cmd'  : [fc_exe, "-FI -V -c %(fname)s.f -o %(fname)s.o" \
+        'version_cmd'  : ['<F77>', "-FI -V -c %(fname)s.f -o %(fname)s.o" \
                           % {'fname':dummy_fortran_file()}],
-        'compiler_f77' : [fc_exe,"-FI","-w90","-w95"],
-        'compiler_fix' : [fc_exe,"-FI"],
-        'compiler_f90' : [fc_exe],
-        'linker_so'    : [fc_exe,"-shared"],
+        'compiler_f77' : [None,"-FI","-w90","-w95"],
+        'compiler_fix' : [None,"-FI"],
+        'compiler_f90' : [None],
+        'linker_so'    : ['<F90>', "-shared"],
         'archiver'     : ["ar", "-cr"],
         'ranlib'       : ["ranlib"]
         }
 
 class IntelEM64TFCompiler(IntelFCompiler):
     compiler_type = 'intelem'
+    description = 'Intel Fortran Compiler for EM64T-based apps'
 
     version_match = intel_version_match('EM64T-based')
 
-    for fc_exe in map(find_executable,['ifort','efort','efc']):
-        if os.path.isfile(fc_exe):
-            break
+    possible_executables = ['ifort', 'efort', 'efc']
 
     executables = {
-        'version_cmd'  : [fc_exe, "-FI -V -c %(fname)s.f -o %(fname)s.o" \
+        'version_cmd'  : ['<F77>', "-FI -V -c %(fname)s.f -o %(fname)s.o" \
                           % {'fname':dummy_fortran_file()}],
-        'compiler_f77' : [fc_exe,"-FI","-w90","-w95"],
-        'compiler_fix' : [fc_exe,"-FI"],
-        'compiler_f90' : [fc_exe],
-        'linker_so'    : [fc_exe,"-shared"],
+        'compiler_f77' : [None, "-FI", "-w90", "-w95"],
+        'compiler_fix' : [None, "-FI"],
+        'compiler_f90' : [None],
+        'linker_so'    : ['<F90>', "-shared"],
         'archiver'     : ["ar", "-cr"],
         'ranlib'       : ["ranlib"]
         }
@@ -133,20 +133,20 @@
 # and the Visual compilers?
 
 class IntelVisualFCompiler(FCompiler):
-
     compiler_type = 'intelv'
+    description = 'Intel Visual Fortran Compiler for 32-bit apps'
     version_match = intel_version_match('32-bit')
 
     ar_exe = 'lib.exe'
-    fc_exe = 'ifl'
+    possible_executables = ['ifl']
 
     executables = {
-        'version_cmd'  : [fc_exe, "-FI -V -c %(fname)s.f -o %(fname)s.o" \
+        'version_cmd'  : ['<F77>', "-FI -V -c %(fname)s.f -o %(fname)s.o" \
                           % {'fname':dummy_fortran_file()}],
-        'compiler_f77' : [fc_exe,"-FI","-w90","-w95"],
-        'compiler_fix' : [fc_exe,"-FI","-4L72","-w"],
-        'compiler_f90' : [fc_exe],
-        'linker_so'    : [fc_exe,"-shared"],
+        'compiler_f77' : [None,"-FI","-w90","-w95"],
+        'compiler_fix' : [None,"-FI","-4L72","-w"],
+        'compiler_f90' : [None],
+        'linker_so'    : ['<F90>', "-shared"],
         'archiver'     : [ar_exe, "/verbose", "/OUT:"],
         'ranlib'       : None
         }
@@ -185,20 +185,21 @@
         return opt
 
 class IntelItaniumVisualFCompiler(IntelVisualFCompiler):
+    compiler_type = 'intelev'
+    description = 'Intel Visual Fortran Compiler for Itanium apps'
 
-    compiler_type = 'intelev'
     version_match = intel_version_match('Itanium')
 
-    fc_exe = 'efl' # XXX this is a wild guess
+    possible_executables = ['efl'] # XXX this is a wild guess
     ar_exe = IntelVisualFCompiler.ar_exe
 
     executables = {
-        'version_cmd'  : [fc_exe, "-FI -V -c %(fname)s.f -o %(fname)s.o" \
+        'version_cmd'  : ['<F77>', "-FI -V -c %(fname)s.f -o %(fname)s.o" \
                           % {'fname':dummy_fortran_file()}],
-        'compiler_f77' : [fc_exe,"-FI","-w90","-w95"],
-        'compiler_fix' : [fc_exe,"-FI","-4L72","-w"],
-        'compiler_f90' : [fc_exe],
-        'linker_so'    : [fc_exe,"-shared"],
+        'compiler_f77' : [None,"-FI","-w90","-w95"],
+        'compiler_fix' : [None,"-FI","-4L72","-w"],
+        'compiler_f90' : [None],
+        'linker_so'    : ['<F90>',"-shared"],
         'archiver'     : [ar_exe, "/verbose", "/OUT:"],
         'ranlib'       : None
         }

Modified: trunk/numpy/distutils/fcompiler/lahey.py
===================================================================
--- trunk/numpy/distutils/fcompiler/lahey.py	2007-05-25 11:20:02 UTC (rev 3823)
+++ trunk/numpy/distutils/fcompiler/lahey.py	2007-05-25 11:41:16 UTC (rev 3824)
@@ -4,13 +4,16 @@
 from numpy.distutils.cpuinfo import cpu
 from numpy.distutils.fcompiler import FCompiler
 
+compilers = ['LaheyFCompiler']
+
 class LaheyFCompiler(FCompiler):
 
     compiler_type = 'lahey'
+    description = 'Lahey/Fujitsu Fortran 95 Compiler'
     version_pattern =  r'Lahey/Fujitsu Fortran 95 Compiler Release (?P<version>[^\s*]*)'
 
     executables = {
-        'version_cmd'  : ["lf95", "--version"],
+        'version_cmd'  : ["<F90>", "--version"],
         'compiler_f77' : ["lf95", "--fix"],
         'compiler_fix' : ["lf95", "--fix"],
         'compiler_f90' : ["lf95"],

Modified: trunk/numpy/distutils/fcompiler/mips.py
===================================================================
--- trunk/numpy/distutils/fcompiler/mips.py	2007-05-25 11:20:02 UTC (rev 3823)
+++ trunk/numpy/distutils/fcompiler/mips.py	2007-05-25 11:41:16 UTC (rev 3824)
@@ -4,13 +4,16 @@
 from numpy.distutils.cpuinfo import cpu
 from numpy.distutils.fcompiler import FCompiler
 
-class MipsFCompiler(FCompiler):
+compilers = ['MIPSFCompiler']
 
+class MIPSFCompiler(FCompiler):
+
     compiler_type = 'mips'
+    description = 'MIPSpro Fortran Compiler'
     version_pattern =  r'MIPSpro Compilers: Version (?P<version>[^\s*,]*)'
 
     executables = {
-        'version_cmd'  : ["f90", "-version"],
+        'version_cmd'  : ["<F90>", "-version"],
         'compiler_f77' : ["f77", "-f77"],
         'compiler_fix' : ["f90", "-fixedform"],
         'compiler_f90' : ["f90"],

Modified: trunk/numpy/distutils/fcompiler/nag.py
===================================================================
--- trunk/numpy/distutils/fcompiler/nag.py	2007-05-25 11:20:02 UTC (rev 3823)
+++ trunk/numpy/distutils/fcompiler/nag.py	2007-05-25 11:41:16 UTC (rev 3824)
@@ -4,17 +4,20 @@
 from numpy.distutils.cpuinfo import cpu
 from numpy.distutils.fcompiler import FCompiler
 
+compilers = ['NAGFCompiler']
+
 class NAGFCompiler(FCompiler):
 
     compiler_type = 'nag'
+    description = 'NAGWare Fortran 95 Compiler'
     version_pattern =  r'NAGWare Fortran 95 compiler Release (?P<version>[^\s]*)'
 
     executables = {
-        'version_cmd'  : ["f95", "-V"],
+        'version_cmd'  : ["<F90>", "-V"],
         'compiler_f77' : ["f95", "-fixed"],
         'compiler_fix' : ["f95", "-fixed"],
         'compiler_f90' : ["f95"],
-        'linker_so'    : ["f95"],
+        'linker_so'    : ["<F90>"],
         'archiver'     : ["ar", "-cr"],
         'ranlib'       : ["ranlib"]
         }

Modified: trunk/numpy/distutils/fcompiler/none.py
===================================================================
--- trunk/numpy/distutils/fcompiler/none.py	2007-05-25 11:20:02 UTC (rev 3823)
+++ trunk/numpy/distutils/fcompiler/none.py	2007-05-25 11:41:16 UTC (rev 3824)
@@ -1,20 +1,27 @@
 
 from numpy.distutils.fcompiler import FCompiler
 
+compilers = ['NoneFCompiler']
+
 class NoneFCompiler(FCompiler):
 
     compiler_type = 'none'
+    description = 'Fake Fortran compiler'
 
-    executables = {'compiler_f77':['/path/to/nowhere/none'],
-                   'compiler_f90':['/path/to/nowhere/none'],
-                   'compiler_fix':['/path/to/nowhere/none'],
-                   'linker_so':['/path/to/nowhere/none'],
-                   'archiver':['/path/to/nowhere/none'],
-                   'ranlib':['/path/to/nowhere/none'],
-                   'version_cmd':['/path/to/nowhere/none'],
+    executables = {'compiler_f77' : None,
+                   'compiler_f90' : None,
+                   'compiler_fix' : None,
+                   'linker_so' : None,
+                   'linker_exe' : None,
+                   'archiver' : None,
+                   'ranlib' : None,
+                   'version_cmd' : None,
                    }
 
+    def find_executables(self):
+        pass
 
+
 if __name__ == '__main__':
     from distutils import log
     log.set_verbosity(2)

Modified: trunk/numpy/distutils/fcompiler/pg.py
===================================================================
--- trunk/numpy/distutils/fcompiler/pg.py	2007-05-25 11:20:02 UTC (rev 3823)
+++ trunk/numpy/distutils/fcompiler/pg.py	2007-05-25 11:41:16 UTC (rev 3824)
@@ -7,13 +7,16 @@
 from numpy.distutils.cpuinfo import cpu
 from numpy.distutils.fcompiler import FCompiler
 
+compilers = ['PGroupFCompiler']
+
 class PGroupFCompiler(FCompiler):
 
     compiler_type = 'pg'
+    description = 'Portland Group Fortran Compiler'
     version_pattern =  r'\s*pg(f77|f90|hpf) (?P<version>[\d.-]+).*'
 
     executables = {
-        'version_cmd'  : ["pgf77", "-V 2>/dev/null"],
+        'version_cmd'  : ["<F77>", "-V 2>/dev/null"],
         'compiler_f77' : ["pgf77"],
         'compiler_fix' : ["pgf90", "-Mfixed"],
         'compiler_f90' : ["pgf90"],

Modified: trunk/numpy/distutils/fcompiler/sun.py
===================================================================
--- trunk/numpy/distutils/fcompiler/sun.py	2007-05-25 11:20:02 UTC (rev 3823)
+++ trunk/numpy/distutils/fcompiler/sun.py	2007-05-25 11:41:16 UTC (rev 3824)
@@ -5,20 +5,23 @@
 from numpy.distutils.ccompiler import simple_version_match
 from numpy.distutils.fcompiler import FCompiler
 
+compilers = ['SunFCompiler']
+
 class SunFCompiler(FCompiler):
 
     compiler_type = 'sun'
+    description = 'Sun or Forte Fortran 95 Compiler'
     # ex:
     # f90: Sun WorkShop 6 update 2 Fortran 95 6.2 Patch 111690-10 2003/08/28
     version_match = simple_version_match(
                       start=r'f9[05]: (Sun|Forte|WorkShop).*Fortran 95')
 
     executables = {
-        'version_cmd'  : ["f90", "-V"],
+        'version_cmd'  : ["<F90>", "-V"],
         'compiler_f77' : ["f90"],
         'compiler_fix' : ["f90", "-fixed"],
         'compiler_f90' : ["f90"],
-        'linker_so'    : ["f90","-Bdynamic","-G"],
+        'linker_so'    : ["<F90>","-Bdynamic","-G"],
         'archiver'     : ["ar", "-cr"],
         'ranlib'       : ["ranlib"]
         }

Modified: trunk/numpy/distutils/fcompiler/vast.py
===================================================================
--- trunk/numpy/distutils/fcompiler/vast.py	2007-05-25 11:20:02 UTC (rev 3823)
+++ trunk/numpy/distutils/fcompiler/vast.py	2007-05-25 11:41:16 UTC (rev 3824)
@@ -4,9 +4,12 @@
 from numpy.distutils.cpuinfo import cpu
 from numpy.distutils.fcompiler.gnu import GnuFCompiler
 
+compilers = ['VastFCompiler']
+
 class VastFCompiler(GnuFCompiler):
 
     compiler_type = 'vast'
+    description = 'Pacific-Sierra Research Fortran 90 Compiler'
     version_pattern = r'\s*Pacific-Sierra Research vf90 '\
                       '(Personal|Professional)\s+(?P<version>[^\s]*)'
 
@@ -19,7 +22,7 @@
         'compiler_f77' : ["g77"],
         'compiler_fix' : ["f90", "-Wv,-ya"],
         'compiler_f90' : ["f90"],
-        'linker_so'    : ["f90"],
+        'linker_so'    : ["<F90>"],
         'archiver'     : ["ar", "-cr"],
         'ranlib'       : ["ranlib"]
         }
@@ -31,8 +34,8 @@
 
     def get_version_cmd(self):
         f90 = self.compiler_f90[0]
-        d,b = os.path.split(f90)
-        vf90 = os.path.join(d,'v'+b)
+        d, b = os.path.split(f90)
+        vf90 = os.path.join(d, 'v'+b)
         return vf90
 
     def get_flags_arch(self):

Modified: trunk/numpy/distutils/interactive.py
===================================================================
--- trunk/numpy/distutils/interactive.py	2007-05-25 11:20:02 UTC (rev 3823)
+++ trunk/numpy/distutils/interactive.py	2007-05-25 11:41:16 UTC (rev 3824)
@@ -19,7 +19,7 @@
 
 def show_fortran_compilers(*args):
     from fcompiler import show_fcompilers
-    show_fcompilers({})
+    show_fcompilers()
 
 def show_compilers(*args):
     from distutils.ccompiler import show_compilers




More information about the Numpy-svn mailing list