134 lines
4.6 KiB
Diff
134 lines
4.6 KiB
Diff
|
diff --git a/config/gmakegen.py b/config/gmakegen.py
|
||
|
index cc42a25..ca286ac 100755
|
||
|
--- a/config/gmakegen.py
|
||
|
+++ b/config/gmakegen.py
|
||
|
@@ -1,12 +1,127 @@
|
||
|
#!/usr/bin/env python
|
||
|
|
||
|
import os
|
||
|
-from distutils.sysconfig import parse_makefile
|
||
|
import sys
|
||
|
import logging
|
||
|
sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
|
||
|
from collections import defaultdict
|
||
|
|
||
|
+
|
||
|
+# Embedded distutils.sysconfig.parse_makefile() from Python 3.9
|
||
|
+# To workaround https://bugs.python.org/issue44351
|
||
|
+import re
|
||
|
+# Regexes needed for parsing Makefile (and similar syntaxes,
|
||
|
+# like old-style Setup files).
|
||
|
+_variable_rx = re.compile(r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
|
||
|
+_findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
|
||
|
+_findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
|
||
|
+
|
||
|
+def parse_makefile(fn, g=None):
|
||
|
+ """Parse a Makefile-style file.
|
||
|
+
|
||
|
+ A dictionary containing name/value pairs is returned. If an
|
||
|
+ optional dictionary is passed in as the second argument, it is
|
||
|
+ used instead of a new dictionary.
|
||
|
+ """
|
||
|
+ from distutils.text_file import TextFile
|
||
|
+ fp = TextFile(fn, strip_comments=1, skip_blanks=1, join_lines=1, errors="surrogateescape")
|
||
|
+
|
||
|
+ if g is None:
|
||
|
+ g = {}
|
||
|
+ done = {}
|
||
|
+ notdone = {}
|
||
|
+
|
||
|
+ while True:
|
||
|
+ line = fp.readline()
|
||
|
+ if line is None: # eof
|
||
|
+ break
|
||
|
+ m = _variable_rx.match(line)
|
||
|
+ if m:
|
||
|
+ n, v = m.group(1, 2)
|
||
|
+ v = v.strip()
|
||
|
+ # `$$' is a literal `$' in make
|
||
|
+ tmpv = v.replace('$$', '')
|
||
|
+
|
||
|
+ if "$" in tmpv:
|
||
|
+ notdone[n] = v
|
||
|
+ else:
|
||
|
+ try:
|
||
|
+ v = int(v)
|
||
|
+ except ValueError:
|
||
|
+ # insert literal `$'
|
||
|
+ done[n] = v.replace('$$', '$')
|
||
|
+ else:
|
||
|
+ done[n] = v
|
||
|
+
|
||
|
+ # Variables with a 'PY_' prefix in the makefile. These need to
|
||
|
+ # be made available without that prefix through sysconfig.
|
||
|
+ # Special care is needed to ensure that variable expansion works, even
|
||
|
+ # if the expansion uses the name without a prefix.
|
||
|
+ renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
|
||
|
+
|
||
|
+ # do variable interpolation here
|
||
|
+ while notdone:
|
||
|
+ for name in list(notdone):
|
||
|
+ value = notdone[name]
|
||
|
+ m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
|
||
|
+ if m:
|
||
|
+ n = m.group(1)
|
||
|
+ found = True
|
||
|
+ if n in done:
|
||
|
+ item = str(done[n])
|
||
|
+ elif n in notdone:
|
||
|
+ # get it on a subsequent round
|
||
|
+ found = False
|
||
|
+ elif n in os.environ:
|
||
|
+ # do it like make: fall back to environment
|
||
|
+ item = os.environ[n]
|
||
|
+
|
||
|
+ elif n in renamed_variables:
|
||
|
+ if name.startswith('PY_') and name[3:] in renamed_variables:
|
||
|
+ item = ""
|
||
|
+
|
||
|
+ elif 'PY_' + n in notdone:
|
||
|
+ found = False
|
||
|
+
|
||
|
+ else:
|
||
|
+ item = str(done['PY_' + n])
|
||
|
+ else:
|
||
|
+ done[n] = item = ""
|
||
|
+ if found:
|
||
|
+ after = value[m.end():]
|
||
|
+ value = value[:m.start()] + item + after
|
||
|
+ if "$" in after:
|
||
|
+ notdone[name] = value
|
||
|
+ else:
|
||
|
+ try: value = int(value)
|
||
|
+ except ValueError:
|
||
|
+ done[name] = value.strip()
|
||
|
+ else:
|
||
|
+ done[name] = value
|
||
|
+ del notdone[name]
|
||
|
+
|
||
|
+ if name.startswith('PY_') \
|
||
|
+ and name[3:] in renamed_variables:
|
||
|
+
|
||
|
+ name = name[3:]
|
||
|
+ if name not in done:
|
||
|
+ done[name] = value
|
||
|
+ else:
|
||
|
+ # bogus variable reference; just drop it since we can't deal
|
||
|
+ del notdone[name]
|
||
|
+
|
||
|
+ fp.close()
|
||
|
+
|
||
|
+ # strip spurious spaces
|
||
|
+ for k, v in done.items():
|
||
|
+ if isinstance(v, str):
|
||
|
+ done[k] = v.strip()
|
||
|
+
|
||
|
+ # save the results in the global dictionary
|
||
|
+ g.update(done)
|
||
|
+ return g
|
||
|
+
|
||
|
+
|
||
|
AUTODIRS = set('ftn-auto ftn-custom f90-custom'.split()) # Automatically recurse into these, if they exist
|
||
|
SKIPDIRS = set('benchmarks build'.split()) # Skip these during the build
|
||
|
NOWARNDIRS = set('tests tutorials'.split()) # Do not warn about mismatch in these
|