diff options
author | Pearu Peterson <pearu.peterson@gmail.com> | 2004-02-13 23:25:43 +0000 |
---|---|---|
committer | Pearu Peterson <pearu.peterson@gmail.com> | 2004-02-13 23:25:43 +0000 |
commit | 68569c20c5a8775e4ce0a01260d11e8d28753822 (patch) | |
tree | 6646ca7c132c68311df4a7a8373fb5bf62cbcef2 | |
parent | 3317087bc3f28aaebc5e796346e306cbb1828b43 (diff) | |
download | numpy-68569c20c5a8775e4ce0a01260d11e8d28753822.tar.gz |
Using new.instancemethod to override distutils internal methods - this is very robust that avoids using nasty import hacks.
-rw-r--r-- | scipy_distutils/__init__.py | 15 | ||||
-rw-r--r-- | scipy_distutils/ccompiler.py | 103 | ||||
-rw-r--r-- | scipy_distutils/command/build_clib.py | 30 | ||||
-rw-r--r-- | scipy_distutils/command/build_ext.py | 26 | ||||
-rw-r--r-- | scipy_distutils/exec_command.py | 2 | ||||
-rw-r--r-- | scipy_distutils/extension.py | 2 | ||||
-rw-r--r-- | scipy_distutils/fcompiler.py | 59 | ||||
-rw-r--r-- | scipy_distutils/mingw32ccompiler.py | 1 | ||||
-rw-r--r-- | scipy_distutils/unixccompiler.py | 136 |
9 files changed, 201 insertions, 173 deletions
diff --git a/scipy_distutils/__init__.py b/scipy_distutils/__init__.py index 50169952e..ce4c2d287 100644 --- a/scipy_distutils/__init__.py +++ b/scipy_distutils/__init__.py @@ -10,14 +10,7 @@ from scipy_distutils_version import scipy_distutils_version as __version__ import sys -if not sys.modules.has_key('distutils'): - # Replace distutils.ccompiler with scipy_distutils.ccompiler - assert not sys.modules.has_key('distutils.ccompiler'),\ - 'distutils has been imported before scipy_distutils' - import ccompiler - sys.modules['distutils.ccompiler'] = ccompiler - - assert not sys.modules.has_key('distutils.unixccompiler'),\ - 'cannot override distutils.unixccompiler' - import unixccompiler - sys.modules['distutils.unixccompiler'] = unixccompiler +# Must import local ccompiler ASAP in order to get +# customized CCompiler.spawn effective. +import ccompiler +import unixccompiler diff --git a/scipy_distutils/ccompiler.py b/scipy_distutils/ccompiler.py index 7d148a138..288e92c1f 100644 --- a/scipy_distutils/ccompiler.py +++ b/scipy_distutils/ccompiler.py @@ -2,12 +2,110 @@ import re import os import sys +import new from distutils.ccompiler import * from distutils import ccompiler +from distutils.sysconfig import customize_compiler import log from exec_command import exec_command +from misc_util import compiler_to_string + +# Using customized CCompiler.spawn. +def CCompiler_spawn(self, cmd, display=None): + if display is None: + display = cmd + if type(display) is type([]): display = ' '.join(display) + log.info(display) + s,o = exec_command(cmd) + if s: + if type(cmd) is type([]): + cmd = ' '.join(cmd) + raise DistutilsExecError,\ + 'Command "%s" failed with exit status %d' % (cmd, s) +CCompiler.spawn = new.instancemethod(CCompiler_spawn,None,CCompiler) + +def CCompiler_compile(self, sources, output_dir=None, macros=None, + include_dirs=None, debug=0, extra_preargs=None, + extra_postargs=None, depends=None): + from fcompiler import FCompiler + if isinstance(self, FCompiler): + display = [] + for fcomp in ['f77','f90','fix']: + fcomp = getattr(self,'compiler_'+fcomp) + if fcomp is None: + continue + display.append('%s options: "%s"' % (os.path.basename(fcomp[0]), + ' '.join(fcomp[1:]))) + display = '\n'.join(display) + else: + ccomp = self.compiler_so + display = '%s options: "%s"' % (os.path.basename(ccomp[0]), + ' '.join(ccomp[1:])) + log.info(display) + macros, objects, extra_postargs, pp_opts, build = \ + self._setup_compile(output_dir, macros, include_dirs, sources, + depends, extra_postargs) + cc_args = self._get_cc_args(pp_opts, debug, extra_preargs) + display = "compile options: '%s'" % (' '.join(cc_args)) + if extra_postargs: + display += "extra: '%s'" % (' '.join(extra_postargs)) + log.info(display) + for obj, (src, ext) in build.items(): + self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts) + + # Return *all* object filenames, not just the ones we just built. + return objects + +CCompiler.compile = new.instancemethod(CCompiler_compile,None,CCompiler) + +def CCompiler_customize_cmd(self, cmd): + """ Customize compiler using distutils command. + """ + log.info('customize %s using %s' % (self.__class__.__name__, + cmd.__class__.__name__)) + if getattr(cmd,'include_dirs',None) is not None: + self.set_include_dirs(cmd.include_dirs) + if getattr(cmd,'define',None) is not None: + for (name,value) in cmd.define: + self.define_macro(name, value) + if getattr(cmd,'undef',None) is not None: + for macro in cmd.undef: + self.undefine_macro(macro) + if getattr(cmd,'libraries',None) is not None: + self.set_libraries(self.libraries + cmd.libraries) + if getattr(cmd,'library_dirs',None) is not None: + self.set_library_dirs(self.library_dirs + cmd.library_dirs) + if getattr(cmd,'rpath',None) is not None: + self.set_runtime_library_dirs(cmd.rpath) + if getattr(cmd,'link_objects',None) is not None: + self.set_link_objects(cmd.link_objects) + self.show_customization() + return +CCompiler.customize_cmd = new.instancemethod(\ + CCompiler_customize_cmd,None,CCompiler) + +def CCompiler_show_customization(self): + for attrname in ['include_dirs','libraries','library_dirs', + 'rpath','link_objects']: + attr = getattr(self,attrname,None) + if not attr: + continue + log.info("compiler '%s' is set to %s" % (attrname,attr)) + +CCompiler.show_customization = new.instancemethod(\ + CCompiler_show_customization,None,CCompiler) + + +def CCompiler_customize(self, dist): + # See FCompiler.customize for suggested usage. + log.info('customize %s' % (self.__class__.__name__)) + customize_compiler(self) + return +CCompiler.customize = new.instancemethod(\ + CCompiler_customize,None,CCompiler) + if sys.platform == 'win32': compiler_class['mingw32'] = ('mingw32ccompiler', 'Mingw32CCompiler', @@ -21,6 +119,7 @@ if sys.platform == 'win32': ccompiler._default_compilers = (('nt', 'mingw32'),) \ + ccompiler._default_compilers + _distutils_new_compiler = new_compiler def new_compiler (plat=None, compiler=None, @@ -59,8 +158,10 @@ def new_compiler (plat=None, raise DistutilsModuleError, \ ("can't compile C/C++ code: unable to find class '%s' " + "in module '%s'") % (class_name, module_name) + compiler = klass(None, dry_run, force) print '*'*80 print klass + print compiler_to_string(compiler) print '*'*80 - return klass(None, dry_run, force) + return compiler diff --git a/scipy_distutils/command/build_clib.py b/scipy_distutils/command/build_clib.py index 0d22fb685..2ddbfc315 100644 --- a/scipy_distutils/command/build_clib.py +++ b/scipy_distutils/command/build_clib.py @@ -81,8 +81,16 @@ class build_clib(old_build_clib): raise TypeError,'Library "%s" sources contains unresolved'\ ' items (call build_src before built_clib).' % (lib_name) - old_build_clib.run(self) # sets self.compiler - log.info(misc_util.compiler_to_string(self.compiler)) + from distutils.ccompiler import new_compiler + self.compiler = new_compiler(compiler=self.compiler, + dry_run=self.dry_run, + force=self.force) + self.compiler.customize(self.distribution) + + libraries = self.libraries + self.libraries = None + self.compiler.customize_cmd(self) + self.libraries = libraries if self.have_f_sources(): from scipy_distutils.fcompiler import new_fcompiler @@ -91,17 +99,14 @@ class build_clib(old_build_clib): dry_run=self.dry_run, force=self.force) self.fcompiler.customize(self.distribution) - log.info(misc_util.compiler_to_string(self.fcompiler)) - - #XXX: C++ linker support, see build_ext.py - self.build_libraries2(self.libraries) - return + libraries = self.libraries + self.libraries = None + self.fcompiler.customize_cmd(self) + self.libraries = libraries - def build_libraries(self, libraries): - # Hold on building libraries in old_build_clib.run() - # until Fortran/C++ compilers are set. Building will be - # carried out in build_libraries2() + #XXX: C++ linker support, see build_ext.py + self.build_libraries(self.libraries) return def get_source_files(self): @@ -113,7 +118,7 @@ class build_clib(old_build_clib): filenames.extend(get_headers(get_directories(filenames))) return filenames - def build_libraries2(self, libraries): + def build_libraries(self, libraries): compiler = self.compiler fcompiler = self.fcompiler @@ -149,6 +154,7 @@ class build_clib(old_build_clib): if cxx_sources: print 'XXX: C++ linker support not implemented or tested' + objects = compiler.compile(c_sources+cxx_sources, output_dir=self.build_temp, macros=macros, diff --git a/scipy_distutils/command/build_ext.py b/scipy_distutils/command/build_ext.py index 62c247f8f..c989acc1c 100644 --- a/scipy_distutils/command/build_ext.py +++ b/scipy_distutils/command/build_ext.py @@ -50,11 +50,13 @@ class build_ext (old_build_ext): # bogus linking commands. Extensions must # explicitly specify the C libraries that they use. - save_mth = self.distribution.has_c_libraries - self.distribution.has_c_libraries = self.distribution.return_false - old_build_ext.run(self) # sets self.compiler - log.info(misc_util.compiler_to_string(self.compiler)) - self.distribution.has_c_libraries = save_mth + from distutils.ccompiler import new_compiler + self.compiler = new_compiler(compiler=self.compiler, + verbose=self.verbose, + dry_run=self.dry_run, + force=self.force) + self.compiler.customize(self.distribution) + self.compiler.customize_cmd(self) # Determine if Fortran compiler is needed. if build_clib and build_clib.fcompiler is not None: @@ -88,7 +90,6 @@ class build_ext (old_build_ext): force=self.force) self.fcompiler.customize(self.distribution) self.fcompiler.customize_cmd(self) - log.info(misc_util.compiler_to_string(self.fcompiler)) if need_cxx_compiler: c = self.compiler if c.compiler[0].find('gcc')>=0: @@ -103,17 +104,7 @@ class build_ext (old_build_ext): print 'XXX: Fix compiler_cxx for',c.__class__.__name__ # Build extensions - self.build_extensions2() - return - - def build_extensions(self): - # Hold on building extensions in old_build_ext.run() - # until Fortran/C++ compilers are set. Building will be - # carried out in build_extensions2() - return - - def build_extensions2(self): - old_build_ext.build_extensions(self) + self.build_extensions() return def swig_sources(self, sources): @@ -172,6 +163,7 @@ class build_ext (old_build_ext): if cxx_sources: old_compiler = self.compiler.compiler_so[0] self.compiler.compiler_so[0] = self.compiler.compiler_cxx[0] + c_objects += self.compiler.compile(cxx_sources, output_dir=self.build_temp, macros=macros, diff --git a/scipy_distutils/exec_command.py b/scipy_distutils/exec_command.py index b2fd0e05c..54d47fecd 100644 --- a/scipy_distutils/exec_command.py +++ b/scipy_distutils/exec_command.py @@ -115,7 +115,7 @@ def test_splitcmdline(): def find_executable(exe, path=None): """ Return full path of a executable. """ - log.info('find_executable(%r)' % exe) + log.debug('find_executable(%r)' % exe) if path is None: path = os.environ.get('PATH',os.defpath) suffices = [''] diff --git a/scipy_distutils/extension.py b/scipy_distutils/extension.py index b0ab92ec9..4f9a6df4d 100644 --- a/scipy_distutils/extension.py +++ b/scipy_distutils/extension.py @@ -6,8 +6,6 @@ modules in setup scripts. Overridden to support f2py and SourceGenerator. """ -# created 2000/05/30, Greg Ward - __revision__ = "$Id$" from distutils.extension import Extension as old_Extension diff --git a/scipy_distutils/fcompiler.py b/scipy_distutils/fcompiler.py index f9ca23ab9..7ef04a0c5 100644 --- a/scipy_distutils/fcompiler.py +++ b/scipy_distutils/fcompiler.py @@ -28,6 +28,7 @@ from distutils.sysconfig import get_config_var from scipy_distutils.command.config_compiler import config_fc import log +from misc_util import compiler_to_string from exec_command import find_executable, exec_command class FCompiler(CCompiler): @@ -304,6 +305,7 @@ class FCompiler(CCompiler): compiler instance. But not in __init__ because Distribution instance is needed for (iii) and (iv). """ + log.info('customize %s' % (self.__class__.__name__)) if dist is None: # These hooks are for testing only! from dist import Distribution @@ -408,25 +410,6 @@ class FCompiler(CCompiler): self.dump_properties() return - def customize_cmd(self, cmd): - if cmd.include_dirs is not None: - self.set_include_dirs(cmd.include_dirs) - if cmd.define is not None: - for (name,value) in cmd.define: - self.define_macro(name, value) - if cmd.undef is not None: - for macro in cmd.undef: - self.undefine_macro(macro) - if cmd.libraries is not None: - self.set_libraries(self.get_libraries() + cmd.libraries) - if cmd.library_dirs is not None: - self.set_library_dirs(self.get_library_dirs() + cmd.library_dirs) - if cmd.rpath is not None: - self.set_runtime_library_dirs(cmd.rpath) - if cmd.link_objects is not None: - self.set_link_objects(cmd.link_objects) - return - def dump_properties(self): """ Print out the attributes of a compiler instance. """ props = [] @@ -446,21 +429,8 @@ class FCompiler(CCompiler): print l return - def spawn(self, cmd): - s,o = exec_command(cmd) - if s: - if type(cmd) is type([]): - cmd = ' '.join(cmd) - raise DistutilsExecError,\ - 'Command "%s" failed with exit status %d' % (cmd, s) - ################### - def _get_cc_args(self, pp_opts, debug, before): - #XXX - #print self.__class__.__name__ + '._get_cc_args:',pp_opts, debug, before - return [] - def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts): """Compile 'src' to product 'obj'.""" if is_f_file(src): @@ -483,12 +453,13 @@ class FCompiler(CCompiler): assert self.compile_switch.strip() s_args = [self.compile_switch, src] - command = compiler + cc_args + pp_opts + s_args + o_args + extra_postargs - log.info('%s: %s' % (os.path.basename(compiler[0]) \ - + (compiler is self.compiler_fix and ':fix' or ''), - src)) + command = compiler + cc_args + s_args + o_args + extra_postargs + + display = '%s: %s' % (os.path.basename(compiler[0]) \ + + (compiler is self.compiler_fix and ':fix' or ''), + src) try: - self.spawn(command) + self.spawn(command,display=display) except DistutilsExecError, msg: raise CompileError, msg @@ -517,6 +488,9 @@ class FCompiler(CCompiler): def library_dir_option(self, dir): return "-L" + dir + def _get_cc_args(self, pp_opts, debug, extra_preargs): + return [] + if sys.version[:3]<'2.3': def compile(self, sources, output_dir=None, macros=None, include_dirs=None, debug=0, extra_preargs=None, @@ -569,8 +543,8 @@ class FCompiler(CCompiler): o_args = [self.library_switch.strip()+output_filename] ld_args = (objects + self.objects + lib_opts + o_args) - #if debug: - # ld_args[:0] = ['-g'] + if debug: + ld_args[:0] = ['-g'] if extra_preargs: ld_args[:0] = extra_preargs if extra_postargs: @@ -581,8 +555,7 @@ class FCompiler(CCompiler): else: linker = self.linker_so[:] command = linker + ld_args - log.info('%s:> %s' % (os.path.basename(linker[0]), - output_filename)) + try: self.spawn(command) except DistutilsExecError, msg: @@ -726,10 +699,12 @@ def new_fcompiler(plat=None, 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) print '*'*80 print klass + print compiler_to_string(compiler) print '*'*80 - return klass(None, dry_run, force) + return compiler def show_fcompilers(dist = None): diff --git a/scipy_distutils/mingw32ccompiler.py b/scipy_distutils/mingw32ccompiler.py index deef2f998..df7d6a74e 100644 --- a/scipy_distutils/mingw32ccompiler.py +++ b/scipy_distutils/mingw32ccompiler.py @@ -144,7 +144,6 @@ class Mingw32CCompiler(distutils.cygwinccompiler.CygwinCCompiler): strip_dir=0, output_dir=''): if output_dir is None: output_dir = '' - print 'cygiwn_output_dir:', output_dir obj_names = [] for src_name in source_filenames: # use normcase to make sure '.rc' is really '.rc' and not '.RC' diff --git a/scipy_distutils/unixccompiler.py b/scipy_distutils/unixccompiler.py index fa6a2931a..214763cef 100644 --- a/scipy_distutils/unixccompiler.py +++ b/scipy_distutils/unixccompiler.py @@ -3,99 +3,63 @@ unixccompiler - can handle very long argument lists for ar. """ import os -from distutils import unixccompiler -from distutils.errors import DistutilsExecError, LinkError -from types import StringType, NoneType +import sys +import new -from ccompiler import gen_lib_options, CCompiler -import log -from exec_command import exec_command +from distutils.errors import DistutilsExecError, LinkError, CompileError +from distutils.unixccompiler import * -class UnixCCompiler(unixccompiler.UnixCCompiler): - def _compile(self, obj, src, *args): - log.info('%s: %s' % (os.path.basename(self.compiler_so[0]),src)) - return unixccompiler.UnixCCompiler._compile(self, obj, src, *args) +import log - def spawn(self, cmd): - s,o = exec_command(cmd) - if s: - if type(cmd) is type([]): - cmd = ' '.join(cmd) - raise DistutilsExecError,\ - 'Command "%s" failed with exit status %d' % (cmd, s) +# Note that UnixCCompiler._compile appeared in Python 2.3 +def UnixCCompiler__compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts): + display = '%s: %s' % (os.path.basename(self.compiler_so[0]),src) + try: + self.spawn(self.compiler_so + cc_args + [src, '-o', obj] + + extra_postargs, display = display) + except DistutilsExecError, msg: + raise CompileError, msg +UnixCCompiler._compile = new.instancemethod(UnixCCompiler__compile, + None, + UnixCCompiler) - def create_static_lib(self, objects, output_libname, - output_dir=None, debug=0, target_lang=None): - objects, output_dir = self._fix_object_args(objects, output_dir) - - output_filename = \ - self.library_filename(output_libname, output_dir=output_dir) - - if self._need_link(objects, output_filename): - self.mkpath(os.path.dirname(output_filename)) - tmp_objects = objects + self.objects - log.info('%s:> %s' % (os.path.basename(self.archiver[0]), - output_filename)) - while tmp_objects: - objects = tmp_objects[:50] - tmp_objects = tmp_objects[50:] - self.spawn(self.archiver + - [output_filename] + - objects) - - # Not many Unices required ranlib anymore -- SunOS 4.x is, I - # think the only major Unix that does. Maybe we need some - # platform intelligence here to skip ranlib if it's not - # needed -- or maybe Python's configure script took care of - # it for us, hence the check for leading colon. - if self.ranlib: - log.info('%s:@ %s' % (os.path.basename(self.ranlib[0]), - output_filename)) - try: - self.spawn(self.ranlib + [output_filename]) - except DistutilsExecError, msg: - raise LibError, msg - else: - log.debug("skipping %s (up-to-date)", output_filename) - def link(self, target_desc, objects, - output_filename, output_dir=None, libraries=None, - library_dirs=None, runtime_library_dirs=None, - export_symbols=None, debug=0, extra_preargs=None, - extra_postargs=None, build_temp=None, target_lang=None): - objects, output_dir = self._fix_object_args(objects, output_dir) - libraries, library_dirs, runtime_library_dirs = \ - self._fix_lib_args(libraries, library_dirs, runtime_library_dirs) +def UnixCCompile_create_static_lib(self, objects, output_libname, + output_dir=None, debug=0, target_lang=None): + objects, output_dir = self._fix_object_args(objects, output_dir) - lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, - libraries) - if type(output_dir) not in (StringType, NoneType): - raise TypeError, "'output_dir' must be a string or None" - if output_dir is not None: - output_filename = os.path.join(output_dir, output_filename) + output_filename = \ + self.library_filename(output_libname, output_dir=output_dir) + + if self._need_link(objects, output_filename): + self.mkpath(os.path.dirname(output_filename)) + tmp_objects = objects + self.objects + while tmp_objects: + objects = tmp_objects[:50] + tmp_objects = tmp_objects[50:] + display = '%s: adding %d object files to %s' % (os.path.basename(self.archiver[0]), + len(objects),output_filename) + self.spawn(self.archiver + [output_filename] + objects, + display = display) - if self._need_link(objects, output_filename): - ld_args = (objects + self.objects + - lib_opts + ['-o', output_filename]) - if debug: - ld_args[:0] = ['-g'] - if extra_preargs: - ld_args[:0] = extra_preargs - if extra_postargs: - ld_args.extend(extra_postargs) - self.mkpath(os.path.dirname(output_filename)) + # Not many Unices required ranlib anymore -- SunOS 4.x is, I + # think the only major Unix that does. Maybe we need some + # platform intelligence here to skip ranlib if it's not + # needed -- or maybe Python's configure script took care of + # it for us, hence the check for leading colon. + if self.ranlib: + display = '%s:@ %s' % (os.path.basename(self.ranlib[0]), + output_filename) try: - if target_desc == CCompiler.EXECUTABLE: - linker = self.linker_exe[:] - else: - linker = self.linker_so[:] - if target_lang == "c++" and self.compiler_cxx: - linker[0] = self.compiler_cxx[0] - log.info('%s:> %s' % (os.path.basename(linker[0]), - output_filename)) - self.spawn(linker + ld_args) + self.spawn(self.ranlib + [output_filename], + display = display) except DistutilsExecError, msg: - raise LinkError, msg - else: - log.debug("skipping %s (up-to-date)", output_filename) + raise LibError, msg + else: + log.debug("skipping %s (up-to-date)", output_filename) + return + +UnixCCompiler.create_static_lib = \ + new.instancemethod(UnixCCompile_create_static_lib, + None,UnixCCompiler) |