ccompiler.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805
  1. from __future__ import division, absolute_import, print_function
  2. import os
  3. import re
  4. import sys
  5. import types
  6. import shlex
  7. import time
  8. import subprocess
  9. from copy import copy
  10. from distutils import ccompiler
  11. from distutils.ccompiler import *
  12. from distutils.errors import DistutilsExecError, DistutilsModuleError, \
  13. DistutilsPlatformError, CompileError
  14. from distutils.sysconfig import customize_compiler
  15. from distutils.version import LooseVersion
  16. from numpy.distutils import log
  17. from numpy.distutils.compat import get_exception
  18. from numpy.distutils.exec_command import (
  19. filepath_from_subprocess_output, forward_bytes_to_stdout
  20. )
  21. from numpy.distutils.misc_util import cyg2win32, is_sequence, mingw32, \
  22. get_num_build_jobs, \
  23. _commandline_dep_string
  24. # globals for parallel build management
  25. try:
  26. import threading
  27. except ImportError:
  28. import dummy_threading as threading
  29. _job_semaphore = None
  30. _global_lock = threading.Lock()
  31. _processing_files = set()
  32. def _needs_build(obj, cc_args, extra_postargs, pp_opts):
  33. """
  34. Check if an objects needs to be rebuild based on its dependencies
  35. Parameters
  36. ----------
  37. obj : str
  38. object file
  39. Returns
  40. -------
  41. bool
  42. """
  43. # defined in unixcompiler.py
  44. dep_file = obj + '.d'
  45. if not os.path.exists(dep_file):
  46. return True
  47. # dep_file is a makefile containing 'object: dependencies'
  48. # formatted like posix shell (spaces escaped, \ line continuations)
  49. # the last line contains the compiler commandline arguments as some
  50. # projects may compile an extension multiple times with different
  51. # arguments
  52. with open(dep_file, "r") as f:
  53. lines = f.readlines()
  54. cmdline =_commandline_dep_string(cc_args, extra_postargs, pp_opts)
  55. last_cmdline = lines[-1]
  56. if last_cmdline != cmdline:
  57. return True
  58. contents = ''.join(lines[:-1])
  59. deps = [x for x in shlex.split(contents, posix=True)
  60. if x != "\n" and not x.endswith(":")]
  61. try:
  62. t_obj = os.stat(obj).st_mtime
  63. # check if any of the dependencies is newer than the object
  64. # the dependencies includes the source used to create the object
  65. for f in deps:
  66. if os.stat(f).st_mtime > t_obj:
  67. return True
  68. except OSError:
  69. # no object counts as newer (shouldn't happen if dep_file exists)
  70. return True
  71. return False
  72. def replace_method(klass, method_name, func):
  73. if sys.version_info[0] < 3:
  74. m = types.MethodType(func, None, klass)
  75. else:
  76. # Py3k does not have unbound method anymore, MethodType does not work
  77. m = lambda self, *args, **kw: func(self, *args, **kw)
  78. setattr(klass, method_name, m)
  79. ######################################################################
  80. ## Method that subclasses may redefine. But don't call this method,
  81. ## it i private to CCompiler class and may return unexpected
  82. ## results if used elsewhere. So, you have been warned..
  83. def CCompiler_find_executables(self):
  84. """
  85. Does nothing here, but is called by the get_version method and can be
  86. overridden by subclasses. In particular it is redefined in the `FCompiler`
  87. class where more documentation can be found.
  88. """
  89. pass
  90. replace_method(CCompiler, 'find_executables', CCompiler_find_executables)
  91. # Using customized CCompiler.spawn.
  92. def CCompiler_spawn(self, cmd, display=None):
  93. """
  94. Execute a command in a sub-process.
  95. Parameters
  96. ----------
  97. cmd : str
  98. The command to execute.
  99. display : str or sequence of str, optional
  100. The text to add to the log file kept by `numpy.distutils`.
  101. If not given, `display` is equal to `cmd`.
  102. Returns
  103. -------
  104. None
  105. Raises
  106. ------
  107. DistutilsExecError
  108. If the command failed, i.e. the exit status was not 0.
  109. """
  110. if display is None:
  111. display = cmd
  112. if is_sequence(display):
  113. display = ' '.join(list(display))
  114. log.info(display)
  115. try:
  116. if self.verbose:
  117. subprocess.check_output(cmd)
  118. else:
  119. subprocess.check_output(cmd, stderr=subprocess.STDOUT)
  120. except subprocess.CalledProcessError as exc:
  121. o = exc.output
  122. s = exc.returncode
  123. except OSError:
  124. # OSError doesn't have the same hooks for the exception
  125. # output, but exec_command() historically would use an
  126. # empty string for EnvironmentError (base class for
  127. # OSError)
  128. o = b''
  129. # status previously used by exec_command() for parent
  130. # of OSError
  131. s = 127
  132. else:
  133. # use a convenience return here so that any kind of
  134. # caught exception will execute the default code after the
  135. # try / except block, which handles various exceptions
  136. return None
  137. if is_sequence(cmd):
  138. cmd = ' '.join(list(cmd))
  139. if self.verbose:
  140. forward_bytes_to_stdout(o)
  141. if re.search(b'Too many open files', o):
  142. msg = '\nTry rerunning setup command until build succeeds.'
  143. else:
  144. msg = ''
  145. raise DistutilsExecError('Command "%s" failed with exit status %d%s' %
  146. (cmd, s, msg))
  147. replace_method(CCompiler, 'spawn', CCompiler_spawn)
  148. def CCompiler_object_filenames(self, source_filenames, strip_dir=0, output_dir=''):
  149. """
  150. Return the name of the object files for the given source files.
  151. Parameters
  152. ----------
  153. source_filenames : list of str
  154. The list of paths to source files. Paths can be either relative or
  155. absolute, this is handled transparently.
  156. strip_dir : bool, optional
  157. Whether to strip the directory from the returned paths. If True,
  158. the file name prepended by `output_dir` is returned. Default is False.
  159. output_dir : str, optional
  160. If given, this path is prepended to the returned paths to the
  161. object files.
  162. Returns
  163. -------
  164. obj_names : list of str
  165. The list of paths to the object files corresponding to the source
  166. files in `source_filenames`.
  167. """
  168. if output_dir is None:
  169. output_dir = ''
  170. obj_names = []
  171. for src_name in source_filenames:
  172. base, ext = os.path.splitext(os.path.normpath(src_name))
  173. base = os.path.splitdrive(base)[1] # Chop off the drive
  174. base = base[os.path.isabs(base):] # If abs, chop off leading /
  175. if base.startswith('..'):
  176. # Resolve starting relative path components, middle ones
  177. # (if any) have been handled by os.path.normpath above.
  178. i = base.rfind('..')+2
  179. d = base[:i]
  180. d = os.path.basename(os.path.abspath(d))
  181. base = d + base[i:]
  182. if ext not in self.src_extensions:
  183. raise UnknownFileError("unknown file type '%s' (from '%s')" % (ext, src_name))
  184. if strip_dir:
  185. base = os.path.basename(base)
  186. obj_name = os.path.join(output_dir, base + self.obj_extension)
  187. obj_names.append(obj_name)
  188. return obj_names
  189. replace_method(CCompiler, 'object_filenames', CCompiler_object_filenames)
  190. def CCompiler_compile(self, sources, output_dir=None, macros=None,
  191. include_dirs=None, debug=0, extra_preargs=None,
  192. extra_postargs=None, depends=None):
  193. """
  194. Compile one or more source files.
  195. Please refer to the Python distutils API reference for more details.
  196. Parameters
  197. ----------
  198. sources : list of str
  199. A list of filenames
  200. output_dir : str, optional
  201. Path to the output directory.
  202. macros : list of tuples
  203. A list of macro definitions.
  204. include_dirs : list of str, optional
  205. The directories to add to the default include file search path for
  206. this compilation only.
  207. debug : bool, optional
  208. Whether or not to output debug symbols in or alongside the object
  209. file(s).
  210. extra_preargs, extra_postargs : ?
  211. Extra pre- and post-arguments.
  212. depends : list of str, optional
  213. A list of file names that all targets depend on.
  214. Returns
  215. -------
  216. objects : list of str
  217. A list of object file names, one per source file `sources`.
  218. Raises
  219. ------
  220. CompileError
  221. If compilation fails.
  222. """
  223. # This method is effective only with Python >=2.3 distutils.
  224. # Any changes here should be applied also to fcompiler.compile
  225. # method to support pre Python 2.3 distutils.
  226. global _job_semaphore
  227. jobs = get_num_build_jobs()
  228. # setup semaphore to not exceed number of compile jobs when parallelized at
  229. # extension level (python >= 3.5)
  230. with _global_lock:
  231. if _job_semaphore is None:
  232. _job_semaphore = threading.Semaphore(jobs)
  233. if not sources:
  234. return []
  235. # FIXME:RELATIVE_IMPORT
  236. if sys.version_info[0] < 3:
  237. from .fcompiler import FCompiler, is_f_file, has_f90_header
  238. else:
  239. from numpy.distutils.fcompiler import (FCompiler, is_f_file,
  240. has_f90_header)
  241. if isinstance(self, FCompiler):
  242. display = []
  243. for fc in ['f77', 'f90', 'fix']:
  244. fcomp = getattr(self, 'compiler_'+fc)
  245. if fcomp is None:
  246. continue
  247. display.append("Fortran %s compiler: %s" % (fc, ' '.join(fcomp)))
  248. display = '\n'.join(display)
  249. else:
  250. ccomp = self.compiler_so
  251. display = "C compiler: %s\n" % (' '.join(ccomp),)
  252. log.info(display)
  253. macros, objects, extra_postargs, pp_opts, build = \
  254. self._setup_compile(output_dir, macros, include_dirs, sources,
  255. depends, extra_postargs)
  256. cc_args = self._get_cc_args(pp_opts, debug, extra_preargs)
  257. display = "compile options: '%s'" % (' '.join(cc_args))
  258. if extra_postargs:
  259. display += "\nextra options: '%s'" % (' '.join(extra_postargs))
  260. log.info(display)
  261. def single_compile(args):
  262. obj, (src, ext) = args
  263. if not _needs_build(obj, cc_args, extra_postargs, pp_opts):
  264. return
  265. # check if we are currently already processing the same object
  266. # happens when using the same source in multiple extensions
  267. while True:
  268. # need explicit lock as there is no atomic check and add with GIL
  269. with _global_lock:
  270. # file not being worked on, start working
  271. if obj not in _processing_files:
  272. _processing_files.add(obj)
  273. break
  274. # wait for the processing to end
  275. time.sleep(0.1)
  276. try:
  277. # retrieve slot from our #job semaphore and build
  278. with _job_semaphore:
  279. self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)
  280. finally:
  281. # register being done processing
  282. with _global_lock:
  283. _processing_files.remove(obj)
  284. if isinstance(self, FCompiler):
  285. objects_to_build = list(build.keys())
  286. f77_objects, other_objects = [], []
  287. for obj in objects:
  288. if obj in objects_to_build:
  289. src, ext = build[obj]
  290. if self.compiler_type=='absoft':
  291. obj = cyg2win32(obj)
  292. src = cyg2win32(src)
  293. if is_f_file(src) and not has_f90_header(src):
  294. f77_objects.append((obj, (src, ext)))
  295. else:
  296. other_objects.append((obj, (src, ext)))
  297. # f77 objects can be built in parallel
  298. build_items = f77_objects
  299. # build f90 modules serial, module files are generated during
  300. # compilation and may be used by files later in the list so the
  301. # ordering is important
  302. for o in other_objects:
  303. single_compile(o)
  304. else:
  305. build_items = build.items()
  306. if len(build) > 1 and jobs > 1:
  307. # build parallel
  308. import multiprocessing.pool
  309. pool = multiprocessing.pool.ThreadPool(jobs)
  310. pool.map(single_compile, build_items)
  311. pool.close()
  312. else:
  313. # build serial
  314. for o in build_items:
  315. single_compile(o)
  316. # Return *all* object filenames, not just the ones we just built.
  317. return objects
  318. replace_method(CCompiler, 'compile', CCompiler_compile)
  319. def CCompiler_customize_cmd(self, cmd, ignore=()):
  320. """
  321. Customize compiler using distutils command.
  322. Parameters
  323. ----------
  324. cmd : class instance
  325. An instance inheriting from `distutils.cmd.Command`.
  326. ignore : sequence of str, optional
  327. List of `CCompiler` commands (without ``'set_'``) that should not be
  328. altered. Strings that are checked for are:
  329. ``('include_dirs', 'define', 'undef', 'libraries', 'library_dirs',
  330. 'rpath', 'link_objects')``.
  331. Returns
  332. -------
  333. None
  334. """
  335. log.info('customize %s using %s' % (self.__class__.__name__,
  336. cmd.__class__.__name__))
  337. def allow(attr):
  338. return getattr(cmd, attr, None) is not None and attr not in ignore
  339. if allow('include_dirs'):
  340. self.set_include_dirs(cmd.include_dirs)
  341. if allow('define'):
  342. for (name, value) in cmd.define:
  343. self.define_macro(name, value)
  344. if allow('undef'):
  345. for macro in cmd.undef:
  346. self.undefine_macro(macro)
  347. if allow('libraries'):
  348. self.set_libraries(self.libraries + cmd.libraries)
  349. if allow('library_dirs'):
  350. self.set_library_dirs(self.library_dirs + cmd.library_dirs)
  351. if allow('rpath'):
  352. self.set_runtime_library_dirs(cmd.rpath)
  353. if allow('link_objects'):
  354. self.set_link_objects(cmd.link_objects)
  355. replace_method(CCompiler, 'customize_cmd', CCompiler_customize_cmd)
  356. def _compiler_to_string(compiler):
  357. props = []
  358. mx = 0
  359. keys = list(compiler.executables.keys())
  360. for key in ['version', 'libraries', 'library_dirs',
  361. 'object_switch', 'compile_switch',
  362. 'include_dirs', 'define', 'undef', 'rpath', 'link_objects']:
  363. if key not in keys:
  364. keys.append(key)
  365. for key in keys:
  366. if hasattr(compiler, key):
  367. v = getattr(compiler, key)
  368. mx = max(mx, len(key))
  369. props.append((key, repr(v)))
  370. fmt = '%-' + repr(mx+1) + 's = %s'
  371. lines = [fmt % prop for prop in props]
  372. return '\n'.join(lines)
  373. def CCompiler_show_customization(self):
  374. """
  375. Print the compiler customizations to stdout.
  376. Parameters
  377. ----------
  378. None
  379. Returns
  380. -------
  381. None
  382. Notes
  383. -----
  384. Printing is only done if the distutils log threshold is < 2.
  385. """
  386. if 0:
  387. for attrname in ['include_dirs', 'define', 'undef',
  388. 'libraries', 'library_dirs',
  389. 'rpath', 'link_objects']:
  390. attr = getattr(self, attrname, None)
  391. if not attr:
  392. continue
  393. log.info("compiler '%s' is set to %s" % (attrname, attr))
  394. try:
  395. self.get_version()
  396. except Exception:
  397. pass
  398. if log._global_log.threshold<2:
  399. print('*'*80)
  400. print(self.__class__)
  401. print(_compiler_to_string(self))
  402. print('*'*80)
  403. replace_method(CCompiler, 'show_customization', CCompiler_show_customization)
  404. def CCompiler_customize(self, dist, need_cxx=0):
  405. """
  406. Do any platform-specific customization of a compiler instance.
  407. This method calls `distutils.sysconfig.customize_compiler` for
  408. platform-specific customization, as well as optionally remove a flag
  409. to suppress spurious warnings in case C++ code is being compiled.
  410. Parameters
  411. ----------
  412. dist : object
  413. This parameter is not used for anything.
  414. need_cxx : bool, optional
  415. Whether or not C++ has to be compiled. If so (True), the
  416. ``"-Wstrict-prototypes"`` option is removed to prevent spurious
  417. warnings. Default is False.
  418. Returns
  419. -------
  420. None
  421. Notes
  422. -----
  423. All the default options used by distutils can be extracted with::
  424. from distutils import sysconfig
  425. sysconfig.get_config_vars('CC', 'CXX', 'OPT', 'BASECFLAGS',
  426. 'CCSHARED', 'LDSHARED', 'SO')
  427. """
  428. # See FCompiler.customize for suggested usage.
  429. log.info('customize %s' % (self.__class__.__name__))
  430. customize_compiler(self)
  431. if need_cxx:
  432. # In general, distutils uses -Wstrict-prototypes, but this option is
  433. # not valid for C++ code, only for C. Remove it if it's there to
  434. # avoid a spurious warning on every compilation.
  435. try:
  436. self.compiler_so.remove('-Wstrict-prototypes')
  437. except (AttributeError, ValueError):
  438. pass
  439. if hasattr(self, 'compiler') and 'cc' in self.compiler[0]:
  440. if not self.compiler_cxx:
  441. if self.compiler[0].startswith('gcc'):
  442. a, b = 'gcc', 'g++'
  443. else:
  444. a, b = 'cc', 'c++'
  445. self.compiler_cxx = [self.compiler[0].replace(a, b)]\
  446. + self.compiler[1:]
  447. else:
  448. if hasattr(self, 'compiler'):
  449. log.warn("#### %s #######" % (self.compiler,))
  450. if not hasattr(self, 'compiler_cxx'):
  451. log.warn('Missing compiler_cxx fix for ' + self.__class__.__name__)
  452. # check if compiler supports gcc style automatic dependencies
  453. # run on every extension so skip for known good compilers
  454. if hasattr(self, 'compiler') and ('gcc' in self.compiler[0] or
  455. 'g++' in self.compiler[0] or
  456. 'clang' in self.compiler[0]):
  457. self._auto_depends = True
  458. elif os.name == 'posix':
  459. import tempfile
  460. import shutil
  461. tmpdir = tempfile.mkdtemp()
  462. try:
  463. fn = os.path.join(tmpdir, "file.c")
  464. with open(fn, "w") as f:
  465. f.write("int a;\n")
  466. self.compile([fn], output_dir=tmpdir,
  467. extra_preargs=['-MMD', '-MF', fn + '.d'])
  468. self._auto_depends = True
  469. except CompileError:
  470. self._auto_depends = False
  471. finally:
  472. shutil.rmtree(tmpdir)
  473. return
  474. replace_method(CCompiler, 'customize', CCompiler_customize)
  475. def simple_version_match(pat=r'[-.\d]+', ignore='', start=''):
  476. """
  477. Simple matching of version numbers, for use in CCompiler and FCompiler.
  478. Parameters
  479. ----------
  480. pat : str, optional
  481. A regular expression matching version numbers.
  482. Default is ``r'[-.\\d]+'``.
  483. ignore : str, optional
  484. A regular expression matching patterns to skip.
  485. Default is ``''``, in which case nothing is skipped.
  486. start : str, optional
  487. A regular expression matching the start of where to start looking
  488. for version numbers.
  489. Default is ``''``, in which case searching is started at the
  490. beginning of the version string given to `matcher`.
  491. Returns
  492. -------
  493. matcher : callable
  494. A function that is appropriate to use as the ``.version_match``
  495. attribute of a `CCompiler` class. `matcher` takes a single parameter,
  496. a version string.
  497. """
  498. def matcher(self, version_string):
  499. # version string may appear in the second line, so getting rid
  500. # of new lines:
  501. version_string = version_string.replace('\n', ' ')
  502. pos = 0
  503. if start:
  504. m = re.match(start, version_string)
  505. if not m:
  506. return None
  507. pos = m.end()
  508. while True:
  509. m = re.search(pat, version_string[pos:])
  510. if not m:
  511. return None
  512. if ignore and re.match(ignore, m.group(0)):
  513. pos = m.end()
  514. continue
  515. break
  516. return m.group(0)
  517. return matcher
  518. def CCompiler_get_version(self, force=False, ok_status=[0]):
  519. """
  520. Return compiler version, or None if compiler is not available.
  521. Parameters
  522. ----------
  523. force : bool, optional
  524. If True, force a new determination of the version, even if the
  525. compiler already has a version attribute. Default is False.
  526. ok_status : list of int, optional
  527. The list of status values returned by the version look-up process
  528. for which a version string is returned. If the status value is not
  529. in `ok_status`, None is returned. Default is ``[0]``.
  530. Returns
  531. -------
  532. version : str or None
  533. Version string, in the format of `distutils.version.LooseVersion`.
  534. """
  535. if not force and hasattr(self, 'version'):
  536. return self.version
  537. self.find_executables()
  538. try:
  539. version_cmd = self.version_cmd
  540. except AttributeError:
  541. return None
  542. if not version_cmd or not version_cmd[0]:
  543. return None
  544. try:
  545. matcher = self.version_match
  546. except AttributeError:
  547. try:
  548. pat = self.version_pattern
  549. except AttributeError:
  550. return None
  551. def matcher(version_string):
  552. m = re.match(pat, version_string)
  553. if not m:
  554. return None
  555. version = m.group('version')
  556. return version
  557. try:
  558. output = subprocess.check_output(version_cmd, stderr=subprocess.STDOUT)
  559. except subprocess.CalledProcessError as exc:
  560. output = exc.output
  561. status = exc.returncode
  562. except OSError:
  563. # match the historical returns for a parent
  564. # exception class caught by exec_command()
  565. status = 127
  566. output = b''
  567. else:
  568. # output isn't actually a filepath but we do this
  569. # for now to match previous distutils behavior
  570. output = filepath_from_subprocess_output(output)
  571. status = 0
  572. version = None
  573. if status in ok_status:
  574. version = matcher(output)
  575. if version:
  576. version = LooseVersion(version)
  577. self.version = version
  578. return version
  579. replace_method(CCompiler, 'get_version', CCompiler_get_version)
  580. def CCompiler_cxx_compiler(self):
  581. """
  582. Return the C++ compiler.
  583. Parameters
  584. ----------
  585. None
  586. Returns
  587. -------
  588. cxx : class instance
  589. The C++ compiler, as a `CCompiler` instance.
  590. """
  591. if self.compiler_type in ('msvc', 'intelw', 'intelemw'):
  592. return self
  593. cxx = copy(self)
  594. cxx.compiler_so = [cxx.compiler_cxx[0]] + cxx.compiler_so[1:]
  595. if sys.platform.startswith('aix') and 'ld_so_aix' in cxx.linker_so[0]:
  596. # AIX needs the ld_so_aix script included with Python
  597. cxx.linker_so = [cxx.linker_so[0], cxx.compiler_cxx[0]] \
  598. + cxx.linker_so[2:]
  599. else:
  600. cxx.linker_so = [cxx.compiler_cxx[0]] + cxx.linker_so[1:]
  601. return cxx
  602. replace_method(CCompiler, 'cxx_compiler', CCompiler_cxx_compiler)
  603. compiler_class['intel'] = ('intelccompiler', 'IntelCCompiler',
  604. "Intel C Compiler for 32-bit applications")
  605. compiler_class['intele'] = ('intelccompiler', 'IntelItaniumCCompiler',
  606. "Intel C Itanium Compiler for Itanium-based applications")
  607. compiler_class['intelem'] = ('intelccompiler', 'IntelEM64TCCompiler',
  608. "Intel C Compiler for 64-bit applications")
  609. compiler_class['intelw'] = ('intelccompiler', 'IntelCCompilerW',
  610. "Intel C Compiler for 32-bit applications on Windows")
  611. compiler_class['intelemw'] = ('intelccompiler', 'IntelEM64TCCompilerW',
  612. "Intel C Compiler for 64-bit applications on Windows")
  613. compiler_class['pathcc'] = ('pathccompiler', 'PathScaleCCompiler',
  614. "PathScale Compiler for SiCortex-based applications")
  615. ccompiler._default_compilers += (('linux.*', 'intel'),
  616. ('linux.*', 'intele'),
  617. ('linux.*', 'intelem'),
  618. ('linux.*', 'pathcc'),
  619. ('nt', 'intelw'),
  620. ('nt', 'intelemw'))
  621. if sys.platform == 'win32':
  622. compiler_class['mingw32'] = ('mingw32ccompiler', 'Mingw32CCompiler',
  623. "Mingw32 port of GNU C Compiler for Win32"\
  624. "(for MSC built Python)")
  625. if mingw32():
  626. # On windows platforms, we want to default to mingw32 (gcc)
  627. # because msvc can't build blitz stuff.
  628. log.info('Setting mingw32 as default compiler for nt.')
  629. ccompiler._default_compilers = (('nt', 'mingw32'),) \
  630. + ccompiler._default_compilers
  631. _distutils_new_compiler = new_compiler
  632. def new_compiler (plat=None,
  633. compiler=None,
  634. verbose=None,
  635. dry_run=0,
  636. force=0):
  637. # Try first C compilers from numpy.distutils.
  638. if verbose is None:
  639. verbose = log.get_threshold() <= log.INFO
  640. if plat is None:
  641. plat = os.name
  642. try:
  643. if compiler is None:
  644. compiler = get_default_compiler(plat)
  645. (module_name, class_name, long_description) = compiler_class[compiler]
  646. except KeyError:
  647. msg = "don't know how to compile C/C++ code on platform '%s'" % plat
  648. if compiler is not None:
  649. msg = msg + " with '%s' compiler" % compiler
  650. raise DistutilsPlatformError(msg)
  651. module_name = "numpy.distutils." + module_name
  652. try:
  653. __import__ (module_name)
  654. except ImportError:
  655. msg = str(get_exception())
  656. log.info('%s in numpy.distutils; trying from distutils',
  657. str(msg))
  658. module_name = module_name[6:]
  659. try:
  660. __import__(module_name)
  661. except ImportError:
  662. msg = str(get_exception())
  663. raise DistutilsModuleError("can't compile C/C++ code: unable to load module '%s'" % \
  664. module_name)
  665. try:
  666. module = sys.modules[module_name]
  667. klass = vars(module)[class_name]
  668. except KeyError:
  669. raise DistutilsModuleError(("can't compile C/C++ code: unable to find class '%s' " +
  670. "in module '%s'") % (class_name, module_name))
  671. compiler = klass(None, dry_run, force)
  672. compiler.verbose = verbose
  673. log.debug('new_compiler returns %s' % (klass))
  674. return compiler
  675. ccompiler.new_compiler = new_compiler
  676. _distutils_gen_lib_options = gen_lib_options
  677. def gen_lib_options(compiler, library_dirs, runtime_library_dirs, libraries):
  678. # the version of this function provided by CPython allows the following
  679. # to return lists, which are unpacked automatically:
  680. # - compiler.runtime_library_dir_option
  681. # our version extends the behavior to:
  682. # - compiler.library_dir_option
  683. # - compiler.library_option
  684. # - compiler.find_library_file
  685. r = _distutils_gen_lib_options(compiler, library_dirs,
  686. runtime_library_dirs, libraries)
  687. lib_opts = []
  688. for i in r:
  689. if is_sequence(i):
  690. lib_opts.extend(list(i))
  691. else:
  692. lib_opts.append(i)
  693. return lib_opts
  694. ccompiler.gen_lib_options = gen_lib_options
  695. # Also fix up the various compiler modules, which do
  696. # from distutils.ccompiler import gen_lib_options
  697. # Don't bother with mwerks, as we don't support Classic Mac.
  698. for _cc in ['msvc9', 'msvc', '_msvc', 'bcpp', 'cygwinc', 'emxc', 'unixc']:
  699. _m = sys.modules.get('distutils.' + _cc + 'compiler')
  700. if _m is not None:
  701. setattr(_m, 'gen_lib_options', gen_lib_options)