ccompiler.py 27 KB

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