summaryrefslogtreecommitdiff
path: root/PC/layout/support
diff options
context:
space:
mode:
authorSteve Dower <steve.dower@python.org>2019-11-20 09:30:47 -0800
committerGitHub <noreply@github.com>2019-11-20 09:30:47 -0800
commitde148f263fba75cd10d2cb010fe9c495cee4ec83 (patch)
tree7559853c00252bb9e300e6815ee3615a90e3973b /PC/layout/support
parentabce2d9bc6b990831d303f4cf9f2de8a6712a1fc (diff)
downloadcpython-git-de148f263fba75cd10d2cb010fe9c495cee4ec83.tar.gz
bpo-33125: Add support for building and releasing Windows ARM64 packages (GH-16828)
Note that the support is not actually enabled yet, and so we won't be publishing these packages. However, for those who want to build it themselves (even by reusing the Azure Pipelines definition), it's now relatively easy to enable.
Diffstat (limited to 'PC/layout/support')
-rw-r--r--PC/layout/support/appxmanifest.py43
-rw-r--r--PC/layout/support/constants.py32
-rw-r--r--PC/layout/support/nuspec.py40
-rw-r--r--PC/layout/support/props.py22
4 files changed, 92 insertions, 45 deletions
diff --git a/PC/layout/support/appxmanifest.py b/PC/layout/support/appxmanifest.py
index de5813a253..9e008f793c 100644
--- a/PC/layout/support/appxmanifest.py
+++ b/PC/layout/support/appxmanifest.py
@@ -28,7 +28,14 @@ APPX_DATA = dict(
),
DisplayName="Python {}".format(VER_DOT),
Description="The Python {} runtime and console.".format(VER_DOT),
- ProcessorArchitecture="x64" if IS_X64 else "x86",
+)
+
+APPX_PLATFORM_DATA = dict(
+ _keys=("ProcessorArchitecture",),
+ win32=("x86",),
+ amd64=("x64",),
+ arm32=("arm",),
+ arm64=("arm64",),
)
PYTHON_VE_DATA = dict(
@@ -65,7 +72,7 @@ IDLE_VE_DATA = dict(
BackgroundColor="transparent",
)
-PY_PNG = '_resources/py.png'
+PY_PNG = "_resources/py.png"
APPXMANIFEST_NS = {
"": "http://schemas.microsoft.com/appx/manifest/foundation/windows10",
@@ -147,18 +154,22 @@ RESOURCES_XML_TEMPLATE = r"""<?xml version="1.0" encoding="UTF-8" standalone="ye
SCCD_FILENAME = "PC/classicAppCompat.sccd"
+SPECIAL_LOOKUP = object()
+
REGISTRY = {
"HKCU\\Software\\Python\\PythonCore": {
VER_DOT: {
"DisplayName": APPX_DATA["DisplayName"],
"SupportUrl": "https://www.python.org/",
- "SysArchitecture": "64bit" if IS_X64 else "32bit",
+ "SysArchitecture": SPECIAL_LOOKUP,
"SysVersion": VER_DOT,
"Version": "{}.{}.{}".format(VER_MAJOR, VER_MINOR, VER_MICRO),
"InstallPath": {
"": "[{AppVPackageRoot}]",
"ExecutablePath": "[{{AppVPackageRoot}}]\\python{}.exe".format(VER_DOT),
- "WindowedExecutablePath": "[{{AppVPackageRoot}}]\\pythonw{}.exe".format(VER_DOT),
+ "WindowedExecutablePath": "[{{AppVPackageRoot}}]\\pythonw{}.exe".format(
+ VER_DOT
+ ),
},
"Help": {
"Main Python Documentation": {
@@ -338,6 +349,16 @@ def _get_registry_entries(ns, root="", d=None):
if len(fullkey.parts) > 1:
yield str(fullkey), None, None
yield from _get_registry_entries(ns, fullkey, value)
+ elif value is SPECIAL_LOOKUP:
+ if key == "SysArchitecture":
+ return {
+ "win32": "32bit",
+ "amd64": "64bit",
+ "arm32": "32bit",
+ "arm64": "64bit",
+ }[ns.arch]
+ else:
+ raise ValueError(f"Key '{key}' unhandled for special lookup")
elif len(r.parts) > 1:
yield str(r), key, value
@@ -376,14 +397,18 @@ def get_appxmanifest(ns):
NS = APPXMANIFEST_NS
QN = ET.QName
+ data = dict(APPX_DATA)
+ for k, v in zip(APPX_PLATFORM_DATA["_keys"], APPX_PLATFORM_DATA[ns.arch]):
+ data[k] = v
+
node = xml.find("m:Identity", NS)
for k in node.keys():
- value = APPX_DATA.get(k)
+ value = data.get(k)
if value:
node.set(k, value)
for node in xml.find("m:Properties", NS):
- value = APPX_DATA.get(node.tag.rpartition("}")[2])
+ value = data.get(node.tag.rpartition("}")[2])
if value:
node.text = value
@@ -405,7 +430,7 @@ def get_appxmanifest(ns):
["python", "python{}".format(VER_MAJOR), "python{}".format(VER_DOT)],
PYTHON_VE_DATA,
"console",
- ("python.file", [".py"], '"%1"', 'Python File', PY_PNG),
+ ("python.file", [".py"], '"%1"', "Python File", PY_PNG),
)
add_application(
@@ -416,7 +441,7 @@ def get_appxmanifest(ns):
["pythonw", "pythonw{}".format(VER_MAJOR), "pythonw{}".format(VER_DOT)],
PYTHONW_VE_DATA,
"windows",
- ("python.windowedfile", [".pyw"], '"%1"', 'Python File (no console)', PY_PNG),
+ ("python.windowedfile", [".pyw"], '"%1"', "Python File (no console)", PY_PNG),
)
if ns.include_pip and ns.include_launchers:
@@ -428,7 +453,7 @@ def get_appxmanifest(ns):
["pip", "pip{}".format(VER_MAJOR), "pip{}".format(VER_DOT)],
PIP_VE_DATA,
"console",
- ("python.wheel", [".whl"], 'install "%1"', 'Python Wheel'),
+ ("python.wheel", [".whl"], 'install "%1"', "Python Wheel"),
)
if ns.include_idle and ns.include_launchers:
diff --git a/PC/layout/support/constants.py b/PC/layout/support/constants.py
index d76fa3bbf3..a8647631e9 100644
--- a/PC/layout/support/constants.py
+++ b/PC/layout/support/constants.py
@@ -5,15 +5,31 @@ Constants for generating the layout.
__author__ = "Steve Dower <steve.dower@python.org>"
__version__ = "3.8"
+import os
+import re
import struct
import sys
-VER_MAJOR, VER_MINOR, VER_MICRO, VER_FIELD4 = struct.pack(">i", sys.hexversion)
+
+def _unpack_hexversion():
+ try:
+ hexversion = int(os.getenv("PYTHON_HEXVERSION"), 16)
+ except (TypeError, ValueError):
+ hexversion = sys.hexversion
+ return struct.pack(">i", sys.hexversion)
+
+
+def _get_suffix(field4):
+ name = {0xA0: "a", 0xB0: "b", 0xC0: "c"}.get(field4 & 0xF0, "")
+ if name:
+ serial = field4 & 0x0F
+ return f"{name}{serial}"
+ return ""
+
+
+VER_MAJOR, VER_MINOR, VER_MICRO, VER_FIELD4 = _unpack_hexversion()
+VER_SUFFIX = _get_suffix(VER_FIELD4)
VER_FIELD3 = VER_MICRO << 8 | VER_FIELD4
-VER_NAME = {"alpha": "a", "beta": "b", "candidate": "rc"}.get(
- sys.version_info.releaselevel, ""
-)
-VER_SERIAL = sys.version_info.serial if VER_NAME else ""
VER_DOT = "{}.{}".format(VER_MAJOR, VER_MINOR)
PYTHON_DLL_NAME = "python{}{}.dll".format(VER_MAJOR, VER_MINOR)
@@ -21,8 +37,6 @@ PYTHON_STABLE_DLL_NAME = "python{}.dll".format(VER_MAJOR)
PYTHON_ZIP_NAME = "python{}{}.zip".format(VER_MAJOR, VER_MINOR)
PYTHON_PTH_NAME = "python{}{}._pth".format(VER_MAJOR, VER_MINOR)
-PYTHON_CHM_NAME = "python{}{}{}{}{}.chm".format(
- VER_MAJOR, VER_MINOR, VER_MICRO, VER_NAME, VER_SERIAL
+PYTHON_CHM_NAME = "python{}{}{}{}.chm".format(
+ VER_MAJOR, VER_MINOR, VER_MICRO, VER_SUFFIX
)
-
-IS_X64 = sys.maxsize > 2 ** 32
diff --git a/PC/layout/support/nuspec.py b/PC/layout/support/nuspec.py
index ba26ff337e..b85095c555 100644
--- a/PC/layout/support/nuspec.py
+++ b/PC/layout/support/nuspec.py
@@ -13,25 +13,21 @@ PYTHON_NUSPEC_NAME = "python.nuspec"
NUSPEC_DATA = {
"PYTHON_TAG": VER_DOT,
"PYTHON_VERSION": os.getenv("PYTHON_NUSPEC_VERSION"),
- "PYTHON_BITNESS": "64-bit" if IS_X64 else "32-bit",
- "PACKAGENAME": os.getenv("PYTHON_NUSPEC_PACKAGENAME"),
- "PACKAGETITLE": os.getenv("PYTHON_NUSPEC_PACKAGETITLE"),
"FILELIST": r' <file src="**\*" target="tools" />',
}
-if not NUSPEC_DATA["PYTHON_VERSION"]:
- if VER_NAME:
- NUSPEC_DATA["PYTHON_VERSION"] = "{}.{}-{}{}".format(
- VER_DOT, VER_MICRO, VER_NAME, VER_SERIAL
- )
- else:
- NUSPEC_DATA["PYTHON_VERSION"] = "{}.{}".format(VER_DOT, VER_MICRO)
-
-if not NUSPEC_DATA["PACKAGETITLE"]:
- NUSPEC_DATA["PACKAGETITLE"] = "Python" if IS_X64 else "Python (32-bit)"
+NUSPEC_PLATFORM_DATA = dict(
+ _keys=("PYTHON_BITNESS", "PACKAGENAME", "PACKAGETITLE"),
+ win32=("32-bit", "pythonx86", "Python (32-bit)"),
+ amd64=("64-bit", "python", "Python"),
+ arm32=("ARM", "pythonarm", "Python (ARM)"),
+ arm64=("ARM64", "pythonarm64", "Python (ARM64)"),
+)
-if not NUSPEC_DATA["PACKAGENAME"]:
- NUSPEC_DATA["PACKAGENAME"] = "python" if IS_X64 else "pythonx86"
+if not NUSPEC_DATA["PYTHON_VERSION"]:
+ NUSPEC_DATA["PYTHON_VERSION"] = "{}.{}{}{}".format(
+ VER_DOT, VER_MICRO, "-" if VER_SUFFIX else "", VER_SUFFIX
+ )
FILELIST_WITH_PROPS = r""" <file src="**\*" exclude="python.props" target="tools" />
<file src="python.props" target="build\native" />"""
@@ -56,11 +52,21 @@ NUSPEC_TEMPLATE = r"""<?xml version="1.0"?>
"""
+def _get_nuspec_data_overrides(ns):
+ for k, v in zip(NUSPEC_PLATFORM_DATA["_keys"], NUSPEC_PLATFORM_DATA[ns.arch]):
+ ev = os.getenv("PYTHON_NUSPEC_" + k)
+ if ev:
+ yield k, ev
+ yield k, v
+
+
def get_nuspec_layout(ns):
if ns.include_all or ns.include_nuspec:
- data = NUSPEC_DATA
+ data = dict(NUSPEC_DATA)
+ for k, v in _get_nuspec_data_overrides(ns):
+ if not data.get(k):
+ data[k] = v
if ns.include_all or ns.include_props:
- data = dict(data)
data["FILELIST"] = FILELIST_WITH_PROPS
nuspec = NUSPEC_TEMPLATE.format_map(data)
yield "python.nuspec", ("python.nuspec", nuspec.encode("utf-8"))
diff --git a/PC/layout/support/props.py b/PC/layout/support/props.py
index 4d3b06195f..b1560b5244 100644
--- a/PC/layout/support/props.py
+++ b/PC/layout/support/props.py
@@ -18,15 +18,9 @@ PROPS_DATA = {
}
if not PROPS_DATA["PYTHON_VERSION"]:
- if VER_NAME:
- PROPS_DATA["PYTHON_VERSION"] = "{}.{}-{}{}".format(
- VER_DOT, VER_MICRO, VER_NAME, VER_SERIAL
- )
- else:
- PROPS_DATA["PYTHON_VERSION"] = "{}.{}".format(VER_DOT, VER_MICRO)
-
-if not PROPS_DATA["PYTHON_PLATFORM"]:
- PROPS_DATA["PYTHON_PLATFORM"] = "x64" if IS_X64 else "Win32"
+ PROPS_DATA["PYTHON_VERSION"] = "{}.{}{}{}".format(
+ VER_DOT, VER_MICRO, "-" if VER_SUFFIX else "", VER_SUFFIX
+ )
PROPS_DATA["PYTHON_TARGET"] = "_GetPythonRuntimeFilesDependsOn{}{}_{}".format(
VER_MAJOR, VER_MINOR, PROPS_DATA["PYTHON_PLATFORM"]
@@ -94,5 +88,13 @@ PROPS_TEMPLATE = r"""<?xml version="1.0" encoding="utf-8"?>
def get_props_layout(ns):
if ns.include_all or ns.include_props:
# TODO: Filter contents of props file according to included/excluded items
- props = PROPS_TEMPLATE.format_map(PROPS_DATA)
+ d = dict(PROPS_DATA)
+ if not d.get("PYTHON_PLATFORM"):
+ d["PYTHON_PLATFORM"] = {
+ "win32": "Win32",
+ "amd64": "X64",
+ "arm32": "ARM",
+ "arm64": "ARM64",
+ }[ns.arch]
+ props = PROPS_TEMPLATE.format_map(d)
yield "python.props", ("python.props", props.encode("utf-8"))