f2py2e.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. #!/usr/bin/env python3
  2. """
  3. f2py2e - Fortran to Python C/API generator. 2nd Edition.
  4. See __usage__ below.
  5. Copyright 1999--2011 Pearu Peterson all rights reserved,
  6. Pearu Peterson <pearu@cens.ioc.ee>
  7. Permission to use, modify, and distribute this software is given under the
  8. terms of the NumPy License.
  9. NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
  10. $Date: 2005/05/06 08:31:19 $
  11. Pearu Peterson
  12. """
  13. import sys
  14. import os
  15. import pprint
  16. import re
  17. from pathlib import Path
  18. from itertools import dropwhile
  19. import argparse
  20. from . import crackfortran
  21. from . import rules
  22. from . import cb_rules
  23. from . import auxfuncs
  24. from . import cfuncs
  25. from . import f90mod_rules
  26. from . import __version__
  27. from . import capi_maps
  28. from numpy.f2py._backends import f2py_build_generator
  29. f2py_version = __version__.version
  30. numpy_version = __version__.version
  31. errmess = sys.stderr.write
  32. # outmess=sys.stdout.write
  33. show = pprint.pprint
  34. outmess = auxfuncs.outmess
  35. __usage__ =\
  36. f"""Usage:
  37. 1) To construct extension module sources:
  38. f2py [<options>] <fortran files> [[[only:]||[skip:]] \\
  39. <fortran functions> ] \\
  40. [: <fortran files> ...]
  41. 2) To compile fortran files and build extension modules:
  42. f2py -c [<options>, <build_flib options>, <extra options>] <fortran files>
  43. 3) To generate signature files:
  44. f2py -h <filename.pyf> ...< same options as in (1) >
  45. Description: This program generates a Python C/API file (<modulename>module.c)
  46. that contains wrappers for given fortran functions so that they
  47. can be called from Python. With the -c option the corresponding
  48. extension modules are built.
  49. Options:
  50. --2d-numpy Use numpy.f2py tool with NumPy support. [DEFAULT]
  51. --2d-numeric Use f2py2e tool with Numeric support.
  52. --2d-numarray Use f2py2e tool with Numarray support.
  53. --g3-numpy Use 3rd generation f2py from the separate f2py package.
  54. [NOT AVAILABLE YET]
  55. -h <filename> Write signatures of the fortran routines to file <filename>
  56. and exit. You can then edit <filename> and use it instead
  57. of <fortran files>. If <filename>==stdout then the
  58. signatures are printed to stdout.
  59. <fortran functions> Names of fortran routines for which Python C/API
  60. functions will be generated. Default is all that are found
  61. in <fortran files>.
  62. <fortran files> Paths to fortran/signature files that will be scanned for
  63. <fortran functions> in order to determine their signatures.
  64. skip: Ignore fortran functions that follow until `:'.
  65. only: Use only fortran functions that follow until `:'.
  66. : Get back to <fortran files> mode.
  67. -m <modulename> Name of the module; f2py generates a Python/C API
  68. file <modulename>module.c or extension module <modulename>.
  69. Default is 'untitled'.
  70. '-include<header>' Writes additional headers in the C wrapper, can be passed
  71. multiple times, generates #include <header> each time.
  72. --[no-]lower Do [not] lower the cases in <fortran files>. By default,
  73. --lower is assumed with -h key, and --no-lower without -h key.
  74. --build-dir <dirname> All f2py generated files are created in <dirname>.
  75. Default is tempfile.mkdtemp().
  76. --overwrite-signature Overwrite existing signature file.
  77. --[no-]latex-doc Create (or not) <modulename>module.tex.
  78. Default is --no-latex-doc.
  79. --short-latex Create 'incomplete' LaTeX document (without commands
  80. \\documentclass, \\tableofcontents, and \\begin{{document}},
  81. \\end{{document}}).
  82. --[no-]rest-doc Create (or not) <modulename>module.rst.
  83. Default is --no-rest-doc.
  84. --debug-capi Create C/API code that reports the state of the wrappers
  85. during runtime. Useful for debugging.
  86. --[no-]wrap-functions Create Fortran subroutine wrappers to Fortran 77
  87. functions. --wrap-functions is default because it ensures
  88. maximum portability/compiler independence.
  89. --include-paths <path1>:<path2>:... Search include files from the given
  90. directories.
  91. --help-link [..] List system resources found by system_info.py. See also
  92. --link-<resource> switch below. [..] is optional list
  93. of resources names. E.g. try 'f2py --help-link lapack_opt'.
  94. --f2cmap <filename> Load Fortran-to-Python KIND specification from the given
  95. file. Default: .f2py_f2cmap in current directory.
  96. --quiet Run quietly.
  97. --verbose Run with extra verbosity.
  98. --skip-empty-wrappers Only generate wrapper files when needed.
  99. -v Print f2py version ID and exit.
  100. build backend options (only effective with -c):
  101. --fcompiler= Specify Fortran compiler type by vendor
  102. --compiler= Specify C compiler type (as defined by distutils)
  103. --help-fcompiler List available Fortran compilers and exit
  104. --f77exec= Specify the path to F77 compiler
  105. --f90exec= Specify the path to F90 compiler
  106. --f77flags= Specify F77 compiler flags
  107. --f90flags= Specify F90 compiler flags
  108. --opt= Specify optimization flags
  109. --arch= Specify architecture specific optimization flags
  110. --noopt Compile without optimization
  111. --noarch Compile without arch-dependent optimization
  112. --debug Compile with debugging information
  113. --dep <dependency>
  114. Specify a meson dependency for the module. This may
  115. be passed multiple times for multiple dependencies.
  116. Dependencies are stored in a list for further processing.
  117. Example: --dep lapack --dep scalapack
  118. This will identify "lapack" and "scalapack" as dependencies
  119. and remove them from argv, leaving a dependencies list
  120. containing ["lapack", "scalapack"].
  121. --backend <backend_type>
  122. Specify the build backend for the compilation process.
  123. The supported backends are 'meson' and 'distutils'.
  124. If not specified, defaults to 'distutils'. On
  125. Python 3.12 or higher, the default is 'meson'.
  126. Extra options (only effective with -c):
  127. --link-<resource> Link extension module with <resource> as defined
  128. by numpy.distutils/system_info.py. E.g. to link
  129. with optimized LAPACK libraries (vecLib on MacOSX,
  130. ATLAS elsewhere), use --link-lapack_opt.
  131. See also --help-link switch.
  132. -L/path/to/lib/ -l<libname>
  133. -D<define> -U<name>
  134. -I/path/to/include/
  135. <filename>.o <filename>.so <filename>.a
  136. Using the following macros may be required with non-gcc Fortran
  137. compilers:
  138. -DPREPEND_FORTRAN -DNO_APPEND_FORTRAN -DUPPERCASE_FORTRAN
  139. -DUNDERSCORE_G77
  140. When using -DF2PY_REPORT_ATEXIT, a performance report of F2PY
  141. interface is printed out at exit (platforms: Linux).
  142. When using -DF2PY_REPORT_ON_ARRAY_COPY=<int>, a message is
  143. sent to stderr whenever F2PY interface makes a copy of an
  144. array. Integer <int> sets the threshold for array sizes when
  145. a message should be shown.
  146. Version: {f2py_version}
  147. numpy Version: {numpy_version}
  148. Requires: Python 3.5 or higher.
  149. License: NumPy license (see LICENSE.txt in the NumPy source code)
  150. Copyright 1999 - 2011 Pearu Peterson all rights reserved.
  151. https://web.archive.org/web/20140822061353/http://cens.ioc.ee/projects/f2py2e"""
  152. def scaninputline(inputline):
  153. files, skipfuncs, onlyfuncs, debug = [], [], [], []
  154. f, f2, f3, f5, f6, f7, f8, f9, f10 = 1, 0, 0, 0, 0, 0, 0, 0, 0
  155. verbose = 1
  156. emptygen = True
  157. dolc = -1
  158. dolatexdoc = 0
  159. dorestdoc = 0
  160. wrapfuncs = 1
  161. buildpath = '.'
  162. include_paths = []
  163. signsfile, modulename = None, None
  164. options = {'buildpath': buildpath,
  165. 'coutput': None,
  166. 'f2py_wrapper_output': None}
  167. for l in inputline:
  168. if l == '':
  169. pass
  170. elif l == 'only:':
  171. f = 0
  172. elif l == 'skip:':
  173. f = -1
  174. elif l == ':':
  175. f = 1
  176. elif l[:8] == '--debug-':
  177. debug.append(l[8:])
  178. elif l == '--lower':
  179. dolc = 1
  180. elif l == '--build-dir':
  181. f6 = 1
  182. elif l == '--no-lower':
  183. dolc = 0
  184. elif l == '--quiet':
  185. verbose = 0
  186. elif l == '--verbose':
  187. verbose += 1
  188. elif l == '--latex-doc':
  189. dolatexdoc = 1
  190. elif l == '--no-latex-doc':
  191. dolatexdoc = 0
  192. elif l == '--rest-doc':
  193. dorestdoc = 1
  194. elif l == '--no-rest-doc':
  195. dorestdoc = 0
  196. elif l == '--wrap-functions':
  197. wrapfuncs = 1
  198. elif l == '--no-wrap-functions':
  199. wrapfuncs = 0
  200. elif l == '--short-latex':
  201. options['shortlatex'] = 1
  202. elif l == '--coutput':
  203. f8 = 1
  204. elif l == '--f2py-wrapper-output':
  205. f9 = 1
  206. elif l == '--f2cmap':
  207. f10 = 1
  208. elif l == '--overwrite-signature':
  209. options['h-overwrite'] = 1
  210. elif l == '-h':
  211. f2 = 1
  212. elif l == '-m':
  213. f3 = 1
  214. elif l[:2] == '-v':
  215. print(f2py_version)
  216. sys.exit()
  217. elif l == '--show-compilers':
  218. f5 = 1
  219. elif l[:8] == '-include':
  220. cfuncs.outneeds['userincludes'].append(l[9:-1])
  221. cfuncs.userincludes[l[9:-1]] = '#include ' + l[8:]
  222. elif l[:15] in '--include_paths':
  223. outmess(
  224. 'f2py option --include_paths is deprecated, use --include-paths instead.\n')
  225. f7 = 1
  226. elif l[:15] in '--include-paths':
  227. # Similar to using -I with -c, however this is
  228. # also used during generation of wrappers
  229. f7 = 1
  230. elif l == '--skip-empty-wrappers':
  231. emptygen = False
  232. elif l[0] == '-':
  233. errmess('Unknown option %s\n' % repr(l))
  234. sys.exit()
  235. elif f2:
  236. f2 = 0
  237. signsfile = l
  238. elif f3:
  239. f3 = 0
  240. modulename = l
  241. elif f6:
  242. f6 = 0
  243. buildpath = l
  244. elif f7:
  245. f7 = 0
  246. include_paths.extend(l.split(os.pathsep))
  247. elif f8:
  248. f8 = 0
  249. options["coutput"] = l
  250. elif f9:
  251. f9 = 0
  252. options["f2py_wrapper_output"] = l
  253. elif f10:
  254. f10 = 0
  255. options["f2cmap_file"] = l
  256. elif f == 1:
  257. try:
  258. with open(l):
  259. pass
  260. files.append(l)
  261. except OSError as detail:
  262. errmess(f'OSError: {detail!s}. Skipping file "{l!s}".\n')
  263. elif f == -1:
  264. skipfuncs.append(l)
  265. elif f == 0:
  266. onlyfuncs.append(l)
  267. if not f5 and not files and not modulename:
  268. print(__usage__)
  269. sys.exit()
  270. if not os.path.isdir(buildpath):
  271. if not verbose:
  272. outmess('Creating build directory %s\n' % (buildpath))
  273. os.mkdir(buildpath)
  274. if signsfile:
  275. signsfile = os.path.join(buildpath, signsfile)
  276. if signsfile and os.path.isfile(signsfile) and 'h-overwrite' not in options:
  277. errmess(
  278. 'Signature file "%s" exists!!! Use --overwrite-signature to overwrite.\n' % (signsfile))
  279. sys.exit()
  280. options['emptygen'] = emptygen
  281. options['debug'] = debug
  282. options['verbose'] = verbose
  283. if dolc == -1 and not signsfile:
  284. options['do-lower'] = 0
  285. else:
  286. options['do-lower'] = dolc
  287. if modulename:
  288. options['module'] = modulename
  289. if signsfile:
  290. options['signsfile'] = signsfile
  291. if onlyfuncs:
  292. options['onlyfuncs'] = onlyfuncs
  293. if skipfuncs:
  294. options['skipfuncs'] = skipfuncs
  295. options['dolatexdoc'] = dolatexdoc
  296. options['dorestdoc'] = dorestdoc
  297. options['wrapfuncs'] = wrapfuncs
  298. options['buildpath'] = buildpath
  299. options['include_paths'] = include_paths
  300. options.setdefault('f2cmap_file', None)
  301. return files, options
  302. def callcrackfortran(files, options):
  303. rules.options = options
  304. crackfortran.debug = options['debug']
  305. crackfortran.verbose = options['verbose']
  306. if 'module' in options:
  307. crackfortran.f77modulename = options['module']
  308. if 'skipfuncs' in options:
  309. crackfortran.skipfuncs = options['skipfuncs']
  310. if 'onlyfuncs' in options:
  311. crackfortran.onlyfuncs = options['onlyfuncs']
  312. crackfortran.include_paths[:] = options['include_paths']
  313. crackfortran.dolowercase = options['do-lower']
  314. postlist = crackfortran.crackfortran(files)
  315. if 'signsfile' in options:
  316. outmess('Saving signatures to file "%s"\n' % (options['signsfile']))
  317. pyf = crackfortran.crack2fortran(postlist)
  318. if options['signsfile'][-6:] == 'stdout':
  319. sys.stdout.write(pyf)
  320. else:
  321. with open(options['signsfile'], 'w') as f:
  322. f.write(pyf)
  323. if options["coutput"] is None:
  324. for mod in postlist:
  325. mod["coutput"] = "%smodule.c" % mod["name"]
  326. else:
  327. for mod in postlist:
  328. mod["coutput"] = options["coutput"]
  329. if options["f2py_wrapper_output"] is None:
  330. for mod in postlist:
  331. mod["f2py_wrapper_output"] = "%s-f2pywrappers.f" % mod["name"]
  332. else:
  333. for mod in postlist:
  334. mod["f2py_wrapper_output"] = options["f2py_wrapper_output"]
  335. return postlist
  336. def buildmodules(lst):
  337. cfuncs.buildcfuncs()
  338. outmess('Building modules...\n')
  339. modules, mnames, isusedby = [], [], {}
  340. for item in lst:
  341. if '__user__' in item['name']:
  342. cb_rules.buildcallbacks(item)
  343. else:
  344. if 'use' in item:
  345. for u in item['use'].keys():
  346. if u not in isusedby:
  347. isusedby[u] = []
  348. isusedby[u].append(item['name'])
  349. modules.append(item)
  350. mnames.append(item['name'])
  351. ret = {}
  352. for module, name in zip(modules, mnames):
  353. if name in isusedby:
  354. outmess('\tSkipping module "%s" which is used by %s.\n' % (
  355. name, ','.join('"%s"' % s for s in isusedby[name])))
  356. else:
  357. um = []
  358. if 'use' in module:
  359. for u in module['use'].keys():
  360. if u in isusedby and u in mnames:
  361. um.append(modules[mnames.index(u)])
  362. else:
  363. outmess(
  364. f'\tModule "{name}" uses nonexisting "{u}" '
  365. 'which will be ignored.\n')
  366. ret[name] = {}
  367. dict_append(ret[name], rules.buildmodule(module, um))
  368. return ret
  369. def dict_append(d_out, d_in):
  370. for (k, v) in d_in.items():
  371. if k not in d_out:
  372. d_out[k] = []
  373. if isinstance(v, list):
  374. d_out[k] = d_out[k] + v
  375. else:
  376. d_out[k].append(v)
  377. def run_main(comline_list):
  378. """
  379. Equivalent to running::
  380. f2py <args>
  381. where ``<args>=string.join(<list>,' ')``, but in Python. Unless
  382. ``-h`` is used, this function returns a dictionary containing
  383. information on generated modules and their dependencies on source
  384. files.
  385. You cannot build extension modules with this function, that is,
  386. using ``-c`` is not allowed. Use the ``compile`` command instead.
  387. Examples
  388. --------
  389. The command ``f2py -m scalar scalar.f`` can be executed from Python as
  390. follows.
  391. .. literalinclude:: ../../source/f2py/code/results/run_main_session.dat
  392. :language: python
  393. """
  394. crackfortran.reset_global_f2py_vars()
  395. f2pydir = os.path.dirname(os.path.abspath(cfuncs.__file__))
  396. fobjhsrc = os.path.join(f2pydir, 'src', 'fortranobject.h')
  397. fobjcsrc = os.path.join(f2pydir, 'src', 'fortranobject.c')
  398. files, options = scaninputline(comline_list)
  399. auxfuncs.options = options
  400. capi_maps.load_f2cmap_file(options['f2cmap_file'])
  401. postlist = callcrackfortran(files, options)
  402. isusedby = {}
  403. for plist in postlist:
  404. if 'use' in plist:
  405. for u in plist['use'].keys():
  406. if u not in isusedby:
  407. isusedby[u] = []
  408. isusedby[u].append(plist['name'])
  409. for plist in postlist:
  410. if plist['block'] == 'python module' and '__user__' in plist['name']:
  411. if plist['name'] in isusedby:
  412. # if not quiet:
  413. outmess(
  414. f'Skipping Makefile build for module "{plist["name"]}" '
  415. 'which is used by {}\n'.format(
  416. ','.join(f'"{s}"' for s in isusedby[plist['name']])))
  417. if 'signsfile' in options:
  418. if options['verbose'] > 1:
  419. outmess(
  420. 'Stopping. Edit the signature file and then run f2py on the signature file: ')
  421. outmess('%s %s\n' %
  422. (os.path.basename(sys.argv[0]), options['signsfile']))
  423. return
  424. for plist in postlist:
  425. if plist['block'] != 'python module':
  426. if 'python module' not in options:
  427. errmess(
  428. 'Tip: If your original code is Fortran source then you must use -m option.\n')
  429. raise TypeError('All blocks must be python module blocks but got %s' % (
  430. repr(plist['block'])))
  431. auxfuncs.debugoptions = options['debug']
  432. f90mod_rules.options = options
  433. auxfuncs.wrapfuncs = options['wrapfuncs']
  434. ret = buildmodules(postlist)
  435. for mn in ret.keys():
  436. dict_append(ret[mn], {'csrc': fobjcsrc, 'h': fobjhsrc})
  437. return ret
  438. def filter_files(prefix, suffix, files, remove_prefix=None):
  439. """
  440. Filter files by prefix and suffix.
  441. """
  442. filtered, rest = [], []
  443. match = re.compile(prefix + r'.*' + suffix + r'\Z').match
  444. if remove_prefix:
  445. ind = len(prefix)
  446. else:
  447. ind = 0
  448. for file in [x.strip() for x in files]:
  449. if match(file):
  450. filtered.append(file[ind:])
  451. else:
  452. rest.append(file)
  453. return filtered, rest
  454. def get_prefix(module):
  455. p = os.path.dirname(os.path.dirname(module.__file__))
  456. return p
  457. def preparse_sysargv():
  458. # To keep backwards bug compatibility, newer flags are handled by argparse,
  459. # and `sys.argv` is passed to the rest of `f2py` as is.
  460. parser = argparse.ArgumentParser(add_help=False)
  461. parser.add_argument("--dep", action="append", dest="dependencies")
  462. parser.add_argument("--backend", choices=['meson', 'distutils'], default='distutils')
  463. args, remaining_argv = parser.parse_known_args()
  464. sys.argv = [sys.argv[0]] + remaining_argv
  465. backend_key = args.backend
  466. if sys.version_info >= (3, 12) and backend_key == 'distutils':
  467. outmess('Cannot use distutils backend with Python 3.12, using meson backend instead.')
  468. backend_key = 'meson'
  469. return {
  470. "dependencies": args.dependencies or [],
  471. "backend": backend_key
  472. }
  473. def run_compile():
  474. """
  475. Do it all in one call!
  476. """
  477. import tempfile
  478. # Collect dependency flags, preprocess sys.argv
  479. argy = preparse_sysargv()
  480. dependencies = argy["dependencies"]
  481. backend_key = argy["backend"]
  482. build_backend = f2py_build_generator(backend_key)
  483. i = sys.argv.index('-c')
  484. del sys.argv[i]
  485. remove_build_dir = 0
  486. try:
  487. i = sys.argv.index('--build-dir')
  488. except ValueError:
  489. i = None
  490. if i is not None:
  491. build_dir = sys.argv[i + 1]
  492. del sys.argv[i + 1]
  493. del sys.argv[i]
  494. else:
  495. remove_build_dir = 1
  496. build_dir = tempfile.mkdtemp()
  497. _reg1 = re.compile(r'--link-')
  498. sysinfo_flags = [_m for _m in sys.argv[1:] if _reg1.match(_m)]
  499. sys.argv = [_m for _m in sys.argv if _m not in sysinfo_flags]
  500. if sysinfo_flags:
  501. sysinfo_flags = [f[7:] for f in sysinfo_flags]
  502. _reg2 = re.compile(
  503. r'--((no-|)(wrap-functions|lower)|debug-capi|quiet|skip-empty-wrappers)|-include')
  504. f2py_flags = [_m for _m in sys.argv[1:] if _reg2.match(_m)]
  505. sys.argv = [_m for _m in sys.argv if _m not in f2py_flags]
  506. f2py_flags2 = []
  507. fl = 0
  508. for a in sys.argv[1:]:
  509. if a in ['only:', 'skip:']:
  510. fl = 1
  511. elif a == ':':
  512. fl = 0
  513. if fl or a == ':':
  514. f2py_flags2.append(a)
  515. if f2py_flags2 and f2py_flags2[-1] != ':':
  516. f2py_flags2.append(':')
  517. f2py_flags.extend(f2py_flags2)
  518. sys.argv = [_m for _m in sys.argv if _m not in f2py_flags2]
  519. _reg3 = re.compile(
  520. r'--((f(90)?compiler(-exec|)|compiler)=|help-compiler)')
  521. flib_flags = [_m for _m in sys.argv[1:] if _reg3.match(_m)]
  522. sys.argv = [_m for _m in sys.argv if _m not in flib_flags]
  523. _reg4 = re.compile(
  524. r'--((f(77|90)(flags|exec)|opt|arch)=|(debug|noopt|noarch|help-fcompiler))')
  525. fc_flags = [_m for _m in sys.argv[1:] if _reg4.match(_m)]
  526. sys.argv = [_m for _m in sys.argv if _m not in fc_flags]
  527. del_list = []
  528. for s in flib_flags:
  529. v = '--fcompiler='
  530. if s[:len(v)] == v:
  531. from numpy.distutils import fcompiler
  532. fcompiler.load_all_fcompiler_classes()
  533. allowed_keys = list(fcompiler.fcompiler_class.keys())
  534. nv = ov = s[len(v):].lower()
  535. if ov not in allowed_keys:
  536. vmap = {} # XXX
  537. try:
  538. nv = vmap[ov]
  539. except KeyError:
  540. if ov not in vmap.values():
  541. print('Unknown vendor: "%s"' % (s[len(v):]))
  542. nv = ov
  543. i = flib_flags.index(s)
  544. flib_flags[i] = '--fcompiler=' + nv
  545. continue
  546. for s in del_list:
  547. i = flib_flags.index(s)
  548. del flib_flags[i]
  549. assert len(flib_flags) <= 2, repr(flib_flags)
  550. _reg5 = re.compile(r'--(verbose)')
  551. setup_flags = [_m for _m in sys.argv[1:] if _reg5.match(_m)]
  552. sys.argv = [_m for _m in sys.argv if _m not in setup_flags]
  553. if '--quiet' in f2py_flags:
  554. setup_flags.append('--quiet')
  555. modulename = 'untitled'
  556. sources = sys.argv[1:]
  557. for optname in ['--include_paths', '--include-paths', '--f2cmap']:
  558. if optname in sys.argv:
  559. i = sys.argv.index(optname)
  560. f2py_flags.extend(sys.argv[i:i + 2])
  561. del sys.argv[i + 1], sys.argv[i]
  562. sources = sys.argv[1:]
  563. pyf_files = []
  564. if '-m' in sys.argv:
  565. i = sys.argv.index('-m')
  566. modulename = sys.argv[i + 1]
  567. del sys.argv[i + 1], sys.argv[i]
  568. sources = sys.argv[1:]
  569. else:
  570. pyf_files, _sources = filter_files('', '[.]pyf([.]src|)', sources)
  571. sources = pyf_files + _sources
  572. for f in pyf_files:
  573. modulename = auxfuncs.get_f2py_modulename(f)
  574. if modulename:
  575. break
  576. extra_objects, sources = filter_files('', '[.](o|a|so|dylib)', sources)
  577. include_dirs, sources = filter_files('-I', '', sources, remove_prefix=1)
  578. library_dirs, sources = filter_files('-L', '', sources, remove_prefix=1)
  579. libraries, sources = filter_files('-l', '', sources, remove_prefix=1)
  580. undef_macros, sources = filter_files('-U', '', sources, remove_prefix=1)
  581. define_macros, sources = filter_files('-D', '', sources, remove_prefix=1)
  582. for i in range(len(define_macros)):
  583. name_value = define_macros[i].split('=', 1)
  584. if len(name_value) == 1:
  585. name_value.append(None)
  586. if len(name_value) == 2:
  587. define_macros[i] = tuple(name_value)
  588. else:
  589. print('Invalid use of -D:', name_value)
  590. # Construct wrappers / signatures / things
  591. if backend_key == 'meson':
  592. outmess('Using meson backend\nWill pass --lower to f2py\nSee https://numpy.org/doc/stable/f2py/buildtools/meson.html')
  593. f2py_flags.append('--lower')
  594. if pyf_files:
  595. run_main(f" {' '.join(f2py_flags)} {' '.join(pyf_files)}".split())
  596. else:
  597. run_main(f" {' '.join(f2py_flags)} -m {modulename} {' '.join(sources)}".split())
  598. # Now use the builder
  599. builder = build_backend(
  600. modulename,
  601. sources,
  602. extra_objects,
  603. build_dir,
  604. include_dirs,
  605. library_dirs,
  606. libraries,
  607. define_macros,
  608. undef_macros,
  609. f2py_flags,
  610. sysinfo_flags,
  611. fc_flags,
  612. flib_flags,
  613. setup_flags,
  614. remove_build_dir,
  615. {"dependencies": dependencies},
  616. )
  617. builder.compile()
  618. def main():
  619. if '--help-link' in sys.argv[1:]:
  620. sys.argv.remove('--help-link')
  621. from numpy.distutils.system_info import show_all
  622. show_all()
  623. return
  624. # Probably outdated options that were not working before 1.16
  625. if '--g3-numpy' in sys.argv[1:]:
  626. sys.stderr.write("G3 f2py support is not implemented, yet.\\n")
  627. sys.exit(1)
  628. elif '--2e-numeric' in sys.argv[1:]:
  629. sys.argv.remove('--2e-numeric')
  630. elif '--2e-numarray' in sys.argv[1:]:
  631. # Note that this errors becaust the -DNUMARRAY argument is
  632. # not recognized. Just here for back compatibility and the
  633. # error message.
  634. sys.argv.append("-DNUMARRAY")
  635. sys.argv.remove('--2e-numarray')
  636. elif '--2e-numpy' in sys.argv[1:]:
  637. sys.argv.remove('--2e-numpy')
  638. else:
  639. pass
  640. if '-c' in sys.argv[1:]:
  641. run_compile()
  642. else:
  643. run_main(sys.argv[1:])