Skip to content

bpo-44351: Restore back parse_makefile in distutils.sysconfig #26637

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 107 additions & 4 deletions Lib/distutils/sysconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
_PYTHON_BUILD as python_build,
_init_posix as sysconfig_init_posix,
parse_config_h as sysconfig_parse_config_h,
_parse_makefile as sysconfig_parse_makefile,

_init_non_posix,
_is_python_source_dir,
Expand Down Expand Up @@ -68,14 +67,118 @@ def parse_config_h(fp, g=None):
return sysconfig_parse_config_h(fp, vars=g)


def parse_makefile(fn, g=None):
return sysconfig_parse_makefile(fn, vars=g, keep_unresolved=False)

_python_build = partial(is_python_build, check_home=True)
_init_posix = partial(sysconfig_init_posix, _config_vars)
_init_nt = partial(_init_non_posix, _config_vars)


# Similar function is also implemented in sysconfig as _parse_makefile
# but without the parsing capabilities of distutils.text_file.TextFile.
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 = re.match(_variable_rx, 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 = re.search(_findvar1_rx, value) or re.search(_findvar2_rx, 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


# Following functions are deprecated together with this module and they
# have no direct replacement

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Restore back :func:`parse_makefile` in :mod:`distutils.sysconfig` because it
behaves differently than the similar implementation in :mod:`sysconfig`.