|
109 | 109 | def _get_implementation():
|
110 | 110 | return 'Python'
|
111 | 111 |
|
| 112 | +def get_platform(): |
| 113 | + """Return a string that identifies the current platform. |
| 114 | +
|
| 115 | + This is used mainly to distinguish platform-specific build directories and |
| 116 | + platform-specific built distributions. Typically includes the OS name and |
| 117 | + version and the architecture (as supplied by 'os.uname()'), although the |
| 118 | + exact information included depends on the OS; on Linux, the kernel version |
| 119 | + isn't particularly important. |
| 120 | +
|
| 121 | + Examples of returned values: |
| 122 | + linux-i586 |
| 123 | + linux-alpha (?) |
| 124 | + solaris-2.6-sun4u |
| 125 | +
|
| 126 | + Windows will return one of: |
| 127 | + win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc) |
| 128 | + win32 (all others - specifically, sys.platform is returned) |
| 129 | +
|
| 130 | + For other non-POSIX platforms, currently just returns 'sys.platform'. |
| 131 | +
|
| 132 | + """ |
| 133 | + if os.name == 'nt': |
| 134 | + if 'amd64' in sys.version.lower(): |
| 135 | + return 'win-amd64' |
| 136 | + if '(arm)' in sys.version.lower(): |
| 137 | + return 'win-arm32' |
| 138 | + if '(arm64)' in sys.version.lower(): |
| 139 | + return 'win-arm64' |
| 140 | + return sys.platform |
| 141 | + |
| 142 | + if os.name != "posix" or not hasattr(os, 'uname'): |
| 143 | + # XXX what about the architecture? NT is Intel or Alpha |
| 144 | + return sys.platform |
| 145 | + |
| 146 | + # Set for cross builds explicitly |
| 147 | + if "_PYTHON_HOST_PLATFORM" in os.environ: |
| 148 | + return os.environ["_PYTHON_HOST_PLATFORM"] |
| 149 | + |
| 150 | + # Try to distinguish various flavours of Unix |
| 151 | + osname, host, release, version, machine = os.uname() |
| 152 | + |
| 153 | + # Convert the OS name to lowercase, remove '/' characters, and translate |
| 154 | + # spaces (for "Power Macintosh") |
| 155 | + osname = osname.lower().replace('/', '') |
| 156 | + machine = machine.replace(' ', '_') |
| 157 | + machine = machine.replace('/', '-') |
| 158 | + |
| 159 | + if osname[:5] == "linux": |
| 160 | + if sys.platform == "android": |
| 161 | + osname = "android" |
| 162 | + release = get_config_var("ANDROID_API_LEVEL") |
| 163 | + |
| 164 | + # Wheel tags use the ABI names from Android's own tools. |
| 165 | + machine = { |
| 166 | + "x86_64": "x86_64", |
| 167 | + "i686": "x86", |
| 168 | + "aarch64": "arm64_v8a", |
| 169 | + "armv7l": "armeabi_v7a", |
| 170 | + }[machine] |
| 171 | + else: |
| 172 | + # At least on Linux/Intel, 'machine' is the processor -- |
| 173 | + # i386, etc. |
| 174 | + # XXX what about Alpha, SPARC, etc? |
| 175 | + return f"{osname}-{machine}" |
| 176 | + elif osname[:5] == "sunos": |
| 177 | + if release[0] >= "5": # SunOS 5 == Solaris 2 |
| 178 | + osname = "solaris" |
| 179 | + release = f"{int(release[0]) - 3}.{release[2:]}" |
| 180 | + # We can't use "platform.architecture()[0]" because a |
| 181 | + # bootstrap problem. We use a dict to get an error |
| 182 | + # if some suspicious happens. |
| 183 | + bitness = {2147483647:"32bit", 9223372036854775807:"64bit"} |
| 184 | + machine += f".{bitness[sys.maxsize]}" |
| 185 | + # fall through to standard osname-release-machine representation |
| 186 | + elif osname[:3] == "aix": |
| 187 | + from _aix_support import aix_platform |
| 188 | + return aix_platform() |
| 189 | + elif osname[:6] == "cygwin": |
| 190 | + osname = "cygwin" |
| 191 | + import re |
| 192 | + rel_re = re.compile(r'[\d.]+') |
| 193 | + m = rel_re.match(release) |
| 194 | + if m: |
| 195 | + release = m.group() |
| 196 | + elif osname[:6] == "darwin": |
| 197 | + if sys.platform == "ios": |
| 198 | + release = get_config_vars().get("IPHONEOS_DEPLOYMENT_TARGET", "13.0") |
| 199 | + osname = sys.platform |
| 200 | + machine = sys.implementation._multiarch |
| 201 | + else: |
| 202 | + import _osx_support |
| 203 | + osname, release, machine = _osx_support.get_platform_osx( |
| 204 | + get_config_vars(), |
| 205 | + osname, release, machine) |
| 206 | + |
| 207 | + return f"{osname}-{release}-{machine}" |
| 208 | + |
112 | 209 | # NOTE: site.py has copy of this function.
|
113 | 210 | # Sync it when modify this function.
|
114 | 211 | def _getuserbase():
|
115 | 212 | env_base = os.environ.get("PYTHONUSERBASE", None)
|
116 | 213 | if env_base:
|
117 | 214 | return env_base
|
118 | 215 |
|
119 |
| - # Emscripten, iOS, tvOS, VxWorks, WASI, and watchOS have no home directories |
120 |
| - if sys.platform in {"emscripten", "ios", "tvos", "vxworks", "wasi", "watchos"}: |
| 216 | + # Emscripten, iOS, tvOS, VxWorks, WASI, and watchOS have no home directories. |
| 217 | + # Use sysconfig.get_platform() to get the correct platform when cross-compiling. |
| 218 | + system_name = get_platform().split('-')[0] |
| 219 | + if system_name in {"emscripten", "ios", "tvos", "vxworks", "wasi", "watchos"}: |
121 | 220 | return None
|
122 | 221 |
|
123 | 222 | def joinuser(*args):
|
@@ -335,34 +434,53 @@ def get_makefile_filename():
|
335 | 434 | return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile')
|
336 | 435 |
|
337 | 436 |
|
| 437 | +def _import_from_directory(path, name): |
| 438 | + if name not in sys.modules: |
| 439 | + import importlib.machinery |
| 440 | + import importlib.util |
| 441 | + |
| 442 | + spec = importlib.machinery.PathFinder.find_spec(name, [path]) |
| 443 | + module = importlib.util.module_from_spec(spec) |
| 444 | + spec.loader.exec_module(module) |
| 445 | + sys.modules[name] = module |
| 446 | + return sys.modules[name] |
| 447 | + |
| 448 | + |
338 | 449 | def _get_sysconfigdata_name():
|
339 | 450 | multiarch = getattr(sys.implementation, '_multiarch', '')
|
340 | 451 | return os.environ.get(
|
341 | 452 | '_PYTHON_SYSCONFIGDATA_NAME',
|
342 | 453 | f'_sysconfigdata_{sys.abiflags}_{sys.platform}_{multiarch}',
|
343 | 454 | )
|
344 | 455 |
|
345 |
| -def _init_posix(vars): |
346 |
| - """Initialize the module as appropriate for POSIX systems.""" |
347 |
| - # _sysconfigdata is generated at build time, see _generate_posix_vars() |
| 456 | + |
| 457 | +def _get_sysconfigdata(): |
| 458 | + import importlib |
| 459 | + |
348 | 460 | name = _get_sysconfigdata_name()
|
| 461 | + path = os.environ.get('_PYTHON_SYSCONFIGDATA_PATH') |
| 462 | + module = _import_from_directory(path, name) if path else importlib.import_module(name) |
349 | 463 |
|
350 |
| - # For cross builds, the path to the target's sysconfigdata must be specified |
351 |
| - # so it can be imported. It cannot be in PYTHONPATH, as foreign modules in |
352 |
| - # sys.path can cause crashes when loaded by the host interpreter. |
353 |
| - # Rely on truthiness as a valueless env variable is still an empty string. |
354 |
| - # See OS X note in _generate_posix_vars re _sysconfigdata. |
355 |
| - if (path := os.environ.get('_PYTHON_SYSCONFIGDATA_PATH')): |
356 |
| - from importlib.machinery import FileFinder, SourceFileLoader, SOURCE_SUFFIXES |
357 |
| - from importlib.util import module_from_spec |
358 |
| - spec = FileFinder(path, (SourceFileLoader, SOURCE_SUFFIXES)).find_spec(name) |
359 |
| - _temp = module_from_spec(spec) |
360 |
| - spec.loader.exec_module(_temp) |
361 |
| - else: |
362 |
| - _temp = __import__(name, globals(), locals(), ['build_time_vars'], 0) |
363 |
| - build_time_vars = _temp.build_time_vars |
| 464 | + return module.build_time_vars |
| 465 | + |
| 466 | + |
| 467 | +def _installation_is_relocated(): |
| 468 | + """Is the Python installation running from a different prefix than what was targetted when building?""" |
| 469 | + if os.name != 'posix': |
| 470 | + raise NotImplementedError('sysconfig._installation_is_relocated() is currently only supported on POSIX') |
| 471 | + |
| 472 | + data = _get_sysconfigdata() |
| 473 | + return ( |
| 474 | + data['prefix'] != getattr(sys, 'base_prefix', '') |
| 475 | + or data['exec_prefix'] != getattr(sys, 'base_exec_prefix', '') |
| 476 | + ) |
| 477 | + |
| 478 | + |
| 479 | +def _init_posix(vars): |
| 480 | + """Initialize the module as appropriate for POSIX systems.""" |
364 | 481 | # GH-126920: Make sure we don't overwrite any of the keys already set
|
365 |
| - vars.update(build_time_vars | vars) |
| 482 | + vars.update(_get_sysconfigdata() | vars) |
| 483 | + |
366 | 484 |
|
367 | 485 | def _init_non_posix(vars):
|
368 | 486 | """Initialize the module as appropriate for NT"""
|
@@ -601,104 +719,6 @@ def get_config_var(name):
|
601 | 719 | return get_config_vars().get(name)
|
602 | 720 |
|
603 | 721 |
|
604 |
| -def get_platform(): |
605 |
| - """Return a string that identifies the current platform. |
606 |
| -
|
607 |
| - This is used mainly to distinguish platform-specific build directories and |
608 |
| - platform-specific built distributions. Typically includes the OS name and |
609 |
| - version and the architecture (as supplied by 'os.uname()'), although the |
610 |
| - exact information included depends on the OS; on Linux, the kernel version |
611 |
| - isn't particularly important. |
612 |
| -
|
613 |
| - Examples of returned values: |
614 |
| - linux-i586 |
615 |
| - linux-alpha (?) |
616 |
| - solaris-2.6-sun4u |
617 |
| -
|
618 |
| - Windows will return one of: |
619 |
| - win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc) |
620 |
| - win32 (all others - specifically, sys.platform is returned) |
621 |
| -
|
622 |
| - For other non-POSIX platforms, currently just returns 'sys.platform'. |
623 |
| -
|
624 |
| - """ |
625 |
| - if os.name == 'nt': |
626 |
| - if 'amd64' in sys.version.lower(): |
627 |
| - return 'win-amd64' |
628 |
| - if '(arm)' in sys.version.lower(): |
629 |
| - return 'win-arm32' |
630 |
| - if '(arm64)' in sys.version.lower(): |
631 |
| - return 'win-arm64' |
632 |
| - return sys.platform |
633 |
| - |
634 |
| - if os.name != "posix" or not hasattr(os, 'uname'): |
635 |
| - # XXX what about the architecture? NT is Intel or Alpha |
636 |
| - return sys.platform |
637 |
| - |
638 |
| - # Set for cross builds explicitly |
639 |
| - if "_PYTHON_HOST_PLATFORM" in os.environ: |
640 |
| - return os.environ["_PYTHON_HOST_PLATFORM"] |
641 |
| - |
642 |
| - # Try to distinguish various flavours of Unix |
643 |
| - osname, host, release, version, machine = os.uname() |
644 |
| - |
645 |
| - # Convert the OS name to lowercase, remove '/' characters, and translate |
646 |
| - # spaces (for "Power Macintosh") |
647 |
| - osname = osname.lower().replace('/', '') |
648 |
| - machine = machine.replace(' ', '_') |
649 |
| - machine = machine.replace('/', '-') |
650 |
| - |
651 |
| - if osname[:5] == "linux": |
652 |
| - if sys.platform == "android": |
653 |
| - osname = "android" |
654 |
| - release = get_config_var("ANDROID_API_LEVEL") |
655 |
| - |
656 |
| - # Wheel tags use the ABI names from Android's own tools. |
657 |
| - machine = { |
658 |
| - "x86_64": "x86_64", |
659 |
| - "i686": "x86", |
660 |
| - "aarch64": "arm64_v8a", |
661 |
| - "armv7l": "armeabi_v7a", |
662 |
| - }[machine] |
663 |
| - else: |
664 |
| - # At least on Linux/Intel, 'machine' is the processor -- |
665 |
| - # i386, etc. |
666 |
| - # XXX what about Alpha, SPARC, etc? |
667 |
| - return f"{osname}-{machine}" |
668 |
| - elif osname[:5] == "sunos": |
669 |
| - if release[0] >= "5": # SunOS 5 == Solaris 2 |
670 |
| - osname = "solaris" |
671 |
| - release = f"{int(release[0]) - 3}.{release[2:]}" |
672 |
| - # We can't use "platform.architecture()[0]" because a |
673 |
| - # bootstrap problem. We use a dict to get an error |
674 |
| - # if some suspicious happens. |
675 |
| - bitness = {2147483647:"32bit", 9223372036854775807:"64bit"} |
676 |
| - machine += f".{bitness[sys.maxsize]}" |
677 |
| - # fall through to standard osname-release-machine representation |
678 |
| - elif osname[:3] == "aix": |
679 |
| - from _aix_support import aix_platform |
680 |
| - return aix_platform() |
681 |
| - elif osname[:6] == "cygwin": |
682 |
| - osname = "cygwin" |
683 |
| - import re |
684 |
| - rel_re = re.compile(r'[\d.]+') |
685 |
| - m = rel_re.match(release) |
686 |
| - if m: |
687 |
| - release = m.group() |
688 |
| - elif osname[:6] == "darwin": |
689 |
| - if sys.platform == "ios": |
690 |
| - release = get_config_vars().get("IPHONEOS_DEPLOYMENT_TARGET", "13.0") |
691 |
| - osname = sys.platform |
692 |
| - machine = sys.implementation._multiarch |
693 |
| - else: |
694 |
| - import _osx_support |
695 |
| - osname, release, machine = _osx_support.get_platform_osx( |
696 |
| - get_config_vars(), |
697 |
| - osname, release, machine) |
698 |
| - |
699 |
| - return f"{osname}-{release}-{machine}" |
700 |
| - |
701 |
| - |
702 | 722 | def get_python_version():
|
703 | 723 | return _PY_VERSION_SHORT
|
704 | 724 |
|
|
0 commit comments