8000 bpo-35920: Windows 10 ARM32 platform support (GH-11774) · python/cpython@62dfd7d · GitHub
[go: up one dir, main page]

Skip to content

Commit 62dfd7d

Browse files
paulmonzooba
authored andcommitted
bpo-35920: Windows 10 ARM32 platform support (GH-11774)
1 parent 8c3ecc6 commit 62dfd7d

File tree

17 files changed

+134
-15
lines changed

17 files changed

+134
-15
lines changed

Doc/library/platform.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,21 @@ Windows Platform
216216
later (support for this was added in Python 2.6). It obviously
217217
only runs on Win32 compatible platforms.
218218

219+
.. function:: win32_edition()
220+
221+
Returns a string representing the current Windows edition. Possible
222+
values include but are not limited to ``'Enterprise'``, ``'IoTUAP'``,
223+
``'ServerStandard'``, and ``'nanoserver'``.
224+
225+
.. versionadded:: 3.8
226+
227+
.. function:: win32_is_iot()
228+
229+
Returns True if the windows edition returned by win32_edition is recognized
230+
as an IoT edition.
231+
232+
.. versionadded:: 3.8
233+
219234

220235
Mac OS Platform
221236
---------------

Lib/distutils/_msvccompiler.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line c 9E88 hange
@@ -89,13 +89,24 @@ def _find_vc2017():
8989

9090
return None, None
9191

92+
PLAT_SPEC_TO_RUNTIME = {
93+
'x86' : 'x86',
94+
'x86_amd64' : 'x64',
95+
'x86_arm' : 'arm',
96+
}
97+
9298
def _find_vcvarsall(plat_spec):
9399
_, best_dir = _find_vc2017()
94100
vcruntime = None
95-
vcruntime_plat = 'x64' if 'amd64' in plat_spec else 'x86'
101+
102+
if plat_spec in PLAT_SPEC_TO_RUNTIME:
103+
vcruntime_plat = PLAT_SPEC_TO_RUNTIME[plat_spec]
104+
else:
105+
vcruntime_plat = 'x64' if 'amd64' in plat_spec else 'x86'
106+
96107
if best_dir:
97108
vcredist = os.path.join(best_dir, "..", "..", "redist", "MSVC", "**",
98-
"Microsoft.VC141.CRT", "vcruntime140.dll")
109+
vcruntime_plat, "Microsoft.VC141.CRT", "vcruntime140.dll")
99110
try:
100111
import glob
101112
vcruntime = glob.glob(vcredist, recursive=True)[-1]
@@ -178,6 +189,7 @@ def _find_exe(exe, paths=None):
178189
PLAT_TO_VCVARS = {
179190
'win32' : 'x86',
180191
'win-amd64' : 'x86_amd64',
192+
'win-arm32' : 'x86_arm',
181193
}
182194

183195
# A set containing the DLLs that are guaranteed to be available for

Lib/distutils/spawn.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ def _spawn_nt(cmd, search_path=1, verbose=0, dry_run=0):
8181
"command %r failed with exit status %d" % (cmd, rc))
8282

8383
if sys.platform == 'darwin':
84-
from distutils import sysconfig
8584
_cfg_target = None
8685
_cfg_target_split = None
8786

@@ -95,6 +94,7 @@ def _spawn_posix(cmd, search_path=1, verbose=0, dry_run=0):
9594
if sys.platform == 'darwin':
9695
global _cfg_target, _cfg_target_split
9796
if _cfg_target is None:
97+
from distutils import sysconfig
9898
_cfg_target = sysconfig.get_config_var(
9999
'MACOSX_DEPLOYMENT_TARGET') or ''
100100
if _cfg_target:

Lib/distutils/sysconfig.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import sys
1616

1717
from .errors import DistutilsPlatformError
18+
from .util import get_platform, get_host_platform
1819

1920
# These are needed in a couple of spots, so just compute them once.
2021
PREFIX = os.path.normpath(sys.prefix)

Lib/distutils/util.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from distutils import log
1616
from distutils.errors import DistutilsByteCompileError
1717

18-
def get_platform ():
18+
def get_host_platform():
1919
"""Return a string that identifies the current platform. This is used mainly to
2020
distinguish platform-specific build directories and platform-specific built
2121
distributions. Typically includes the OS name and version and the
@@ -38,6 +38,8 @@ def get_platform ():
3838
if os.name == 'nt':
3939
if 'amd64' in sys.version.lower():
4040
return 'win-amd64'
41+
if '(arm)' in sys.version.lower():
42+
return 'win-arm32'
4143
return sys.platform
4244

4345
# Set for cross builds explicitly
@@ -90,8 +92,16 @@ def get_platform ():
9092

9193
return "%s-%s-%s" % (osname, release, machine)
9294

93-
# get_platform ()
94-
95+
def get_platform():
96+
if os.name == 'nt':
97+
TARGET_TO_PLAT = {
98+
'x86' : 'win32',
99+
'x64' : 'win-amd64',
100+
'arm' : 'win-arm32',
101+
}
102+
return TARGET_TO_PLAT.get(os.environ.get('VSCMD_ARG_TGT_ARCH')) or get_host_platform()
103+
else:
104+
return get_host_platform()
95105

96106
def convert_path (pathname):
97107
"""Return 'pathname' as a name that will work on the native filesystem,

Lib/platform.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,27 @@ def _syscmd_ver(system='', release='', version='',
334334
(6, None): "post2012ServerR2",
335335
}
336336

337+
def win32_is_iot():
338+
return win32_edition() in ('IoTUAP', 'NanoServer', 'WindowsCoreHeadless', 'IoTEdgeOS')
339+
340+
def win32_edition():
341+
try:
342+
try:
343+
import winreg
344+
except ImportError:
345+
import _winreg as winreg
346+
except ImportError:
347+
pass
348+
else:
349+
try:
350+
cvkey = r'SOFTWARE\Microsoft\Windows NT\CurrentVersion'
351+
with winreg.OpenKeyEx(winreg.HKEY_LOCAL_MACHINE, cvkey) as key:
352+
return winreg.QueryValueEx(key, 'EditionId')[0]
353+
except OSError:
354+
pass
355+
356+
return None
357+
337358
def win32_ver(release='', version='', csd='', ptype=''):
338359
try:
339360
from sys import getwindowsversion

Lib/sysconfig.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,8 @@ def get_platform():
626626
if os.name == 'nt':
627627
if 'amd64' in sys.version.lower():
628628
return 'win-amd64'
629+
if '(arm)' in sys.version.lower():
630+
return 'win-arm32'
629631
return sys.platform
630632

631633
if os.name != "posix" or not hasattr(os, 'uname'):

Lib/test/test_codecs.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,26 @@ def check(input, expect):
2727
self.assertEqual(coder(input), (expect, len(input)))
2828
return check
2929

30+
# On small versions of Windows like Windows IoT or Windows Nano Server not all codepages are present
31+
def is_code_page_present(cp):
32+
from ctypes import POINTER, WINFUNCTYPE, windll, WinError, Structure, WinDLL
33+
from ctypes.wintypes import BOOL, UINT, BYTE, WCHAR, UINT, DWORD
34+
35+
MAX_LEADBYTES = 12 # 5 ranges, 2 bytes ea., 0 term.
36+
MAX_DEFAULTCHAR = 2 # single or double byte
37+
MAX_PATH = 260
38+
class CPINFOEXW(ctypes.Structure):
39+
_fields_ = [("MaxCharSize", UINT),
40+
("DefaultChar", BYTE*MAX_DEFAULTCHAR),
41+
("LeadByte", BYTE*MAX_LEADBYTES),
42+
("UnicodeDefaultChar", WCHAR),
43+
("CodePage", UINT),
44+
("CodePageName", WCHAR*MAX_PATH)]
45+
46+
prototype = WINFUNCTYPE(BOOL, UINT, DWORD, POINTER(CPINFOEXW))
47+
GetCPInfoEx = prototype(("GetCPInfoExW", WinDLL("kernel32")))
48+
info = CPINFOEXW()
49+
return GetCPInfoEx(cp, 0, info)
3050

3151
class Queue(object):
3252
"""
@@ -3078,9 +3098,19 @@ def test_multibyte_encoding(self):
30783098
def test_code_page_decode_flags(self):
30793099
# Issue #36312: For some code pages (e.g. UTF-7) flags for
30803100
# MultiByteToWideChar() must be set to 0.
3101+
if support.verbose:
3102+
sys.stdout.write('\n')
30813103
for cp in (50220, 50221, 50222, 50225, 50227, 50229,
30823104
*range(57002, 57011+1), 65000):
3083-
self.assertEqual(codecs.code_page_decode(cp, b'abc'), ('abc', 3))
3105+
# On small versions of Windows like Windows IoT
3106+
# not all codepages are present.
3107+
# A missing codepage causes an OSError exception
3108+
# so check for the codepage before decoding
3109+
if is_code_page_present(cp):
3110+
self.assertEqual(codecs.code_page_decode(cp, b'abc'), ('abc', 3), f'cp{cp}')
3111+
else:
3112+
if support.verbose:
3113+
print(f" skipping cp={cp}")
30843114
self.assertEqual(codecs.code_page_decode(42, b'abc'),
30853115
('\uf061\uf062\uf063', 3))
30863116

Lib/test/test_mimetypes.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import unittest
77

88
from test import support
9+
from platform import win32_edition
910

1011
# Tell it we don't know about external files:
1112
mimetypes.knownfiles = []
@@ -116,6 +117,8 @@ def tearDown(self):
116117
mimetypes.types_map.clear()
117118
mimetypes.types_map.update(self.original_types_map)
118119

120+
@unittest.skipIf(win32_edition() in ('NanoServer', 'WindowsCoreHeadless', 'IoTEdgeOS'),
121+
"MIME types registry keys unavailable")
119122
def test_registry_parsing(self):
120123
# the original, minimum contents of the MIME database in the
121124
# Windows registry is undocumented AFAIK.

Lib/test/test_os.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import uuid
2929
import warnings
3030
from test import support
31+
from platform import win32_is_iot
3132

3233
try:
3334
import resource
@@ -2439,7 +2440,7 @@ def test_bad_fd(self):
24392440
# Return None when an fd doesn't actually exist.
24402441
self.assertIsNone(os.device_encoding(123456))
24412442

2442-
@unittest.skipUnless(os.isatty(0) and (sys.platform.startswith('win') or
2443+
@unittest.skipUnless(os.isatty(0) and not win32_is_iot() and (sys.platform.startswith('win') or
24432444
(hasattr(locale, 'nl_langinfo') and hasattr(locale, 'CODESET'))),
24442445
'test requires a tty and either Windows or nl_langinfo(CODESET)')
24452446
def test_device_encoding(self):

Lib/test/test_startfile.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import unittest
1111
from test import support
1212
import os
13+
import platform
1314
import sys
1415
from os import path
1516

@@ -20,6 +21,7 @@ class TestCase(unittest.TestCase):
2021
def test_nonexisting(self):
2122
self.assertRaises(OSError, startfile, "nonexisting.vbs")
2223

24+
@unittest.skipIf(platform.win32_is_iot(), "starting files is not supported on Windows IoT Core or nanoserver")
2325
def test_empty(self):
2426
# We need to make sure the child process starts in a directory
2527
# we're not about to delete. If we're running under -j, that

Lib/test/test_sundry.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Do a minimal test of all the modules that aren't otherwise tested."""
22
import importlib
3+
import platform
34
import sys
45
from test import support
56
import unittest
@@ -25,7 +26,7 @@ def test_untested_modules_can_be_imported(self):
2526
import distutils.unixccompiler
2627

2728
import distutils.command.bdist_dumb
28-
if sys.platform.startswith('win'):
29+
if sys.platform.startswith('win') and not platform.win32_is_iot():
2930
import distutils.command.bdist_msi
3031
import distutils.command.bdist
3132
10000 import distutils.command.bdist_rpm

Lib/test/test_winreg.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import unittest
66
from test import support
77
import threading
8-
from platform import machine
8+
from platform import machine, win32_edition
99

1010
# Do this first so test will be skipped if module doesn't exist
1111
support.import_module('winreg', required_on=['win'])
@@ -399,6 +399,7 @@ def test_named_arguments(self):
399399
DeleteKeyEx(key=HKEY_CURRENT_USER, sub_key=test_key_name,
400400
access=KEY_ALL_ACCESS, reserved=0)
401401

402+
@unittest.skipIf(win32_edition() in ('WindowsCoreHeadless', 'IoTEdgeOS'), "APIs not available on WindowsCoreHeadless")
402403
def test_reflection_functions(self):
403404
# Test that we can call the query, enable, and disable functions
404405
# on a key which isn't on the reflection list with no consequences.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Added platform.win32_edition() and platform.win32_is_iot(). Added support
2+
for cross-compiling packages for Windows ARM32. Skip tests that are not
3+
expected to work on Windows IoT Core ARM32.

PC/bdist_wininst/bdist_wininst.vcxproj

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
33
<ItemGroup Label="ProjectConfigurations">
4+
<ProjectConfiguration Include="Debug|ARM">
5+
<Configuration>Debug</Configuration>
6+
<Platform>ARM</Platform>
7+
</ProjectConfiguration>
48
<ProjectConfiguration Include="Debug|Win32">
59
<Configuration>Debug</Configuration>
610
<Platform>Win32</Platform>
@@ -9,6 +13,10 @@
913
<Configuration>Debug</Configuration>
1014
<Platform>x64</Platform>
1115
</ProjectConfiguration>
16+
<ProjectConfiguration Include="PGInstrument|ARM">
17+
<Configuration>PGInstrument</Configuration>
18+
<Platform>ARM</Platform>
19+
</ProjectConfiguration>
1220
<ProjectConfiguration Include="PGInstrument|Win32">
1321
<Configuration>PGInstrument</Configuration>
1422
<Platform>Win32</Platform>
@@ -17,6 +25,10 @@
1725
<Configuration>PGInstrument</Configuration>
1826
<Platform>x64</Platform>
1927
</ProjectConfiguration>
28+
<ProjectConfiguration Include="PGUpdate|ARM">
29+
<Configuration>PGUpdate</Configuration>
30+
<Platform>ARM</Platform>
31+
</ProjectConfiguration>
2032
<ProjectConfiguration Include="PGUpdate|Win32">
2133
<Configuration>PGUpdate</Configuration>
2234
<Platform>Win32</Platform>
@@ -25,6 +37,10 @@
2537
<Configuration>PGUpdate</Configuration>
2638
<Platform>x64</Platform>
2739
</ProjectConfiguration>
40+
<ProjectConfiguration Include="Release|ARM">
41+
<Configuration>Release</Configuration>
42+
<Platform>ARM</Platform>
43+
</ProjectConfiguration>
2844
<ProjectConfiguration Include="Release|Win32">
2945
<Configuration>Release</Configuration>
3046
<Platform>Win32</Platform>

PCbuild/build.bat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ echo.
4141
echo.Available arguments:
4242
echo. -c Release ^| Debug ^| PGInstrument ^| PGUpdate
4343
echo. Set the configuration (default: Release)
44-
echo. -p x64 ^| Win32
44+
echo. -p x64 ^| Win32 ^| ARM
4545
echo. Set the platform (default: Win32)
4646
echo. -t Build ^| Rebuild ^| Clean ^| CleanAll
4747
echo. Set the target manually

PCbuild/pcbuild.sln

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -597,16 +597,16 @@ Global
597597
{D06B6426-4762-44CC-8BAD-D79052507F2F}.Release|Win32.Build.0 = Release|Win32
598598
{D06B6426-4762-44CC-8BAD-D79052507F2F}.Release|x64.ActiveCfg = Release|x64
599599
{D06B6426-4762-44CC-8BAD-D79052507F2F}.Release|x64.Build.0 = Release|x64
600-
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Debug|ARM.ActiveCfg = Debug|Win32
600+
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Debug|ARM.ActiveCfg = Debug|ARM
601601
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Debug|Win32.ActiveCfg = Debug|Win32
602602
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Debug|x64.ActiveCfg = Release|x64
603-
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGInstrument|ARM.ActiveCfg = PGInstrument|Win32
603+
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGInstrument|ARM.ActiveCfg = PGInstrument|ARM
604604
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGInstrument|Win32.ActiveCfg = Release|Win32
605605
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGInstrument|x64.ActiveCfg = Release|x64
606-
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGUpdate|ARM.ActiveCfg = PGUpdate|Win32
606+
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGUpdate|ARM.ActiveCfg = PGUpdate|ARM
607607
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGUpdate|Win32.ActiveCfg = Release|Win32
608608
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGUpdate|x64.ActiveCfg = Release|x64
609-
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Release|ARM.ActiveCfg = Release|Win32
609+
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Release|ARM.ActiveCfg = Release|ARM
610610
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Release|Win32.ActiveCfg = Release|Win32
611611
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Release|x64.ActiveCfg = Release|x64
612612
{447F05A8-F581-4CAC-A466-5AC7936E207E}.Debug|ARM.ActiveCfg = Debug|ARM
@@ -896,6 +896,7 @@ Global
896896
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.PGUpdate|x64.ActiveCfg = PGUpdate|x64
897897
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.PGUpdate|x64.Build.0 = PGUpdate|x64
898898
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Release|ARM.ActiveCfg = Release|ARM
899+
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Release|ARM.Build.0 = Release|ARM
899900
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Release|Win32.ActiveCfg = Release|Win32
900901
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Release|Win32.Build.0 = Release|Win32
901902
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Release|x64.ActiveCfg = Release|x64

0 commit comments

Comments
 (0)
0