I wrote:
> Based on the buildfarm results so far, the problem can be described
> as "some installations say /usr/local when they should have said /usr".
> I experimented with the attached delta patch and it fixes the problem
> on my Debian 9 image. (I don't know Python, so there may be a better
> way to do this.) We'd have to also bump the minimum 3.x version to
> 3.2, but that seems very unlikely to bother anyone.
I did a little more digging into this. The python2 package on
my Deb9 (actually Raspbian) system says it is 2.7.13, but
/usr/lib/python2.7/sysconfig.py is different from what I find in
a virgin Python 2.7.13 tarball, as per attached diff. I conclude
that somebody at Debian decided that Python should live under
/usr/local, and changed sysconfig.py to match, but then failed
to adjust the actual install scripts to agree, because there is
certainly nothing installed under /usr/local. (I don't know
enough about Debian packaging to find the smoking gun though;
what apt-get claims is the source package contains no trace of
this diff.) There's no sign of comparable changes in
/usr/lib/python3.5/sysconfig.py on the same machine, either.
So I think this can fairly be characterized as brain-dead packaging
error, and we should just hack around it as per my previous patch.
In other news, I switched prairiedog and gaur to python 3.2.
regards, tom lane
--- Python-2.7.13/Lib/sysconfig.py 2016-12-17 15:05:06.000000000 -0500
+++ /usr/lib/python2.7/sysconfig.py 2018-09-26 14:42:22.000000000 -0400
@@ -16,6 +16,26 @@ _INSTALL_SCHEMES = {
'scripts': '{base}/bin',
'data': '{base}',
},
+ 'posix_local': {
+ 'stdlib': '{base}/lib/python{py_version_short}',
+ 'platstdlib': '{platbase}/lib/python{py_version_short}',
+ 'purelib': '{base}/local/lib/python{py_version_short}/dist-packages',
+ 'platlib': '{platbase}/local/lib/python{py_version_short}/dist-packages',
+ 'include': '{base}/local/include/python{py_version_short}',
+ 'platinclude': '{platbase}/local/include/python{py_version_short}',
+ 'scripts': '{base}/local/bin',
+ 'data': '{base}/local',
+ },
+ 'deb_system': {
+ 'stdlib': '{base}/lib/python{py_version_short}',
+ 'platstdlib': '{platbase}/lib/python{py_version_short}',
+ 'purelib': '{base}/lib/python{py_version_short}/dist-packages',
+ 'platlib': '{platbase}/lib/python{py_version_short}/dist-packages',
+ 'include': '{base}/include/python{py_version_short}',
+ 'platinclude': '{platbase}/include/python{py_version_short}',
+ 'scripts': '{base}/bin',
+ 'data': '{base}',
+ },
'posix_home': {
'stdlib': '{base}/lib/python',
'platstdlib': '{base}/lib/python',
@@ -129,7 +149,7 @@ def is_python_build():
_PYTHON_BUILD = is_python_build()
if _PYTHON_BUILD:
- for scheme in ('posix_prefix', 'posix_home'):
+ for scheme in ('posix_prefix', 'posix_local', 'deb_system', 'posix_home'):
_INSTALL_SCHEMES[scheme]['include'] = '{projectbase}/Include'
_INSTALL_SCHEMES[scheme]['platinclude'] = '{srcdir}'
@@ -163,8 +183,11 @@ def _expand_vars(scheme, vars):
def _get_default_scheme():
if os.name == 'posix':
- # the default scheme for posix is posix_prefix
- return 'posix_prefix'
+ # the default scheme for posix on Debian/Ubuntu is posix_local
+ # FIXME: return dist-packages/posix_prefix only for
+ # is_default_prefix and 'PYTHONUSERBASE' not in os.environ and 'real_prefix' not in sys.__dict__
+ # is_default_prefix = not prefix or os.path.normpath(prefix) in ('/usr', '/usr/local')
+ return 'posix_local'
return os.name
def _getuserbase():
@@ -231,11 +254,19 @@ def _parse_makefile(filename, vars=None)
done[n] = v
# do variable interpolation here
- while notdone:
- for name in notdone.keys():
+ variables = list(notdone.keys())
+
+ # 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')
+
+ while len(variables) > 0:
+ for name in tuple(variables):
value = notdone[name]
m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
- if m:
+ if m is not None:
n = m.group(1)
found = True
if n in done:
@@ -246,23 +277,48 @@ def _parse_makefile(filename, vars=None)
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)
+ try:
+ value = int(value)
except ValueError:
done[name] = value.strip()
else:
done[name] = value
- del notdone[name]
+ variables.remove(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]
+ # bogus variable reference (e.g. "prefix=$/opt/python");
+ # just drop it since we can't deal
+ done[name] = value
+ variables.remove(name)
+
# strip spurious spaces
for k, v in done.items():
if isinstance(v, str):
@@ -277,7 +333,7 @@ def get_makefile_filename():
"""Return the path of the Makefile."""
if _PYTHON_BUILD:
return os.path.join(_PROJECT_BASE, "Makefile")
- return os.path.join(get_path('platstdlib'), "config", "Makefile")
+ return os.path.join(get_config_var('LIBPL'), "Makefile")
# Issue #22199: retain undocumented private name for compatibility
_get_makefile_filename = get_makefile_filename
@@ -409,7 +465,7 @@ def get_config_h_filename():
else:
inc_dir = _PROJECT_BASE
else:
- inc_dir = get_path('platinclude')
+ inc_dir = get_path('platinclude').replace("/usr/local","/usr",1)+(sys.pydebug and "_d" or "")
return os.path.join(inc_dir, 'pyconfig.h')
def get_scheme_names():
@@ -476,6 +532,12 @@ def get_config_vars(*args):
# the init-function.
_CONFIG_VARS['userbase'] = _getuserbase()
+ multiarch = get_config_var('MULTIARCH')
+ if multiarch:
+ _CONFIG_VARS['multiarchsubdir'] = '/' + multiarch
+ else:
+ _CONFIG_VARS['multiarchsubdir'] = ''
+
if 'srcdir' not in _CONFIG_VARS:
_CONFIG_VARS['srcdir'] = _PROJECT_BASE