__init__.py 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025
  1. """numpy.distutils.fcompiler
  2. Contains FCompiler, an abstract base class that defines the interface
  3. for the numpy.distutils Fortran compiler abstraction model.
  4. Terminology:
  5. To be consistent, where the term 'executable' is used, it means the single
  6. file, like 'gcc', that is executed, and should be a string. In contrast,
  7. 'command' means the entire command line, like ['gcc', '-c', 'file.c'], and
  8. should be a list.
  9. But note that FCompiler.executables is actually a dictionary of commands.
  10. """
  11. __all__ = ['FCompiler', 'new_fcompiler', 'show_fcompilers',
  12. 'dummy_fortran_file']
  13. import os
  14. import sys
  15. import re
  16. from distutils.sysconfig import get_python_lib
  17. from distutils.fancy_getopt import FancyGetopt
  18. from distutils.errors import DistutilsModuleError, \
  19. DistutilsExecError, CompileError, LinkError, DistutilsPlatformError
  20. from distutils.util import split_quoted, strtobool
  21. from numpy.distutils.ccompiler import CCompiler, gen_lib_options
  22. from numpy.distutils import log
  23. from numpy.distutils.misc_util import is_string, all_strings, is_sequence, \
  24. make_temp_file, get_shared_lib_extension
  25. from numpy.distutils.exec_command import find_executable
  26. from numpy.distutils import _shell_utils
  27. from .environment import EnvironmentConfig
  28. __metaclass__ = type
  29. class CompilerNotFound(Exception):
  30. pass
  31. def flaglist(s):
  32. if is_string(s):
  33. return split_quoted(s)
  34. else:
  35. return s
  36. def str2bool(s):
  37. if is_string(s):
  38. return strtobool(s)
  39. return bool(s)
  40. def is_sequence_of_strings(seq):
  41. return is_sequence(seq) and all_strings(seq)
  42. class FCompiler(CCompiler):
  43. """Abstract base class to define the interface that must be implemented
  44. by real Fortran compiler classes.
  45. Methods that subclasses may redefine:
  46. update_executables(), find_executables(), get_version()
  47. get_flags(), get_flags_opt(), get_flags_arch(), get_flags_debug()
  48. get_flags_f77(), get_flags_opt_f77(), get_flags_arch_f77(),
  49. get_flags_debug_f77(), get_flags_f90(), get_flags_opt_f90(),
  50. get_flags_arch_f90(), get_flags_debug_f90(),
  51. get_flags_fix(), get_flags_linker_so()
  52. DON'T call these methods (except get_version) after
  53. constructing a compiler instance or inside any other method.
  54. All methods, except update_executables() and find_executables(),
  55. may call the get_version() method.
  56. After constructing a compiler instance, always call customize(dist=None)
  57. method that finalizes compiler construction and makes the following
  58. attributes available:
  59. compiler_f77
  60. compiler_f90
  61. compiler_fix
  62. linker_so
  63. archiver
  64. ranlib
  65. libraries
  66. library_dirs
  67. """
  68. # These are the environment variables and distutils keys used.
  69. # Each configuration description is
  70. # (<hook name>, <environment variable>, <key in distutils.cfg>, <convert>, <append>)
  71. # The hook names are handled by the self._environment_hook method.
  72. # - names starting with 'self.' call methods in this class
  73. # - names starting with 'exe.' return the key in the executables dict
  74. # - names like 'flags.YYY' return self.get_flag_YYY()
  75. # convert is either None or a function to convert a string to the
  76. # appropriate type used.
  77. distutils_vars = EnvironmentConfig(
  78. distutils_section='config_fc',
  79. noopt = (None, None, 'noopt', str2bool, False),
  80. noarch = (None, None, 'noarch', str2bool, False),
  81. debug = (None, None, 'debug', str2bool, False),
  82. verbose = (None, None, 'verbose', str2bool, False),
  83. )
  84. command_vars = EnvironmentConfig(
  85. distutils_section='config_fc',
  86. compiler_f77 = ('exe.compiler_f77', 'F77', 'f77exec', None, False),
  87. compiler_f90 = ('exe.compiler_f90', 'F90', 'f90exec', None, False),
  88. compiler_fix = ('exe.compiler_fix', 'F90', 'f90exec', None, False),
  89. version_cmd = ('exe.version_cmd', None, None, None, False),
  90. linker_so = ('exe.linker_so', 'LDSHARED', 'ldshared', None, False),
  91. linker_exe = ('exe.linker_exe', 'LD', 'ld', None, False),
  92. archiver = (None, 'AR', 'ar', None, False),
  93. ranlib = (None, 'RANLIB', 'ranlib', None, False),
  94. )
  95. flag_vars = EnvironmentConfig(
  96. distutils_section='config_fc',
  97. f77 = ('flags.f77', 'F77FLAGS', 'f77flags', flaglist, True),
  98. f90 = ('flags.f90', 'F90FLAGS', 'f90flags', flaglist, True),
  99. free = ('flags.free', 'FREEFLAGS', 'freeflags', flaglist, True),
  100. fix = ('flags.fix', None, None, flaglist, False),
  101. opt = ('flags.opt', 'FOPT', 'opt', flaglist, True),
  102. opt_f77 = ('flags.opt_f77', None, None, flaglist, False),
  103. opt_f90 = ('flags.opt_f90', None, None, flaglist, False),
  104. arch = ('flags.arch', 'FARCH', 'arch', flaglist, False),
  105. arch_f77 = ('flags.arch_f77', None, None, flaglist, False),
  106. arch_f90 = ('flags.arch_f90', None, None, flaglist, False),
  107. debug = ('flags.debug', 'FDEBUG', 'fdebug', flaglist, True),
  108. debug_f77 = ('flags.debug_f77', None, None, flaglist, False),
  109. debug_f90 = ('flags.debug_f90', None, None, flaglist, False),
  110. flags = ('self.get_flags', 'FFLAGS', 'fflags', flaglist, True),
  111. linker_so = ('flags.linker_so', 'LDFLAGS', 'ldflags', flaglist, True),
  112. linker_exe = ('flags.linker_exe', 'LDFLAGS', 'ldflags', flaglist, True),
  113. ar = ('flags.ar', 'ARFLAGS', 'arflags', flaglist, True),
  114. )
  115. language_map = {'.f': 'f77',
  116. '.for': 'f77',
  117. '.F': 'f77', # XXX: needs preprocessor
  118. '.ftn': 'f77',
  119. '.f77': 'f77',
  120. '.f90': 'f90',
  121. '.F90': 'f90', # XXX: needs preprocessor
  122. '.f95': 'f90',
  123. }
  124. language_order = ['f90', 'f77']
  125. # These will be set by the subclass
  126. compiler_type = None
  127. compiler_aliases = ()
  128. version_pattern = None
  129. possible_executables = []
  130. executables = {
  131. 'version_cmd': ["f77", "-v"],
  132. 'compiler_f77': ["f77"],
  133. 'compiler_f90': ["f90"],
  134. 'compiler_fix': ["f90", "-fixed"],
  135. 'linker_so': ["f90", "-shared"],
  136. 'linker_exe': ["f90"],
  137. 'archiver': ["ar", "-cr"],
  138. 'ranlib': None,
  139. }
  140. # If compiler does not support compiling Fortran 90 then it can
  141. # suggest using another compiler. For example, gnu would suggest
  142. # gnu95 compiler type when there are F90 sources.
  143. suggested_f90_compiler = None
  144. compile_switch = "-c"
  145. object_switch = "-o " # Ending space matters! It will be stripped
  146. # but if it is missing then object_switch
  147. # will be prefixed to object file name by
  148. # string concatenation.
  149. library_switch = "-o " # Ditto!
  150. # Switch to specify where module files are created and searched
  151. # for USE statement. Normally it is a string and also here ending
  152. # space matters. See above.
  153. module_dir_switch = None
  154. # Switch to specify where module files are searched for USE statement.
  155. module_include_switch = '-I'
  156. pic_flags = [] # Flags to create position-independent code
  157. src_extensions = ['.for', '.ftn', '.f77', '.f', '.f90', '.f95', '.F', '.F90', '.FOR']
  158. obj_extension = ".o"
  159. shared_lib_extension = get_shared_lib_extension()
  160. static_lib_extension = ".a" # or .lib
  161. static_lib_format = "lib%s%s" # or %s%s
  162. shared_lib_format = "%s%s"
  163. exe_extension = ""
  164. _exe_cache = {}
  165. _executable_keys = ['version_cmd', 'compiler_f77', 'compiler_f90',
  166. 'compiler_fix', 'linker_so', 'linker_exe', 'archiver',
  167. 'ranlib']
  168. # This will be set by new_fcompiler when called in
  169. # command/{build_ext.py, build_clib.py, config.py} files.
  170. c_compiler = None
  171. # extra_{f77,f90}_compile_args are set by build_ext.build_extension method
  172. extra_f77_compile_args = []
  173. extra_f90_compile_args = []
  174. def __init__(self, *args, **kw):
  175. CCompiler.__init__(self, *args, **kw)
  176. self.distutils_vars = self.distutils_vars.clone(self._environment_hook)
  177. self.command_vars = self.command_vars.clone(self._environment_hook)
  178. self.flag_vars = self.flag_vars.clone(self._environment_hook)
  179. self.executables = self.executables.copy()
  180. for e in self._executable_keys:
  181. if e not in self.executables:
  182. self.executables[e] = None
  183. # Some methods depend on .customize() being called first, so
  184. # this keeps track of whether that's happened yet.
  185. self._is_customised = False
  186. def __copy__(self):
  187. obj = self.__new__(self.__class__)
  188. obj.__dict__.update(self.__dict__)
  189. obj.distutils_vars = obj.distutils_vars.clone(obj._environment_hook)
  190. obj.command_vars = obj.command_vars.clone(obj._environment_hook)
  191. obj.flag_vars = obj.flag_vars.clone(obj._environment_hook)
  192. obj.executables = obj.executables.copy()
  193. return obj
  194. def copy(self):
  195. return self.__copy__()
  196. # Use properties for the attributes used by CCompiler. Setting them
  197. # as attributes from the self.executables dictionary is error-prone,
  198. # so we get them from there each time.
  199. def _command_property(key):
  200. def fget(self):
  201. assert self._is_customised
  202. return self.executables[key]
  203. return property(fget=fget)
  204. version_cmd = _command_property('version_cmd')
  205. compiler_f77 = _command_property('compiler_f77')
  206. compiler_f90 = _command_property('compiler_f90')
  207. compiler_fix = _command_property('compiler_fix')
  208. linker_so = _command_property('linker_so')
  209. linker_exe = _command_property('linker_exe')
  210. archiver = _command_property('archiver')
  211. ranlib = _command_property('ranlib')
  212. # Make our terminology consistent.
  213. def set_executable(self, key, value):
  214. self.set_command(key, value)
  215. def set_commands(self, **kw):
  216. for k, v in kw.items():
  217. self.set_command(k, v)
  218. def set_command(self, key, value):
  219. if not key in self._executable_keys:
  220. raise ValueError(
  221. "unknown executable '%s' for class %s" %
  222. (key, self.__class__.__name__))
  223. if is_string(value):
  224. value = split_quoted(value)
  225. assert value is None or is_sequence_of_strings(value[1:]), (key, value)
  226. self.executables[key] = value
  227. ######################################################################
  228. ## Methods that subclasses may redefine. But don't call these methods!
  229. ## They are private to FCompiler class and may return unexpected
  230. ## results if used elsewhere. So, you have been warned..
  231. def find_executables(self):
  232. """Go through the self.executables dictionary, and attempt to
  233. find and assign appropriate executables.
  234. Executable names are looked for in the environment (environment
  235. variables, the distutils.cfg, and command line), the 0th-element of
  236. the command list, and the self.possible_executables list.
  237. Also, if the 0th element is "<F77>" or "<F90>", the Fortran 77
  238. or the Fortran 90 compiler executable is used, unless overridden
  239. by an environment setting.
  240. Subclasses should call this if overridden.
  241. """
  242. assert self._is_customised
  243. exe_cache = self._exe_cache
  244. def cached_find_executable(exe):
  245. if exe in exe_cache:
  246. return exe_cache[exe]
  247. fc_exe = find_executable(exe)
  248. exe_cache[exe] = exe_cache[fc_exe] = fc_exe
  249. return fc_exe
  250. def verify_command_form(name, value):
  251. if value is not None and not is_sequence_of_strings(value):
  252. raise ValueError(
  253. "%s value %r is invalid in class %s" %
  254. (name, value, self.__class__.__name__))
  255. def set_exe(exe_key, f77=None, f90=None):
  256. cmd = self.executables.get(exe_key, None)
  257. if not cmd:
  258. return None
  259. # Note that we get cmd[0] here if the environment doesn't
  260. # have anything set
  261. exe_from_environ = getattr(self.command_vars, exe_key)
  262. if not exe_from_environ:
  263. possibles = [f90, f77] + self.possible_executables
  264. else:
  265. possibles = [exe_from_environ] + self.possible_executables
  266. seen = set()
  267. unique_possibles = []
  268. for e in possibles:
  269. if e == '<F77>':
  270. e = f77
  271. elif e == '<F90>':
  272. e = f90
  273. if not e or e in seen:
  274. continue
  275. seen.add(e)
  276. unique_possibles.append(e)
  277. for exe in unique_possibles:
  278. fc_exe = cached_find_executable(exe)
  279. if fc_exe:
  280. cmd[0] = fc_exe
  281. return fc_exe
  282. self.set_command(exe_key, None)
  283. return None
  284. ctype = self.compiler_type
  285. f90 = set_exe('compiler_f90')
  286. if not f90:
  287. f77 = set_exe('compiler_f77')
  288. if f77:
  289. log.warn('%s: no Fortran 90 compiler found' % ctype)
  290. else:
  291. raise CompilerNotFound('%s: f90 nor f77' % ctype)
  292. else:
  293. f77 = set_exe('compiler_f77', f90=f90)
  294. if not f77:
  295. log.warn('%s: no Fortran 77 compiler found' % ctype)
  296. set_exe('compiler_fix', f90=f90)
  297. set_exe('linker_so', f77=f77, f90=f90)
  298. set_exe('linker_exe', f77=f77, f90=f90)
  299. set_exe('version_cmd', f77=f77, f90=f90)
  300. set_exe('archiver')
  301. set_exe('ranlib')
  302. def update_executables(self):
  303. """Called at the beginning of customisation. Subclasses should
  304. override this if they need to set up the executables dictionary.
  305. Note that self.find_executables() is run afterwards, so the
  306. self.executables dictionary values can contain <F77> or <F90> as
  307. the command, which will be replaced by the found F77 or F90
  308. compiler.
  309. """
  310. pass
  311. def get_flags(self):
  312. """List of flags common to all compiler types."""
  313. return [] + self.pic_flags
  314. def _get_command_flags(self, key):
  315. cmd = self.executables.get(key, None)
  316. if cmd is None:
  317. return []
  318. return cmd[1:]
  319. def get_flags_f77(self):
  320. """List of Fortran 77 specific flags."""
  321. return self._get_command_flags('compiler_f77')
  322. def get_flags_f90(self):
  323. """List of Fortran 90 specific flags."""
  324. return self._get_command_flags('compiler_f90')
  325. def get_flags_free(self):
  326. """List of Fortran 90 free format specific flags."""
  327. return []
  328. def get_flags_fix(self):
  329. """List of Fortran 90 fixed format specific flags."""
  330. return self._get_command_flags('compiler_fix')
  331. def get_flags_linker_so(self):
  332. """List of linker flags to build a shared library."""
  333. return self._get_command_flags('linker_so')
  334. def get_flags_linker_exe(self):
  335. """List of linker flags to build an executable."""
  336. return self._get_command_flags('linker_exe')
  337. def get_flags_ar(self):
  338. """List of archiver flags. """
  339. return self._get_command_flags('archiver')
  340. def get_flags_opt(self):
  341. """List of architecture independent compiler flags."""
  342. return []
  343. def get_flags_arch(self):
  344. """List of architecture dependent compiler flags."""
  345. return []
  346. def get_flags_debug(self):
  347. """List of compiler flags to compile with debugging information."""
  348. return []
  349. get_flags_opt_f77 = get_flags_opt_f90 = get_flags_opt
  350. get_flags_arch_f77 = get_flags_arch_f90 = get_flags_arch
  351. get_flags_debug_f77 = get_flags_debug_f90 = get_flags_debug
  352. def get_libraries(self):
  353. """List of compiler libraries."""
  354. return self.libraries[:]
  355. def get_library_dirs(self):
  356. """List of compiler library directories."""
  357. return self.library_dirs[:]
  358. def get_version(self, force=False, ok_status=[0]):
  359. assert self._is_customised
  360. version = CCompiler.get_version(self, force=force, ok_status=ok_status)
  361. if version is None:
  362. raise CompilerNotFound()
  363. return version
  364. ############################################################
  365. ## Public methods:
  366. def customize(self, dist = None):
  367. """Customize Fortran compiler.
  368. This method gets Fortran compiler specific information from
  369. (i) class definition, (ii) environment, (iii) distutils config
  370. files, and (iv) command line (later overrides earlier).
  371. This method should be always called after constructing a
  372. compiler instance. But not in __init__ because Distribution
  373. instance is needed for (iii) and (iv).
  374. """
  375. log.info('customize %s' % (self.__class__.__name__))
  376. self._is_customised = True
  377. self.distutils_vars.use_distribution(dist)
  378. self.command_vars.use_distribution(dist)
  379. self.flag_vars.use_distribution(dist)
  380. self.update_executables()
  381. # find_executables takes care of setting the compiler commands,
  382. # version_cmd, linker_so, linker_exe, ar, and ranlib
  383. self.find_executables()
  384. noopt = self.distutils_vars.get('noopt', False)
  385. noarch = self.distutils_vars.get('noarch', noopt)
  386. debug = self.distutils_vars.get('debug', False)
  387. f77 = self.command_vars.compiler_f77
  388. f90 = self.command_vars.compiler_f90
  389. f77flags = []
  390. f90flags = []
  391. freeflags = []
  392. fixflags = []
  393. if f77:
  394. f77 = _shell_utils.NativeParser.split(f77)
  395. f77flags = self.flag_vars.f77
  396. if f90:
  397. f90 = _shell_utils.NativeParser.split(f90)
  398. f90flags = self.flag_vars.f90
  399. freeflags = self.flag_vars.free
  400. # XXX Assuming that free format is default for f90 compiler.
  401. fix = self.command_vars.compiler_fix
  402. # NOTE: this and similar examples are probably just
  403. # excluding --coverage flag when F90 = gfortran --coverage
  404. # instead of putting that flag somewhere more appropriate
  405. # this and similar examples where a Fortran compiler
  406. # environment variable has been customized by CI or a user
  407. # should perhaps eventually be more thoroughly tested and more
  408. # robustly handled
  409. if fix:
  410. fix = _shell_utils.NativeParser.split(fix)
  411. fixflags = self.flag_vars.fix + f90flags
  412. oflags, aflags, dflags = [], [], []
  413. # examine get_flags_<tag>_<compiler> for extra flags
  414. # only add them if the method is different from get_flags_<tag>
  415. def get_flags(tag, flags):
  416. # note that self.flag_vars.<tag> calls self.get_flags_<tag>()
  417. flags.extend(getattr(self.flag_vars, tag))
  418. this_get = getattr(self, 'get_flags_' + tag)
  419. for name, c, flagvar in [('f77', f77, f77flags),
  420. ('f90', f90, f90flags),
  421. ('f90', fix, fixflags)]:
  422. t = '%s_%s' % (tag, name)
  423. if c and this_get is not getattr(self, 'get_flags_' + t):
  424. flagvar.extend(getattr(self.flag_vars, t))
  425. if not noopt:
  426. get_flags('opt', oflags)
  427. if not noarch:
  428. get_flags('arch', aflags)
  429. if debug:
  430. get_flags('debug', dflags)
  431. fflags = self.flag_vars.flags + dflags + oflags + aflags
  432. if f77:
  433. self.set_commands(compiler_f77=f77+f77flags+fflags)
  434. if f90:
  435. self.set_commands(compiler_f90=f90+freeflags+f90flags+fflags)
  436. if fix:
  437. self.set_commands(compiler_fix=fix+fixflags+fflags)
  438. #XXX: Do we need LDSHARED->SOSHARED, LDFLAGS->SOFLAGS
  439. linker_so = self.linker_so
  440. if linker_so:
  441. linker_so_flags = self.flag_vars.linker_so
  442. if sys.platform.startswith('aix'):
  443. python_lib = get_python_lib(standard_lib=1)
  444. ld_so_aix = os.path.join(python_lib, 'config', 'ld_so_aix')
  445. python_exp = os.path.join(python_lib, 'config', 'python.exp')
  446. linker_so = [ld_so_aix] + linker_so + ['-bI:'+python_exp]
  447. self.set_commands(linker_so=linker_so+linker_so_flags)
  448. linker_exe = self.linker_exe
  449. if linker_exe:
  450. linker_exe_flags = self.flag_vars.linker_exe
  451. self.set_commands(linker_exe=linker_exe+linker_exe_flags)
  452. ar = self.command_vars.archiver
  453. if ar:
  454. arflags = self.flag_vars.ar
  455. self.set_commands(archiver=[ar]+arflags)
  456. self.set_library_dirs(self.get_library_dirs())
  457. self.set_libraries(self.get_libraries())
  458. def dump_properties(self):
  459. """Print out the attributes of a compiler instance."""
  460. props = []
  461. for key in list(self.executables.keys()) + \
  462. ['version', 'libraries', 'library_dirs',
  463. 'object_switch', 'compile_switch']:
  464. if hasattr(self, key):
  465. v = getattr(self, key)
  466. props.append((key, None, '= '+repr(v)))
  467. props.sort()
  468. pretty_printer = FancyGetopt(props)
  469. for l in pretty_printer.generate_help("%s instance properties:" \
  470. % (self.__class__.__name__)):
  471. if l[:4]==' --':
  472. l = ' ' + l[4:]
  473. print(l)
  474. ###################
  475. def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
  476. """Compile 'src' to product 'obj'."""
  477. src_flags = {}
  478. if is_f_file(src) and not has_f90_header(src):
  479. flavor = ':f77'
  480. compiler = self.compiler_f77
  481. src_flags = get_f77flags(src)
  482. extra_compile_args = self.extra_f77_compile_args or []
  483. elif is_free_format(src):
  484. flavor = ':f90'
  485. compiler = self.compiler_f90
  486. if compiler is None:
  487. raise DistutilsExecError('f90 not supported by %s needed for %s'\
  488. % (self.__class__.__name__, src))
  489. extra_compile_args = self.extra_f90_compile_args or []
  490. else:
  491. flavor = ':fix'
  492. compiler = self.compiler_fix
  493. if compiler is None:
  494. raise DistutilsExecError('f90 (fixed) not supported by %s needed for %s'\
  495. % (self.__class__.__name__, src))
  496. extra_compile_args = self.extra_f90_compile_args or []
  497. if self.object_switch[-1]==' ':
  498. o_args = [self.object_switch.strip(), obj]
  499. else:
  500. o_args = [self.object_switch.strip()+obj]
  501. assert self.compile_switch.strip()
  502. s_args = [self.compile_switch, src]
  503. if extra_compile_args:
  504. log.info('extra %s options: %r' \
  505. % (flavor[1:], ' '.join(extra_compile_args)))
  506. extra_flags = src_flags.get(self.compiler_type, [])
  507. if extra_flags:
  508. log.info('using compile options from source: %r' \
  509. % ' '.join(extra_flags))
  510. command = compiler + cc_args + extra_flags + s_args + o_args \
  511. + extra_postargs + extra_compile_args
  512. display = '%s: %s' % (os.path.basename(compiler[0]) + flavor,
  513. src)
  514. try:
  515. self.spawn(command, display=display)
  516. except DistutilsExecError as e:
  517. msg = str(e)
  518. raise CompileError(msg)
  519. def module_options(self, module_dirs, module_build_dir):
  520. options = []
  521. if self.module_dir_switch is not None:
  522. if self.module_dir_switch[-1]==' ':
  523. options.extend([self.module_dir_switch.strip(), module_build_dir])
  524. else:
  525. options.append(self.module_dir_switch.strip()+module_build_dir)
  526. else:
  527. print('XXX: module_build_dir=%r option ignored' % (module_build_dir))
  528. print('XXX: Fix module_dir_switch for ', self.__class__.__name__)
  529. if self.module_include_switch is not None:
  530. for d in [module_build_dir]+module_dirs:
  531. options.append('%s%s' % (self.module_include_switch, d))
  532. else:
  533. print('XXX: module_dirs=%r option ignored' % (module_dirs))
  534. print('XXX: Fix module_include_switch for ', self.__class__.__name__)
  535. return options
  536. def library_option(self, lib):
  537. if lib[0]=='-':
  538. return lib
  539. else:
  540. return "-l" + lib
  541. def library_dir_option(self, dir):
  542. return "-L" + dir
  543. def link(self, target_desc, objects,
  544. output_filename, output_dir=None, libraries=None,
  545. library_dirs=None, runtime_library_dirs=None,
  546. export_symbols=None, debug=0, extra_preargs=None,
  547. extra_postargs=None, build_temp=None, target_lang=None):
  548. objects, output_dir = self._fix_object_args(objects, output_dir)
  549. libraries, library_dirs, runtime_library_dirs = \
  550. self._fix_lib_args(libraries, library_dirs, runtime_library_dirs)
  551. lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs,
  552. libraries)
  553. if is_string(output_dir):
  554. output_filename = os.path.join(output_dir, output_filename)
  555. elif output_dir is not None:
  556. raise TypeError("'output_dir' must be a string or None")
  557. if self._need_link(objects, output_filename):
  558. if self.library_switch[-1]==' ':
  559. o_args = [self.library_switch.strip(), output_filename]
  560. else:
  561. o_args = [self.library_switch.strip()+output_filename]
  562. if is_string(self.objects):
  563. ld_args = objects + [self.objects]
  564. else:
  565. ld_args = objects + self.objects
  566. ld_args = ld_args + lib_opts + o_args
  567. if debug:
  568. ld_args[:0] = ['-g']
  569. if extra_preargs:
  570. ld_args[:0] = extra_preargs
  571. if extra_postargs:
  572. ld_args.extend(extra_postargs)
  573. self.mkpath(os.path.dirname(output_filename))
  574. if target_desc == CCompiler.EXECUTABLE:
  575. linker = self.linker_exe[:]
  576. else:
  577. linker = self.linker_so[:]
  578. command = linker + ld_args
  579. try:
  580. self.spawn(command)
  581. except DistutilsExecError as e:
  582. msg = str(e)
  583. raise LinkError(msg)
  584. else:
  585. log.debug("skipping %s (up-to-date)", output_filename)
  586. def _environment_hook(self, name, hook_name):
  587. if hook_name is None:
  588. return None
  589. if is_string(hook_name):
  590. if hook_name.startswith('self.'):
  591. hook_name = hook_name[5:]
  592. hook = getattr(self, hook_name)
  593. return hook()
  594. elif hook_name.startswith('exe.'):
  595. hook_name = hook_name[4:]
  596. var = self.executables[hook_name]
  597. if var:
  598. return var[0]
  599. else:
  600. return None
  601. elif hook_name.startswith('flags.'):
  602. hook_name = hook_name[6:]
  603. hook = getattr(self, 'get_flags_' + hook_name)
  604. return hook()
  605. else:
  606. return hook_name()
  607. def can_ccompiler_link(self, ccompiler):
  608. """
  609. Check if the given C compiler can link objects produced by
  610. this compiler.
  611. """
  612. return True
  613. def wrap_unlinkable_objects(self, objects, output_dir, extra_dll_dir):
  614. """
  615. Convert a set of object files that are not compatible with the default
  616. linker, to a file that is compatible.
  617. Parameters
  618. ----------
  619. objects : list
  620. List of object files to include.
  621. output_dir : str
  622. Output directory to place generated object files.
  623. extra_dll_dir : str
  624. Output directory to place extra DLL files that need to be
  625. included on Windows.
  626. Returns
  627. -------
  628. converted_objects : list of str
  629. List of converted object files.
  630. Note that the number of output files is not necessarily
  631. the same as inputs.
  632. """
  633. raise NotImplementedError()
  634. ## class FCompiler
  635. _default_compilers = (
  636. # sys.platform mappings
  637. ('win32', ('gnu', 'intelv', 'absoft', 'compaqv', 'intelev', 'gnu95', 'g95',
  638. 'intelvem', 'intelem', 'flang')),
  639. ('cygwin.*', ('gnu', 'intelv', 'absoft', 'compaqv', 'intelev', 'gnu95', 'g95')),
  640. ('linux.*', ('gnu95', 'intel', 'lahey', 'pg', 'nv', 'absoft', 'nag', 'vast', 'compaq',
  641. 'intele', 'intelem', 'gnu', 'g95', 'pathf95', 'nagfor', 'fujitsu')),
  642. ('darwin.*', ('gnu95', 'nag', 'absoft', 'ibm', 'intel', 'gnu', 'g95', 'pg')),
  643. ('sunos.*', ('sun', 'gnu', 'gnu95', 'g95')),
  644. ('irix.*', ('mips', 'gnu', 'gnu95',)),
  645. ('aix.*', ('ibm', 'gnu', 'gnu95',)),
  646. # os.name mappings
  647. ('posix', ('gnu', 'gnu95',)),
  648. ('nt', ('gnu', 'gnu95',)),
  649. ('mac', ('gnu95', 'gnu', 'pg')),
  650. )
  651. fcompiler_class = None
  652. fcompiler_aliases = None
  653. def load_all_fcompiler_classes():
  654. """Cache all the FCompiler classes found in modules in the
  655. numpy.distutils.fcompiler package.
  656. """
  657. from glob import glob
  658. global fcompiler_class, fcompiler_aliases
  659. if fcompiler_class is not None:
  660. return
  661. pys = os.path.join(os.path.dirname(__file__), '*.py')
  662. fcompiler_class = {}
  663. fcompiler_aliases = {}
  664. for fname in glob(pys):
  665. module_name, ext = os.path.splitext(os.path.basename(fname))
  666. module_name = 'numpy.distutils.fcompiler.' + module_name
  667. __import__ (module_name)
  668. module = sys.modules[module_name]
  669. if hasattr(module, 'compilers'):
  670. for cname in module.compilers:
  671. klass = getattr(module, cname)
  672. desc = (klass.compiler_type, klass, klass.description)
  673. fcompiler_class[klass.compiler_type] = desc
  674. for alias in klass.compiler_aliases:
  675. if alias in fcompiler_aliases:
  676. raise ValueError("alias %r defined for both %s and %s"
  677. % (alias, klass.__name__,
  678. fcompiler_aliases[alias][1].__name__))
  679. fcompiler_aliases[alias] = desc
  680. def _find_existing_fcompiler(compiler_types,
  681. osname=None, platform=None,
  682. requiref90=False,
  683. c_compiler=None):
  684. from numpy.distutils.core import get_distribution
  685. dist = get_distribution(always=True)
  686. for compiler_type in compiler_types:
  687. v = None
  688. try:
  689. c = new_fcompiler(plat=platform, compiler=compiler_type,
  690. c_compiler=c_compiler)
  691. c.customize(dist)
  692. v = c.get_version()
  693. if requiref90 and c.compiler_f90 is None:
  694. v = None
  695. new_compiler = c.suggested_f90_compiler
  696. if new_compiler:
  697. log.warn('Trying %r compiler as suggested by %r '
  698. 'compiler for f90 support.' % (compiler_type,
  699. new_compiler))
  700. c = new_fcompiler(plat=platform, compiler=new_compiler,
  701. c_compiler=c_compiler)
  702. c.customize(dist)
  703. v = c.get_version()
  704. if v is not None:
  705. compiler_type = new_compiler
  706. if requiref90 and c.compiler_f90 is None:
  707. raise ValueError('%s does not support compiling f90 codes, '
  708. 'skipping.' % (c.__class__.__name__))
  709. except DistutilsModuleError:
  710. log.debug("_find_existing_fcompiler: compiler_type='%s' raised DistutilsModuleError", compiler_type)
  711. except CompilerNotFound:
  712. log.debug("_find_existing_fcompiler: compiler_type='%s' not found", compiler_type)
  713. if v is not None:
  714. return compiler_type
  715. return None
  716. def available_fcompilers_for_platform(osname=None, platform=None):
  717. if osname is None:
  718. osname = os.name
  719. if platform is None:
  720. platform = sys.platform
  721. matching_compiler_types = []
  722. for pattern, compiler_type in _default_compilers:
  723. if re.match(pattern, platform) or re.match(pattern, osname):
  724. for ct in compiler_type:
  725. if ct not in matching_compiler_types:
  726. matching_compiler_types.append(ct)
  727. if not matching_compiler_types:
  728. matching_compiler_types.append('gnu')
  729. return matching_compiler_types
  730. def get_default_fcompiler(osname=None, platform=None, requiref90=False,
  731. c_compiler=None):
  732. """Determine the default Fortran compiler to use for the given
  733. platform."""
  734. matching_compiler_types = available_fcompilers_for_platform(osname,
  735. platform)
  736. log.info("get_default_fcompiler: matching types: '%s'",
  737. matching_compiler_types)
  738. compiler_type = _find_existing_fcompiler(matching_compiler_types,
  739. osname=osname,
  740. platform=platform,
  741. requiref90=requiref90,
  742. c_compiler=c_compiler)
  743. return compiler_type
  744. # Flag to avoid rechecking for Fortran compiler every time
  745. failed_fcompilers = set()
  746. def new_fcompiler(plat=None,
  747. compiler=None,
  748. verbose=0,
  749. dry_run=0,
  750. force=0,
  751. requiref90=False,
  752. c_compiler = None):
  753. """Generate an instance of some FCompiler subclass for the supplied
  754. platform/compiler combination.
  755. """
  756. global failed_fcompilers
  757. fcompiler_key = (plat, compiler)
  758. if fcompiler_key in failed_fcompilers:
  759. return None
  760. load_all_fcompiler_classes()
  761. if plat is None:
  762. plat = os.name
  763. if compiler is None:
  764. compiler = get_default_fcompiler(plat, requiref90=requiref90,
  765. c_compiler=c_compiler)
  766. if compiler in fcompiler_class:
  767. module_name, klass, long_description = fcompiler_class[compiler]
  768. elif compiler in fcompiler_aliases:
  769. module_name, klass, long_description = fcompiler_aliases[compiler]
  770. else:
  771. msg = "don't know how to compile Fortran code on platform '%s'" % plat
  772. if compiler is not None:
  773. msg = msg + " with '%s' compiler." % compiler
  774. msg = msg + " Supported compilers are: %s)" \
  775. % (','.join(fcompiler_class.keys()))
  776. log.warn(msg)
  777. failed_fcompilers.add(fcompiler_key)
  778. return None
  779. compiler = klass(verbose=verbose, dry_run=dry_run, force=force)
  780. compiler.c_compiler = c_compiler
  781. return compiler
  782. def show_fcompilers(dist=None):
  783. """Print list of available compilers (used by the "--help-fcompiler"
  784. option to "config_fc").
  785. """
  786. if dist is None:
  787. from distutils.dist import Distribution
  788. from numpy.distutils.command.config_compiler import config_fc
  789. dist = Distribution()
  790. dist.script_name = os.path.basename(sys.argv[0])
  791. dist.script_args = ['config_fc'] + sys.argv[1:]
  792. try:
  793. dist.script_args.remove('--help-fcompiler')
  794. except ValueError:
  795. pass
  796. dist.cmdclass['config_fc'] = config_fc
  797. dist.parse_config_files()
  798. dist.parse_command_line()
  799. compilers = []
  800. compilers_na = []
  801. compilers_ni = []
  802. if not fcompiler_class:
  803. load_all_fcompiler_classes()
  804. platform_compilers = available_fcompilers_for_platform()
  805. for compiler in platform_compilers:
  806. v = None
  807. log.set_verbosity(-2)
  808. try:
  809. c = new_fcompiler(compiler=compiler, verbose=dist.verbose)
  810. c.customize(dist)
  811. v = c.get_version()
  812. except (DistutilsModuleError, CompilerNotFound) as e:
  813. log.debug("show_fcompilers: %s not found" % (compiler,))
  814. log.debug(repr(e))
  815. if v is None:
  816. compilers_na.append(("fcompiler="+compiler, None,
  817. fcompiler_class[compiler][2]))
  818. else:
  819. c.dump_properties()
  820. compilers.append(("fcompiler="+compiler, None,
  821. fcompiler_class[compiler][2] + ' (%s)' % v))
  822. compilers_ni = list(set(fcompiler_class.keys()) - set(platform_compilers))
  823. compilers_ni = [("fcompiler="+fc, None, fcompiler_class[fc][2])
  824. for fc in compilers_ni]
  825. compilers.sort()
  826. compilers_na.sort()
  827. compilers_ni.sort()
  828. pretty_printer = FancyGetopt(compilers)
  829. pretty_printer.print_help("Fortran compilers found:")
  830. pretty_printer = FancyGetopt(compilers_na)
  831. pretty_printer.print_help("Compilers available for this "
  832. "platform, but not found:")
  833. if compilers_ni:
  834. pretty_printer = FancyGetopt(compilers_ni)
  835. pretty_printer.print_help("Compilers not available on this platform:")
  836. print("For compiler details, run 'config_fc --verbose' setup command.")
  837. def dummy_fortran_file():
  838. fo, name = make_temp_file(suffix='.f')
  839. fo.write(" subroutine dummy()\n end\n")
  840. fo.close()
  841. return name[:-2]
  842. is_f_file = re.compile(r'.*[.](for|ftn|f77|f)\Z', re.I).match
  843. _has_f_header = re.compile(r'-[*]-\s*fortran\s*-[*]-', re.I).search
  844. _has_f90_header = re.compile(r'-[*]-\s*f90\s*-[*]-', re.I).search
  845. _has_fix_header = re.compile(r'-[*]-\s*fix\s*-[*]-', re.I).search
  846. _free_f90_start = re.compile(r'[^c*!]\s*[^\s\d\t]', re.I).match
  847. def is_free_format(file):
  848. """Check if file is in free format Fortran."""
  849. # f90 allows both fixed and free format, assuming fixed unless
  850. # signs of free format are detected.
  851. result = 0
  852. with open(file, encoding='latin1') as f:
  853. line = f.readline()
  854. n = 10000 # the number of non-comment lines to scan for hints
  855. if _has_f_header(line) or _has_fix_header(line):
  856. n = 0
  857. elif _has_f90_header(line):
  858. n = 0
  859. result = 1
  860. while n>0 and line:
  861. line = line.rstrip()
  862. if line and line[0]!='!':
  863. n -= 1
  864. if (line[0]!='\t' and _free_f90_start(line[:5])) or line[-1:]=='&':
  865. result = 1
  866. break
  867. line = f.readline()
  868. return result
  869. def has_f90_header(src):
  870. with open(src, encoding='latin1') as f:
  871. line = f.readline()
  872. return _has_f90_header(line) or _has_fix_header(line)
  873. _f77flags_re = re.compile(r'(c|)f77flags\s*\(\s*(?P<fcname>\w+)\s*\)\s*=\s*(?P<fflags>.*)', re.I)
  874. def get_f77flags(src):
  875. """
  876. Search the first 20 lines of fortran 77 code for line pattern
  877. `CF77FLAGS(<fcompiler type>)=<f77 flags>`
  878. Return a dictionary {<fcompiler type>:<f77 flags>}.
  879. """
  880. flags = {}
  881. with open(src, encoding='latin1') as f:
  882. i = 0
  883. for line in f:
  884. i += 1
  885. if i>20: break
  886. m = _f77flags_re.match(line)
  887. if not m: continue
  888. fcname = m.group('fcname').strip()
  889. fflags = m.group('fflags').strip()
  890. flags[fcname] = split_quoted(fflags)
  891. return flags
  892. # TODO: implement get_f90flags and use it in _compile similarly to get_f77flags
  893. if __name__ == '__main__':
  894. show_fcompilers()