diff -ur a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py --- a/Lib/distutils/command/install.py 2018-06-27 05:07:35.000000000 +0200 +++ b/Lib/distutils/command/install.py 2018-08-28 02:10:54.444538628 +0200 @@ -29,15 +29,15 @@ INSTALL_SCHEMES = { 'unix_prefix': { - 'purelib': '$base/lib/python$py_version_short/site-packages', - 'platlib': '$platbase/lib/python$py_version_short/site-packages', + 'purelib': '$base/$platlibdir/python$py_version_short/site-packages', + 'platlib': '$platbase/$platlibdir/python$py_version_short/site-packages', 'headers': '$base/include/python$py_version_short$abiflags/$dist_name', 'scripts': '$base/bin', 'data' : '$base', }, 'unix_home': { - 'purelib': '$base/lib/python', - 'platlib': '$base/lib/python', + 'purelib': '$base/$platlibdir/python', + 'platlib': '$base/$platlibdir/python', 'headers': '$base/include/python/$dist_name', 'scripts': '$base/bin', 'data' : '$base', @@ -281,7 +281,7 @@ # about needing recursive variable expansion (shudder). py_version = sys.version.split()[0] - (prefix, exec_prefix) = get_config_vars('prefix', 'exec_prefix') + (prefix, exec_prefix, platlibdir) = get_config_vars('prefix', 'exec_prefix', 'platlibdir') try: abiflags = sys.abiflags except AttributeError: @@ -298,6 +298,7 @@ 'sys_exec_prefix': exec_prefix, 'exec_prefix': exec_prefix, 'abiflags': abiflags, + 'platlibdir': platlibdir, } if HAS_USER_SITE: diff -ur a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py --- a/Lib/distutils/sysconfig.py 2018-06-27 05:07:35.000000000 +0200 +++ b/Lib/distutils/sysconfig.py 2018-08-28 02:10:54.444538628 +0200 @@ -129,8 +129,9 @@ prefix = plat_specific and EXEC_PREFIX or PREFIX if os.name == "posix": + libdir = plat_specific and get_config_var("platlibdir") or "lib" libpython = os.path.join(prefix, - "lib", "python" + get_python_version()) + libdir, "python" + get_python_version()) if standard_lib: return libpython else: diff -ur a/Lib/pydoc.py b/Lib/pydoc.py --- a/Lib/pydoc.py 2018-06-27 05:07:35.000000000 +0200 +++ b/Lib/pydoc.py 2018-08-28 02:10:54.444538628 +0200 @@ -66,6 +66,7 @@ import platform import re import sys +import sysconfig import time import tokenize import urllib.parse @@ -398,9 +399,7 @@ docmodule = docclass = docroutine = docother = docproperty = docdata = fail - def getdocloc(self, object, - basedir=os.path.join(sys.base_exec_prefix, "lib", - "python%d.%d" % sys.version_info[:2])): + def getdocloc(self, object, basedir=sysconfig.get_path('stdlib')): """Return the location of module docs or None""" try: diff -ur a/Lib/site.py b/Lib/site.py --- a/Lib/site.py 2018-06-27 05:07:35.000000000 +0200 +++ b/Lib/site.py 2018-08-28 02:11:44.622354660 +0200 @@ -264,14 +264,16 @@ # Same to sysconfig.get_path('purelib', os.name+'_user') def _get_path(userbase): version = sys.version_info + from sysconfig import get_config_var + platlibdir = get_config_var("platlibdir") if os.name == 'nt': return f'{userbase}\\Python{version[0]}{version[1]}\\site-packages' if sys.platform == 'darwin' and sys._framework: - return f'{userbase}/lib/python/site-packages' + return f'{userbase}/{platlibdir}/python/site-packages' - return f'{userbase}/lib/python{version[0]}.{version[1]}/site-packages' + return f'{userbase}/{platlibdir}/python{version[0]}.{version[1]}/site-packages' def getuserbase(): @@ -334,7 +336,9 @@ seen.add(prefix) if os.sep == '/': - sitepackages.append(os.path.join(prefix, "lib", + from sysconfig import get_config_var + platlibdir = get_config_var("platlibdir") + sitepackages.append(os.path.join(prefix, platlibdir, "python%d.%d" % sys.version_info[:2], "site-packages")) else: diff -ur a/Lib/sysconfig.py b/Lib/sysconfig.py --- a/Lib/sysconfig.py 2018-06-27 05:07:35.000000000 +0200 +++ b/Lib/sysconfig.py 2018-08-28 02:10:54.444538628 +0200 @@ -20,10 +20,10 @@ _INSTALL_SCHEMES = { 'posix_prefix': { - 'stdlib': '{installed_base}/lib/python{py_version_short}', - 'platstdlib': '{platbase}/lib/python{py_version_short}', + 'stdlib': '{installed_base}/{platlibdir}/python{py_version_short}', + 'platstdlib': '{platbase}/{platlibdir}/python{py_version_short}', 'purelib': '{base}/lib/python{py_version_short}/site-packages', - 'platlib': '{platbase}/lib/python{py_version_short}/site-packages', + 'platlib': '{platbase}/{platlibdir}/python{py_version_short}/site-packages', 'include': '{installed_base}/include/python{py_version_short}{abiflags}', 'platinclude': diff -ur a/Lib/test/test_site.py b/Lib/test/test_site.py --- a/Lib/test/test_site.py 2018-06-27 05:07:35.000000000 +0200 +++ b/Lib/test/test_site.py 2018-08-28 02:10:54.445538644 +0200 @@ -263,8 +263,9 @@ dirs = site.getsitepackages() if os.sep == '/': # OS X, Linux, FreeBSD, etc - self.assertEqual(len(dirs), 1) - wanted = os.path.join('xoxo', 'lib', + platlibdir = sysconfig.get_config_var('platlibdir') + self.assertTrue(len(dirs) in (1,2)) + wanted = os.path.join('xoxo', platlibdir, 'python%d.%d' % sys.version_info[:2], 'site-packages') self.assertEqual(dirs[0], wanted) diff -ur a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py --- a/Lib/test/test_sysconfig.py 2018-06-27 05:07:35.000000000 +0200 +++ b/Lib/test/test_sysconfig.py 2018-08-28 02:10:54.445538644 +0200 @@ -258,6 +258,7 @@ # is similar to the global posix_prefix one base = get_config_var('base') user = get_config_var('userbase') + platlibdir = get_config_var("platlibdir") # the global scheme mirrors the distinction between prefix and # exec-prefix but not the user scheme, so we have to adapt the paths # before comparing (issue #9100) @@ -272,8 +273,19 @@ # before comparing global_path = global_path.replace(sys.base_prefix, sys.prefix) base = base.replace(sys.base_prefix, sys.prefix) + + if platlibdir != "lib": + platbase = os.path.join(base, platlibdir) + purebase = os.path.join(base, "lib") + userlib = os.path.join(user, "lib") + # replace platbase first because usually purebase is a prefix of platbase + # /usr/lib is prefix of /usr/lib64 and would get replaced first + modified_path = global_path.replace(platbase, userlib, 1).replace(purebase, userlib, 1) + else: + modified_path = global_path.replace(base, user, 1) + user_path = get_path(name, 'posix_user') - self.assertEqual(user_path, global_path.replace(base, user, 1)) + self.assertEqual(user_path, modified_path) def test_main(self): # just making sure _main() runs and returns things in the stdout diff -ur a/Lib/trace.py b/Lib/trace.py --- a/Lib/trace.py 2018-06-27 05:07:35.000000000 +0200 +++ b/Lib/trace.py 2018-08-28 02:10:54.445538644 +0200 @@ -53,6 +53,7 @@ import os import re import sys +import sysconfig import token import tokenize import inspect @@ -665,9 +666,8 @@ opts = parser.parse_args() if opts.ignore_dir: - rel_path = 'lib', 'python{0.major}.{0.minor}'.format(sys.version_info) - _prefix = os.path.join(sys.base_prefix, *rel_path) - _exec_prefix = os.path.join(sys.base_exec_prefix, *rel_path) + _prefix = sysconfig.get_path("stdlib") + _exec_prefix = sysconfig.get_path("platstdlib") def parse_ignore_dir(s): s = os.path.expanduser(os.path.expandvars(s)) diff -ur a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in 2018-06-27 05:07:35.000000000 +0200 +++ b/Makefile.pre.in 2018-08-28 02:10:54.445538644 +0200 @@ -128,13 +128,16 @@ # Install prefix for data files datarootdir= @datarootdir@ +# Name of "lib" directory under prefix +platlibdir= @platlibdir@ + # Expanded directories BINDIR= @bindir@ LIBDIR= @libdir@ MANDIR= @mandir@ INCLUDEDIR= @includedir@ CONFINCLUDEDIR= $(exec_prefix)/include -SCRIPTDIR= $(prefix)/lib +SCRIPTDIR= @libdir@ ABIFLAGS= @ABIFLAGS@ # Detailed destination directories @@ -761,6 +764,7 @@ -DEXEC_PREFIX='"$(exec_prefix)"' \ -DVERSION='"$(VERSION)"' \ -DVPATH='"$(VPATH)"' \ + -DPLATLIBDIR='"$(platlibdir)"' \ -o $@ $(srcdir)/Modules/getpath.c Programs/python.o: $(srcdir)/Programs/python.c diff -ur a/Modules/getpath.c b/Modules/getpath.c --- a/Modules/getpath.c 2018-06-27 05:07:35.000000000 +0200 +++ b/Modules/getpath.c 2018-08-28 02:10:54.445538644 +0200 @@ -52,9 +52,10 @@ * pybuilddir.txt. If the landmark is found, we're done. * * For the remaining steps, the prefix landmark will always be - * lib/python$VERSION/os.py and the exec_prefix will always be - * lib/python$VERSION/lib-dynload, where $VERSION is Python's version - * number as supplied by the Makefile. Note that this means that no more + * $lib/python$VERSION/os.py and the exec_prefix will always be + * $lib/python$VERSION/lib-dynload, where $VERSION is Python's version + * number and $lib is PLATLIBDIR as supplied by the Makefile. (usually + * "lib", "lib32" or "lib64"). Note that this means that no more * build directory checking is performed; if the first step did not find * the landmarks, the assumption is that python is running from an * installed setup. @@ -83,7 +84,7 @@ * containing the shared library modules is appended. The environment * variable $PYTHONPATH is inserted in front of it all. Finally, the * prefix and exec_prefix globals are tweaked so they reflect the values - * expected by other code, by stripping the "lib/python$VERSION/..." stuff + * expected by other code, by stripping the "$lib/python$VERSION/..." stuff * off. If either points to the build directory, the globals are reset to * the corresponding preprocessor variables (so sys.prefix will reflect the * installation location, even though sys.path points into the build @@ -102,8 +103,8 @@ #endif -#if !defined(PREFIX) || !defined(EXEC_PREFIX) || !defined(VERSION) || !defined(VPATH) -#error "PREFIX, EXEC_PREFIX, VERSION, and VPATH must be constant defined" +#if !defined(PREFIX) || !defined(EXEC_PREFIX) || !defined(VERSION) || !defined(VPATH) || !defined(PLATLIBDIR) +#error "PREFIX, EXEC_PREFIX, VERSION, VPATH and PLATLIBDIR must be constant defined" #endif #ifndef LANDMARK @@ -500,7 +501,7 @@ "Could not find platform dependent libraries \n"); } wcsncpy(exec_prefix, calculate->exec_prefix, MAXPATHLEN); - joinpath(exec_prefix, L"lib/lib-dynload"); + joinpath(exec_prefix, PLATLIBDIR L"/lib-dynload"); } /* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */ } @@ -742,7 +743,7 @@ else { wcsncpy(calculate->zip_path, calculate->prefix, MAXPATHLEN); } - joinpath(calculate->zip_path, L"lib/python00.zip"); + joinpath(calculate->zip_path, PLATLIBDIR L"/python00.zip"); /* Replace "00" with version */ size_t bufsz = wcslen(calculate->zip_path); @@ -867,7 +868,7 @@ if (!calculate->prefix) { return DECODE_LOCALE_ERR("EXEC_PREFIX define", len); } - calculate->lib_python = Py_DecodeLocale("lib/python" VERSION, &len); + calculate->lib_python = Py_DecodeLocale(PLATLIBDIR "/python" VERSION, &len); if (!calculate->lib_python) { return DECODE_LOCALE_ERR("EXEC_PREFIX define", len); } diff -ur a/configure.ac b/configure.ac --- a/configure.ac 2018-06-27 05:07:35.000000000 +0200 +++ b/configure.ac 2018-08-28 02:10:54.446538660 +0200 @@ -4680,12 +4680,26 @@ LDVERSION='$(VERSION)$(ABIFLAGS)' AC_MSG_RESULT($LDVERSION) +# platlibdir must be defined before LIBPL definition +AC_MSG_CHECKING(for custom platlibdir) +AC_ARG_WITH(custom-platlibdir, + [AS_HELP_STRING([--with-custom-platlibdir=], + [set the platlibdir name to a custom string])], + [], + [with_custom_platlibdir=yes]) +AS_CASE($with_custom_platlibdir, + [yes],[platlibdir=`basename ${libdir}`], + [no],[platlibdir=lib], + [platlibdir=$with_custom_platlibdir]) +AC_MSG_RESULT($platlibdir) +AC_SUBST(platlibdir) + dnl define LIBPL after ABIFLAGS and LDVERSION is defined. AC_SUBST(PY_ENABLE_SHARED) if test x$PLATFORM_TRIPLET = x; then - LIBPL='$(prefix)'"/lib/python${VERSION}/config-${LDVERSION}" + LIBPL='$(prefix)'"/${platlibdir}/python${VERSION}/config-${LDVERSION}" else - LIBPL='$(prefix)'"/lib/python${VERSION}/config-${LDVERSION}-${PLATFORM_TRIPLET}" + LIBPL='$(prefix)'"/${platlibdir}/python${VERSION}/config-${LDVERSION}-${PLATFORM_TRIPLET}" fi AC_SUBST(LIBPL)