summaryrefslogtreecommitdiff
path: root/scipy/weave/platform_info.py
diff options
context:
space:
mode:
Diffstat (limited to 'scipy/weave/platform_info.py')
-rw-r--r--scipy/weave/platform_info.py245
1 files changed, 245 insertions, 0 deletions
diff --git a/scipy/weave/platform_info.py b/scipy/weave/platform_info.py
new file mode 100644
index 000000000..b9afc9a47
--- /dev/null
+++ b/scipy/weave/platform_info.py
@@ -0,0 +1,245 @@
+""" Information about platform and python version and compilers
+
+ This information is manly used to build directory names that
+ keep the object files and shared libaries straight when
+ multiple platforms share the same file system.
+"""
+
+import os, sys
+
+import distutils
+from distutils.sysconfig import customize_compiler
+
+
+try:
+ from scipy_distutils.ccompiler import new_compiler
+ from scipy_distutils.core import Extension, setup
+ from scipy_distutils.command.build_ext import build_ext
+except ImportError:
+ from distutils.ccompiler import new_compiler
+ from distutils.core import Extension, setup
+ from distutils.command.build_ext import build_ext
+
+import distutils.bcppcompiler
+
+#from scipy_distutils import mingw32_support
+
+def dummy_dist():
+ # create a dummy distribution. It will look at any site configuration files
+ # and parse the command line to pick up any user configured stuff. The
+ # resulting Distribution object is returned from setup.
+ # Setting _setup_stop_after prevents the any commands from actually executing.
+ distutils.core._setup_stop_after = "commandline"
+ dist = setup(name="dummy")
+ distutils.core._setup_stop_after = None
+ return dist
+
+def create_compiler_instance(dist):
+ # build_ext is in charge of building C/C++ files.
+ # We are using it and dist to parse config files, and command line
+ # configurations. There may be other ways to handle this, but I'm
+ # worried I may miss one of the steps in distutils if I do it my self.
+ #ext_builder = build_ext(dist)
+ #ext_builder.finalize_options ()
+
+ # For some reason the build_ext stuff wasn't picking up the compiler
+ # setting, so we grab it manually from the distribution object instead.
+ opts = dist.command_options.get('build_ext',None)
+ compiler_name = ''
+ if opts:
+ comp = opts.get('compiler',('',''))
+ compiler_name = comp[1]
+
+ # Create a new compiler, customize it based on the build settings,
+ # and return it.
+ if not compiler_name:
+ compiler_name = None
+ #print compiler_name
+ compiler = new_compiler(compiler=compiler_name)
+ customize_compiler(compiler)
+ return compiler
+
+def compiler_exe_name(compiler):
+ exe_name = ''
+ # this is really ugly... Why aren't the attribute names
+ # standardized and used in a consistent way?
+ if hasattr(compiler, "compiler"):
+ # standard unix format
+ exe_name = compiler.compiler[0]
+ elif hasattr(compiler, "cc"):
+ exe_name = compiler.cc
+ elif compiler.__class__ is distutils.bcppcompiler.BCPPCompiler:
+ exe_name = 'brcc32'
+ return exe_name
+
+def compiler_exe_path(exe_name):
+ exe_path = None
+ if os.path.exists(exe_name):
+ exe_path = exe_name
+ else:
+ path_string = os.environ['PATH']
+ path_string = os.path.expandvars(path_string)
+ path_string = os.path.expanduser(path_string)
+ paths = path_string.split(os.pathsep)
+ for path in paths:
+ path = os.path.join(path,exe_name)
+ if os.path.exists(path):
+ exe_path = path
+ break
+ # needed to catch gcc on mingw32 installations.
+ path = path + '.exe'
+ if os.path.exists(path):
+ exe_path = path
+ break
+ return exe_path
+
+def check_sum(file):
+
+ import md5
+ try:
+ f = open(file,'r')
+ bytes = f.read(-1)
+ except IOError:
+ bytes = ''
+ chk_sum = md5.md5(bytes)
+ return chk_sum.hexdigest()
+
+def get_compiler_dir(compiler_name):
+ """ Try to figure out the compiler directory based on the
+ input compiler name. This is fragile and really should
+ be done at the distutils level inside the compiler. I
+ think it is only useful on windows at the moment.
+ """
+ compiler_type = choose_compiler(compiler_name)
+ #print compiler_type
+ configure_sys_argv(compiler_type)
+ #print sys.argv
+ dist = dummy_dist()
+ compiler_obj = create_compiler_instance(dist)
+ #print compiler_obj.__class__
+ exe_name = compiler_exe_name(compiler_obj)
+ exe_path = compiler_exe_path(exe_name)
+ if not exe_path:
+ raise ValueError, "The '%s' compiler was not found." % compiler_name
+ chk_sum = check_sum(exe_path)
+ restore_sys_argv()
+
+ return 'compiler_'+chk_sum
+
+#----------------------------------------------------------------------------
+# Not needed -- used for testing.
+#----------------------------------------------------------------------------
+
+def choose_compiler(compiler_name=''):
+ """ Try and figure out which compiler is gonna be used on windows.
+ On other platforms, it just returns whatever value it is given.
+
+ converts 'gcc' to 'mingw32' on win32
+ """
+ if not compiler_name:
+ compiler_name = ''
+
+ if sys.platform == 'win32':
+ if not compiler_name:
+ # On Windows, default to MSVC and use gcc if it wasn't found
+ # wasn't found. If neither are found, go with whatever
+ # the default is for distutils -- and probably fail...
+ if msvc_exists():
+ compiler_name = 'msvc'
+ elif gcc_exists():
+ compiler_name = 'mingw32'
+ elif compiler_name == 'gcc':
+ compiler_name = 'mingw32'
+ else:
+ # don't know how to force gcc -- look into this.
+ if compiler_name == 'gcc':
+ compiler_name = 'unix'
+ return compiler_name
+
+old_argv = []
+def configure_sys_argv(compiler_name):
+ # We're gonna play some tricks with argv here to pass info to distutils
+ # which is really built for command line use. better way??
+ global old_argv
+ old_argv = sys.argv[:]
+ sys.argv = ['','build_ext','--compiler='+compiler_name]
+
+def restore_sys_argv():
+ sys.argv = old_argv
+
+def gcc_exists(name = 'gcc'):
+ """ Test to make sure gcc is found
+
+ Does this return correct value on win98???
+ """
+ result = 0
+ cmd = '%s -v' % name
+ try:
+ w,r=os.popen4(cmd)
+ w.close()
+ str_result = r.read()
+ #print str_result
+ if string.find(str_result,'Reading specs') != -1:
+ result = 1
+ except:
+ # This was needed because the msvc compiler messes with
+ # the path variable. and will occasionlly mess things up
+ # so much that gcc is lost in the path. (Occurs in test
+ # scripts)
+ result = not os.system(cmd)
+ return result
+
+def msvc_exists():
+ """ Determine whether MSVC is available on the machine.
+ """
+ result = 0
+ try:
+ w,r=os.popen4('cl')
+ w.close()
+ str_result = r.read()
+ #print str_result
+ if string.find(str_result,'Microsoft') != -1:
+ result = 1
+ except:
+ #assume we're ok if devstudio exists
+ import distutils.msvccompiler
+
+ # There was a change to 'distutils.msvccompiler' between Python 2.2
+ # and Python 2.3.
+ #
+ # In Python 2.2 the function is 'get_devstudio_versions'
+ # In Python 2.3 the function is 'get_build_version'
+ try:
+ version = distutils.msvccompiler.get_devstudio_versions()
+
+ except:
+ version = distutils.msvccompiler.get_build_version()
+
+ if version:
+ result = 1
+ return result
+
+if __name__ == "__main__":
+ """
+ import time
+ t1 = time.time()
+ dist = dummy_dist()
+ compiler_obj = create_compiler_instance(dist)
+ exe_name = compiler_exe_name(compiler_obj)
+ exe_path = compiler_exe_path(exe_name)
+ chk_sum = check_sum(exe_path)
+
+ t2 = time.time()
+ print 'compiler exe:', exe_path
+ print 'check sum:', chk_sum
+ print 'time (sec):', t2 - t1
+ print
+ """
+ path = get_compiler_dir('gcc')
+ print 'gcc path:', path
+ print
+ try:
+ path = get_compiler_dir('msvc')
+ print 'gcc path:', path
+ except ValueError:
+ pass