142 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			142 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| 
								 | 
							
								"""
							 | 
						||
| 
								 | 
							
								unixccompiler - can handle very long argument lists for ar.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								"""
							 | 
						||
| 
								 | 
							
								import os
							 | 
						||
| 
								 | 
							
								import sys
							 | 
						||
| 
								 | 
							
								import subprocess
							 | 
						||
| 
								 | 
							
								import shlex
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								from distutils.errors import CompileError, DistutilsExecError, LibError
							 | 
						||
| 
								 | 
							
								from distutils.unixccompiler import UnixCCompiler
							 | 
						||
| 
								 | 
							
								from numpy.distutils.ccompiler import replace_method
							 | 
						||
| 
								 | 
							
								from numpy.distutils.misc_util import _commandline_dep_string
							 | 
						||
| 
								 | 
							
								from numpy.distutils import log
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Note that UnixCCompiler._compile appeared in Python 2.3
							 | 
						||
| 
								 | 
							
								def UnixCCompiler__compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
							 | 
						||
| 
								 | 
							
								    """Compile a single source files with a Unix-style compiler."""
							 | 
						||
| 
								 | 
							
								    # HP ad-hoc fix, see ticket 1383
							 | 
						||
| 
								 | 
							
								    ccomp = self.compiler_so
							 | 
						||
| 
								 | 
							
								    if ccomp[0] == 'aCC':
							 | 
						||
| 
								 | 
							
								        # remove flags that will trigger ANSI-C mode for aCC
							 | 
						||
| 
								 | 
							
								        if '-Ae' in ccomp:
							 | 
						||
| 
								 | 
							
								            ccomp.remove('-Ae')
							 | 
						||
| 
								 | 
							
								        if '-Aa' in ccomp:
							 | 
						||
| 
								 | 
							
								            ccomp.remove('-Aa')
							 | 
						||
| 
								 | 
							
								        # add flags for (almost) sane C++ handling
							 | 
						||
| 
								 | 
							
								        ccomp += ['-AA']
							 | 
						||
| 
								 | 
							
								        self.compiler_so = ccomp
							 | 
						||
| 
								 | 
							
								    # ensure OPT environment variable is read
							 | 
						||
| 
								 | 
							
								    if 'OPT' in os.environ:
							 | 
						||
| 
								 | 
							
								        # XXX who uses this?
							 | 
						||
| 
								 | 
							
								        from sysconfig import get_config_vars
							 | 
						||
| 
								 | 
							
								        opt = shlex.join(shlex.split(os.environ['OPT']))
							 | 
						||
| 
								 | 
							
								        gcv_opt = shlex.join(shlex.split(get_config_vars('OPT')[0]))
							 | 
						||
| 
								 | 
							
								        ccomp_s = shlex.join(self.compiler_so)
							 | 
						||
| 
								 | 
							
								        if opt not in ccomp_s:
							 | 
						||
| 
								 | 
							
								            ccomp_s = ccomp_s.replace(gcv_opt, opt)
							 | 
						||
| 
								 | 
							
								            self.compiler_so = shlex.split(ccomp_s)
							 | 
						||
| 
								 | 
							
								        llink_s = shlex.join(self.linker_so)
							 | 
						||
| 
								 | 
							
								        if opt not in llink_s:
							 | 
						||
| 
								 | 
							
								            self.linker_so = self.linker_so + shlex.split(opt)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    display = '%s: %s' % (os.path.basename(self.compiler_so[0]), src)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # gcc style automatic dependencies, outputs a makefile (-MF) that lists
							 | 
						||
| 
								 | 
							
								    # all headers needed by a c file as a side effect of compilation (-MMD)
							 | 
						||
| 
								 | 
							
								    if getattr(self, '_auto_depends', False):
							 | 
						||
| 
								 | 
							
								        deps = ['-MMD', '-MF', obj + '.d']
							 | 
						||
| 
								 | 
							
								    else:
							 | 
						||
| 
								 | 
							
								        deps = []
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    try:
							 | 
						||
| 
								 | 
							
								        self.spawn(self.compiler_so + cc_args + [src, '-o', obj] + deps +
							 | 
						||
| 
								 | 
							
								                   extra_postargs, display = display)
							 | 
						||
| 
								 | 
							
								    except DistutilsExecError as e:
							 | 
						||
| 
								 | 
							
								        msg = str(e)
							 | 
						||
| 
								 | 
							
								        raise CompileError(msg) from None
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # add commandline flags to dependency file
							 | 
						||
| 
								 | 
							
								    if deps:
							 | 
						||
| 
								 | 
							
								        # After running the compiler, the file created will be in EBCDIC
							 | 
						||
| 
								 | 
							
								        # but will not be tagged as such. This tags it so the file does not
							 | 
						||
| 
								 | 
							
								        # have multiple different encodings being written to it
							 | 
						||
| 
								 | 
							
								        if sys.platform == 'zos':
							 | 
						||
| 
								 | 
							
								            subprocess.check_output(['chtag', '-tc', 'IBM1047', obj + '.d'])
							 | 
						||
| 
								 | 
							
								        with open(obj + '.d', 'a') as f:
							 | 
						||
| 
								 | 
							
								            f.write(_commandline_dep_string(cc_args, extra_postargs, pp_opts))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								replace_method(UnixCCompiler, '_compile', UnixCCompiler__compile)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def UnixCCompiler_create_static_lib(self, objects, output_libname,
							 | 
						||
| 
								 | 
							
								                                    output_dir=None, debug=0, target_lang=None):
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    Build a static library in a separate sub-process.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Parameters
							 | 
						||
| 
								 | 
							
								    ----------
							 | 
						||
| 
								 | 
							
								    objects : list or tuple of str
							 | 
						||
| 
								 | 
							
								        List of paths to object files used to build the static library.
							 | 
						||
| 
								 | 
							
								    output_libname : str
							 | 
						||
| 
								 | 
							
								        The library name as an absolute or relative (if `output_dir` is used)
							 | 
						||
| 
								 | 
							
								        path.
							 | 
						||
| 
								 | 
							
								    output_dir : str, optional
							 | 
						||
| 
								 | 
							
								        The path to the output directory. Default is None, in which case
							 | 
						||
| 
								 | 
							
								        the ``output_dir`` attribute of the UnixCCompiler instance.
							 | 
						||
| 
								 | 
							
								    debug : bool, optional
							 | 
						||
| 
								 | 
							
								        This parameter is not used.
							 | 
						||
| 
								 | 
							
								    target_lang : str, optional
							 | 
						||
| 
								 | 
							
								        This parameter is not used.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Returns
							 | 
						||
| 
								 | 
							
								    -------
							 | 
						||
| 
								 | 
							
								    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):
							 | 
						||
| 
								 | 
							
								        try:
							 | 
						||
| 
								 | 
							
								            # previous .a may be screwed up; best to remove it first
							 | 
						||
| 
								 | 
							
								            # and recreate.
							 | 
						||
| 
								 | 
							
								            # Also, ar on OS X doesn't handle updating universal archives
							 | 
						||
| 
								 | 
							
								            os.unlink(output_filename)
							 | 
						||
| 
								 | 
							
								        except OSError:
							 | 
						||
| 
								 | 
							
								            pass
							 | 
						||
| 
								 | 
							
								        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)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # 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:
							 | 
						||
| 
								 | 
							
								                self.spawn(self.ranlib + [output_filename],
							 | 
						||
| 
								 | 
							
								                           display = display)
							 | 
						||
| 
								 | 
							
								            except DistutilsExecError as e:
							 | 
						||
| 
								 | 
							
								                msg = str(e)
							 | 
						||
| 
								 | 
							
								                raise LibError(msg) from None
							 | 
						||
| 
								 | 
							
								    else:
							 | 
						||
| 
								 | 
							
								        log.debug("skipping %s (up-to-date)", output_filename)
							 | 
						||
| 
								 | 
							
								    return
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								replace_method(UnixCCompiler, 'create_static_lib',
							 | 
						||
| 
								 | 
							
								               UnixCCompiler_create_static_lib)
							 |