unixccompiler.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. """
  2. unixccompiler - can handle very long argument lists for ar.
  3. """
  4. from __future__ import division, absolute_import, print_function
  5. import os
  6. from distutils.errors import DistutilsExecError, CompileError
  7. from distutils.unixccompiler import *
  8. from numpy.distutils.ccompiler import replace_method
  9. from numpy.distutils.compat import get_exception
  10. from numpy.distutils.misc_util import _commandline_dep_string
  11. if sys.version_info[0] < 3:
  12. from . import log
  13. else:
  14. from numpy.distutils import log
  15. # Note that UnixCCompiler._compile appeared in Python 2.3
  16. def UnixCCompiler__compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
  17. """Compile a single source files with a Unix-style compiler."""
  18. # HP ad-hoc fix, see ticket 1383
  19. ccomp = self.compiler_so
  20. if ccomp[0] == 'aCC':
  21. # remove flags that will trigger ANSI-C mode for aCC
  22. if '-Ae' in ccomp:
  23. ccomp.remove('-Ae')
  24. if '-Aa' in ccomp:
  25. ccomp.remove('-Aa')
  26. # add flags for (almost) sane C++ handling
  27. ccomp += ['-AA']
  28. self.compiler_so = ccomp
  29. # ensure OPT environment variable is read
  30. if 'OPT' in os.environ:
  31. from distutils.sysconfig import get_config_vars
  32. opt = " ".join(os.environ['OPT'].split())
  33. gcv_opt = " ".join(get_config_vars('OPT')[0].split())
  34. ccomp_s = " ".join(self.compiler_so)
  35. if opt not in ccomp_s:
  36. ccomp_s = ccomp_s.replace(gcv_opt, opt)
  37. self.compiler_so = ccomp_s.split()
  38. llink_s = " ".join(self.linker_so)
  39. if opt not in llink_s:
  40. self.linker_so = llink_s.split() + opt.split()
  41. display = '%s: %s' % (os.path.basename(self.compiler_so[0]), src)
  42. # gcc style automatic dependencies, outputs a makefile (-MF) that lists
  43. # all headers needed by a c file as a side effect of compilation (-MMD)
  44. if getattr(self, '_auto_depends', False):
  45. deps = ['-MMD', '-MF', obj + '.d']
  46. else:
  47. deps = []
  48. try:
  49. self.spawn(self.compiler_so + cc_args + [src, '-o', obj] + deps +
  50. extra_postargs, display = display)
  51. except DistutilsExecError:
  52. msg = str(get_exception())
  53. raise CompileError(msg)
  54. # add commandline flags to dependency file
  55. if deps:
  56. with open(obj + '.d', 'a') as f:
  57. f.write(_commandline_dep_string(cc_args, extra_postargs, pp_opts))
  58. replace_method(UnixCCompiler, '_compile', UnixCCompiler__compile)
  59. def UnixCCompiler_create_static_lib(self, objects, output_libname,
  60. output_dir=None, debug=0, target_lang=None):
  61. """
  62. Build a static library in a separate sub-process.
  63. Parameters
  64. ----------
  65. objects : list or tuple of str
  66. List of paths to object files used to build the static library.
  67. output_libname : str
  68. The library name as an absolute or relative (if `output_dir` is used)
  69. path.
  70. output_dir : str, optional
  71. The path to the output directory. Default is None, in which case
  72. the ``output_dir`` attribute of the UnixCCompiler instance.
  73. debug : bool, optional
  74. This parameter is not used.
  75. target_lang : str, optional
  76. This parameter is not used.
  77. Returns
  78. -------
  79. None
  80. """
  81. objects, output_dir = self._fix_object_args(objects, output_dir)
  82. output_filename = \
  83. self.library_filename(output_libname, output_dir=output_dir)
  84. if self._need_link(objects, output_filename):
  85. try:
  86. # previous .a may be screwed up; best to remove it first
  87. # and recreate.
  88. # Also, ar on OS X doesn't handle updating universal archives
  89. os.unlink(output_filename)
  90. except (IOError, OSError):
  91. pass
  92. self.mkpath(os.path.dirname(output_filename))
  93. tmp_objects = objects + self.objects
  94. while tmp_objects:
  95. objects = tmp_objects[:50]
  96. tmp_objects = tmp_objects[50:]
  97. display = '%s: adding %d object files to %s' % (
  98. os.path.basename(self.archiver[0]),
  99. len(objects), output_filename)
  100. self.spawn(self.archiver + [output_filename] + objects,
  101. display = display)
  102. # Not many Unices required ranlib anymore -- SunOS 4.x is, I
  103. # think the only major Unix that does. Maybe we need some
  104. # platform intelligence here to skip ranlib if it's not
  105. # needed -- or maybe Python's configure script took care of
  106. # it for us, hence the check for leading colon.
  107. if self.ranlib:
  108. display = '%s:@ %s' % (os.path.basename(self.ranlib[0]),
  109. output_filename)
  110. try:
  111. self.spawn(self.ranlib + [output_filename],
  112. display = display)
  113. except DistutilsExecError:
  114. msg = str(get_exception())
  115. raise LibError(msg)
  116. else:
  117. log.debug("skipping %s (up-to-date)", output_filename)
  118. return
  119. replace_method(UnixCCompiler, 'create_static_lib',
  120. UnixCCompiler_create_static_lib)