From 152457a42890dcde043831004933d860f0c0461a Mon Sep 17 00:00:00 2001 From: Christian Hammond Date: Sun, 19 Dec 2021 20:09:38 -0800 Subject: [PATCH] Fix Python 3.6.15 compilation on macOS arm64/M1. (#2189) This change ports several established patches to the Python 3.6.15 build, enabling compilation on arm64/Apple M1 architectures: 1. `0001-Detect-arm64-in-configure.patch` - Updates configure to detect arm64 architectures (port of an existing pyenv patch for 2.7.18). 2. `0002-bpo-36231-Support-building-on-macOS-without-usr-incl.patch` - Adds macOS SDK root computation logic for determining include paths (port of existing Python patches introduced in 2.7.17 and 3.7.4). 3. `0003-Fix-macOS-_tkinter-use-of-Tck-Tk-in-Library-Framewor.patch` - Fixes Tcl/Tk support on macOS (port of an existing pyenv patch for 2.7.18). 4. `0004-Port-ctypes-and-system-libffi-patches-for-arm64-macO.patch` - Fixes system `ffi.h`/`libffi` path determination and usage and enables calling of variadic functions, fixing ctypes support (consolidated port of existing pyenv patches for 2.7.18 that iterate on this logic). 5. `0005-BPO-41100-Support-macOS-11-when-building-GH-21113.patch` - Updates Darwin version checks to handle macOS 11's major version bump (port of Python patches introduced in 3.7.0 and 3.9.0). 6. `0006-bpo-41100-fix-_decimal-for-arm64-Mac-OS-GH-21228.patch` - Adds arm64 to the list of allowable architectures for the `decimal` module (port of Python patch introduced in 3.8.10). --- .../0001-Detect-arm64-in-configure.patch | 41 +++ ...t-building-on-macOS-without-usr-incl.patch | 93 ++++++ ...er-use-of-Tck-Tk-in-Library-Framewor.patch | 240 +++++++++++++ ...system-libffi-patches-for-arm64-macO.patch | 315 ++++++++++++++++++ ...port-macOS-11-when-building-GH-21113.patch | 48 +++ ...x-_decimal-for-arm64-Mac-OS-GH-21228.patch | 37 ++ 6 files changed, 774 insertions(+) create mode 100644 plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0001-Detect-arm64-in-configure.patch create mode 100644 plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0002-bpo-36231-Support-building-on-macOS-without-usr-incl.patch create mode 100644 plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0003-Fix-macOS-_tkinter-use-of-Tck-Tk-in-Library-Framewor.patch create mode 100644 plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0004-Port-ctypes-and-system-libffi-patches-for-arm64-macO.patch create mode 100644 plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0005-BPO-41100-Support-macOS-11-when-building-GH-21113.patch create mode 100644 plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0006-bpo-41100-fix-_decimal-for-arm64-Mac-OS-GH-21228.patch diff --git a/plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0001-Detect-arm64-in-configure.patch b/plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0001-Detect-arm64-in-configure.patch new file mode 100644 index 00000000..d87123f7 --- /dev/null +++ b/plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0001-Detect-arm64-in-configure.patch @@ -0,0 +1,41 @@ +From 002501946bad91a308f37a09204393c172f03c3e Mon Sep 17 00:00:00 2001 +From: Takumi Sueda +Date: Sat, 11 Sep 2021 16:50:14 +0900 +Subject: [PATCH 2/6] Detect arm64 in configure + +--- + configure | 3 +++ + configure.ac | 3 +++ + 2 files changed, 6 insertions(+) + +diff --git a/configure b/configure +index e39c16eee2..8dc1fc7595 100755 +--- a/configure ++++ b/configure +@@ -9230,6 +9230,9 @@ fi + ppc) + MACOSX_DEFAULT_ARCH="ppc64" + ;; ++ arm64) ++ MACOSX_DEFAULT_ARCH="arm64" ++ ;; + *) + as_fn_error $? "Unexpected output of 'arch' on OSX" "$LINENO" 5 + ;; +diff --git a/configure.ac b/configure.ac +index cf280506bd..34846a7df3 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -2435,6 +2435,9 @@ case $ac_sys_system/$ac_sys_release in + ppc) + MACOSX_DEFAULT_ARCH="ppc64" + ;; ++ arm64) ++ MACOSX_DEFAULT_ARCH="arm64" ++ ;; + *) + AC_MSG_ERROR([Unexpected output of 'arch' on OSX]) + ;; +-- +2.30.1 (Apple Git-130) + diff --git a/plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0002-bpo-36231-Support-building-on-macOS-without-usr-incl.patch b/plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0002-bpo-36231-Support-building-on-macOS-without-usr-incl.patch new file mode 100644 index 00000000..f95099a1 --- /dev/null +++ b/plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0002-bpo-36231-Support-building-on-macOS-without-usr-incl.patch @@ -0,0 +1,93 @@ +From c7302116573d853d3181133477d9d0e4d4d3abfd Mon Sep 17 00:00:00 2001 +From: Ned Deily +Date: Tue, 18 Jun 2019 16:28:13 -0400 +Subject: [PATCH] bpo-36231: Support building on macOS without /usr/include + (GH-13773) (GH-14208) + +--- + .../2019-06-03-05-49-49.bpo-36231.RfmW_p.rst | 3 ++ + setup.py | 53 ++++++++++++++++--- + 2 files changed, 49 insertions(+), 7 deletions(-) + create mode 100644 Misc/NEWS.d/next/macOS/2019-06-03-05-49-49.bpo-36231.RfmW_p.rst + +diff --git a/Misc/NEWS.d/next/macOS/2019-06-03-05-49-49.bpo-36231.RfmW_p.rst b/Misc/NEWS.d/next/macOS/2019-06-03-05-49-49.bpo-36231.RfmW_p.rst +new file mode 100644 +index 0000000000..c82e54c12c +--- /dev/null ++++ b/Misc/NEWS.d/next/macOS/2019-06-03-05-49-49.bpo-36231.RfmW_p.rst +@@ -0,0 +1,3 @@ ++Support building Python on macOS without /usr/include installed. As of macOS ++10.14, system header files are only available within an SDK provided by ++either the Command Line Tools or the Xcode app. +diff --git a/setup.py b/setup.py +index bcc4bfa89d..5e0cd02430 100644 +--- a/setup.py ++++ b/setup.py +@@ -90,18 +90,57 @@ def sysroot_paths(make_vars, subdirs): + break + return dirs + ++MACOS_SDK_ROOT = None ++ + def macosx_sdk_root(): ++ """Return the directory of the current macOS SDK. ++ ++ If no SDK was explicitly configured, call the compiler to find which ++ include files paths are being searched by default. Use '/' if the ++ compiler is searching /usr/include (meaning system header files are ++ installed) or use the root of an SDK if that is being searched. ++ (The SDK may be supplied via Xcode or via the Command Line Tools). ++ The SDK paths used by Apple-supplied tool chains depend on the ++ setting of various variables; see the xcrun man page for more info. + """ +- Return the directory of the current OSX SDK, +- or '/' if no SDK was specified. +- """ ++ global MACOS_SDK_ROOT ++ ++ # If already called, return cached result. ++ if MACOS_SDK_ROOT: ++ return MACOS_SDK_ROOT ++ + cflags = sysconfig.get_config_var('CFLAGS') + m = re.search(r'-isysroot\s+(\S+)', cflags) +- if m is None: +- sysroot = '/' ++ if m is not None: ++ MACOS_SDK_ROOT = m.group(1) + else: +- sysroot = m.group(1) +- return sysroot ++ MACOS_SDK_ROOT = '/' ++ cc = sysconfig.get_config_var('CC') ++ tmpfile = '/tmp/setup_sdk_root.%d' % os.getpid() ++ try: ++ os.unlink(tmpfile) ++ except: ++ pass ++ ret = os.system('%s -E -v - %s 1>/dev/null' % (cc, tmpfile)) ++ in_incdirs = False ++ try: ++ if ret >> 8 == 0: ++ with open(tmpfile) as fp: ++ for line in fp.readlines(): ++ if line.startswith("#include <...>"): ++ in_incdirs = True ++ elif line.startswith("End of search list"): ++ in_incdirs = False ++ elif in_incdirs: ++ line = line.strip() ++ if line == '/usr/include': ++ MACOS_SDK_ROOT = '/' ++ elif line.endswith(".sdk/usr/include"): ++ MACOS_SDK_ROOT = line[:-12] ++ finally: ++ os.unlink(tmpfile) ++ ++ return MACOS_SDK_ROOT + + def is_macosx_sdk_path(path): + """ +-- +2.30.1 (Apple Git-130) + diff --git a/plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0003-Fix-macOS-_tkinter-use-of-Tck-Tk-in-Library-Framewor.patch b/plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0003-Fix-macOS-_tkinter-use-of-Tck-Tk-in-Library-Framewor.patch new file mode 100644 index 00000000..62da083e --- /dev/null +++ b/plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0003-Fix-macOS-_tkinter-use-of-Tck-Tk-in-Library-Framewor.patch @@ -0,0 +1,240 @@ +From 942db3e6b96225ef8330f5329c702d62483c6ef8 Mon Sep 17 00:00:00 2001 +From: Takumi Sueda +Date: Sat, 11 Sep 2021 17:14:34 +0900 +Subject: [PATCH 3/6] Fix macOS _tkinter use of Tck/Tk in /Library/Framework + +Modified and imported from https://github.com/Homebrew/formula-patches/blob/master/python/3.8.7.patch +--- + setup.py | 147 ++++++++++++++++++++++++++++++++++++++++--------------- + 1 file changed, 107 insertions(+), 40 deletions(-) + +diff --git a/setup.py b/setup.py +index e2c1898253..8e03c77997 100644 +--- a/setup.py ++++ b/setup.py +@@ -91,6 +91,7 @@ def sysroot_paths(make_vars, subdirs): + return dirs + + MACOS_SDK_ROOT = None ++MACOS_SDK_SPECIFIED = None + + def macosx_sdk_root(): + """Return the directory of the current macOS SDK. +@@ -102,8 +103,9 @@ def macosx_sdk_root(): + (The SDK may be supplied via Xcode or via the Command Line Tools). + The SDK paths used by Apple-supplied tool chains depend on the + setting of various variables; see the xcrun man page for more info. ++ Also sets MACOS_SDK_SPECIFIED for use by macosx_sdk_specified(). + """ +- global MACOS_SDK_ROOT ++ global MACOS_SDK_ROOT, MACOS_SDK_SPECIFIED + + # If already called, return cached result. + if MACOS_SDK_ROOT: +@@ -113,8 +115,10 @@ def macosx_sdk_root(): + m = re.search(r'-isysroot\s+(\S+)', cflags) + if m is not None: + MACOS_SDK_ROOT = m.group(1) ++ MACOS_SDK_SPECIFIED = MACOS_SDK_ROOT != '/' + else: + MACOS_SDK_ROOT = '/' ++ MACOS_SDK_SPECIFIED = False + cc = sysconfig.get_config_var('CC') + tmpfile = '/tmp/setup_sdk_root.%d' % os.getpid() + try: +@@ -142,6 +146,27 @@ def macosx_sdk_root(): + + return MACOS_SDK_ROOT + ++def macosx_sdk_specified(): ++ """Returns true if an SDK was explicitly configured. ++ ++ True if an SDK was selected at configure time, either by specifying ++ --enable-universalsdk=(something other than no or /) or by adding a ++ -isysroot option to CFLAGS. In some cases, like when making ++ decisions about macOS Tk framework paths, we need to be able to ++ know whether the user explicitly asked to build with an SDK versus ++ the implicit use of an SDK when header files are no longer ++ installed on a running system by the Command Line Tools. ++ """ ++ global MACOS_SDK_SPECIFIED ++ ++ # If already called, return cached result. ++ if MACOS_SDK_SPECIFIED: ++ return MACOS_SDK_SPECIFIED ++ ++ # Find the sdk root and set MACOS_SDK_SPECIFIED ++ macosx_sdk_root() ++ return MACOS_SDK_SPECIFIED ++ + def is_macosx_sdk_path(path): + """ + Returns True if 'path' can be located in an OSX SDK +@@ -1758,31 +1783,72 @@ class PyBuildExt(build_ext): + return 1 + + def detect_tkinter_darwin(self, inc_dirs, lib_dirs): +- # The _tkinter module, using frameworks. Since frameworks are quite +- # different the UNIX search logic is not sharable. +- from os.path import join, exists +- framework_dirs = [ +- '/Library/Frameworks', +- '/System/Library/Frameworks/', +- join(os.getenv('HOME'), '/Library/Frameworks') +- ] ++ # Build default _tkinter on macOS using Tcl and Tk frameworks. ++ # ++ # The macOS native Tk (AKA Aqua Tk) and Tcl are most commonly ++ # built and installed as macOS framework bundles. However, ++ # for several reasons, we cannot take full advantage of the ++ # Apple-supplied compiler chain's -framework options here. ++ # Instead, we need to find and pass to the compiler the ++ # absolute paths of the Tcl and Tk headers files we want to use ++ # and the absolute path to the directory containing the Tcl ++ # and Tk frameworks for linking. ++ # ++ # We want to handle here two common use cases on macOS: ++ # 1. Build and link with system-wide third-party or user-built ++ # Tcl and Tk frameworks installed in /Library/Frameworks. ++ # 2. Build and link using a user-specified macOS SDK so that the ++ # built Python can be exported to other systems. In this case, ++ # search only the SDK's /Library/Frameworks (normally empty) ++ # and /System/Library/Frameworks. ++ # ++ # Any other use case should be able to be handled explicitly by ++ # using the options described above in detect_tkinter_explicitly(). ++ # In particular it would be good to handle here the case where ++ # you want to build and link with a framework build of Tcl and Tk ++ # that is not in /Library/Frameworks, say, in your private ++ # $HOME/Library/Frameworks directory or elsewhere. It turns ++ # out to be difficult to make that work automtically here ++ # without bringing into play more tools and magic. That case ++ # can be hamdled using a recipe with the right arguments ++ # to detect_tkinter_explicitly(). ++ # ++ # Note also that the fallback case here is to try to use the ++ # Apple-supplied Tcl and Tk frameworks in /System/Library but ++ # be forewarned that they are deprecated by Apple and typically ++ # out-of-date and buggy; their use should be avoided if at ++ # all possible by installing a newer version of Tcl and Tk in ++ # /Library/Frameworks before bwfore building Python without ++ # an explicit SDK or by configuring build arguments explicitly. + +- sysroot = macosx_sdk_root() ++ from os.path import join, exists ++ sysroot = macosx_sdk_root() # path to the SDK or '/' ++ ++ if macosx_sdk_specified(): ++ # Use case #2: an SDK other than '/' was specified. ++ # Only search there. ++ framework_dirs = [ ++ join(sysroot, 'Library', 'Frameworks'), ++ join(sysroot, 'System', 'Library', 'Frameworks'), ++ ] ++ else: ++ # Use case #1: no explicit SDK selected. ++ # Search the local system-wide /Library/Frameworks, ++ # not the one in the default SDK, othewise fall back to ++ # /System/Library/Frameworks whose header files may be in ++ # the default SDK or, on older systems, actually installed. ++ framework_dirs = [ ++ join('/', 'Library', 'Frameworks'), ++ join(sysroot, 'System', 'Library', 'Frameworks'), ++ ] + +- # Find the directory that contains the Tcl.framework and Tk.framework +- # bundles. +- # XXX distutils should support -F! ++ # Find the directory that contains the Tcl.framework and ++ # Tk.framework bundles. + for F in framework_dirs: + # both Tcl.framework and Tk.framework should be present +- +- + for fw in 'Tcl', 'Tk': +- if is_macosx_sdk_path(F): +- if not exists(join(sysroot, F[1:], fw + '.framework')): +- break +- else: +- if not exists(join(F, fw + '.framework')): +- break ++ if not exists(join(F, fw + '.framework')): ++ break + else: + # ok, F is now directory with both frameworks. Continure + # building +@@ -1792,24 +1858,16 @@ class PyBuildExt(build_ext): + # will now resume. + return 0 + +- # For 8.4a2, we must add -I options that point inside the Tcl and Tk +- # frameworks. In later release we should hopefully be able to pass +- # the -F option to gcc, which specifies a framework lookup path. +- # + include_dirs = [ + join(F, fw + '.framework', H) + for fw in ('Tcl', 'Tk') +- for H in ('Headers', 'Versions/Current/PrivateHeaders') ++ for H in ('Headers',) + ] + +- # For 8.4a2, the X11 headers are not included. Rather than include a +- # complicated search, this is a hard-coded path. It could bail out +- # if X11 libs are not found... +- include_dirs.append('/usr/X11R6/include') +- frameworks = ['-framework', 'Tcl', '-framework', 'Tk'] ++ # Add the base framework directory as well ++ compile_args = ['-F', F] + +- # All existing framework builds of Tcl/Tk don't support 64-bit +- # architectures. ++ # Do not build tkinter for archs that this Tk was not built with. + cflags = sysconfig.get_config_vars('CFLAGS')[0] + archs = re.findall(r'-arch\s+(\w+)', cflags) + +@@ -1819,10 +1877,7 @@ class PyBuildExt(build_ext): + + # Note: cannot use os.popen or subprocess here, that + # requires extensions that are not available here. +- if is_macosx_sdk_path(F): +- os.system("file %s/Tk.framework/Tk | grep 'for architecture' > %s"%(os.path.join(sysroot, F[1:]), tmpfile)) +- else: +- os.system("file %s/Tk.framework/Tk | grep 'for architecture' > %s"%(F, tmpfile)) ++ os.system("file %s/Tk.framework/Tk | grep 'for architecture' > %s"%(F, tmpfile)) + + with open(tmpfile) as fp: + detected_archs = [] +@@ -1832,16 +1887,26 @@ class PyBuildExt(build_ext): + detected_archs.append(ln.split()[-1]) + os.unlink(tmpfile) + ++ arch_args = [] + for a in detected_archs: +- frameworks.append('-arch') +- frameworks.append(a) ++ arch_args.append('-arch') ++ arch_args.append(a) ++ ++ compile_args += arch_args ++ link_args = [','.join(['-Wl', '-F', F, '-framework', 'Tcl', '-framework', 'Tk'])] + arch_args ++ ++ # The X11/xlib.h file bundled in the Tk sources can cause function ++ # prototype warnings from the compiler. Since we cannot easily fix ++ # that, suppress the warnings here instead. ++ if '-Wstrict-prototypes' in cflags.split(): ++ compile_args.append('-Wno-strict-prototypes') + + ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'], + define_macros=[('WITH_APPINIT', 1)], + include_dirs = include_dirs, + libraries = [], +- extra_compile_args = frameworks[2:], +- extra_link_args = frameworks, ++ extra_compile_args = compile_args, ++ extra_link_args = link_args, + ) + self.extensions.append(ext) + return 1 +-- +2.30.1 (Apple Git-130) + diff --git a/plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0004-Port-ctypes-and-system-libffi-patches-for-arm64-macO.patch b/plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0004-Port-ctypes-and-system-libffi-patches-for-arm64-macO.patch new file mode 100644 index 00000000..ae8a90cb --- /dev/null +++ b/plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0004-Port-ctypes-and-system-libffi-patches-for-arm64-macO.patch @@ -0,0 +1,315 @@ +From: Christian Hammond +Date: Wed, 15 Dec 2021 23:12:36 -0800 +Subject: Port ctypes and system libffi patches for arm64/macOS 10.15+ to Python 3.6.15 + +This ports the following ctypes and libffi pyenv patches for Python +2.7.18 to Python 3.6.15: + +* `0004-Use-system-libffi-for-Mac-OS-10.15-and-up.patch` +* `0005-ctypes-use-the-correct-ABI-for-variadic-functions.patch` +* `0006-ctypes-probe-libffi-for-ffi_closure_alloc-and-ffi_pr.patch` + +These patches enable use of system libffi (fixing a broken `ctypes` +module on arm64 targets) and enable calling variadic functions on arm64. +They've been combined from patches port from Homebrew to pyenv by Takumi +Sueda, updated to work on the Python 3.6.15 codebase. + +The Homebrew patches are themselves backports of changes in Python 3.9 +and 3.10. That patch can be found at: + +https://github.com/Homebrew/formula-patches/blob/master/python/3.8.7.patch + +diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst +index a7cc0c84df..f25f3c78d9 100644 +--- a/Doc/library/ctypes.rst ++++ b/Doc/library/ctypes.rst +@@ -1551,6 +1551,13 @@ They are instances of a private class: + value usable as argument (integer, string, ctypes instance). This allows + defining adapters that can adapt custom objects as function parameters. + ++ .. attribute:: variadic ++ ++ Assign a boolean to specify that the function takes a variable number of ++ arguments. This does not matter on most platforms, but for Apple arm64 ++ platforms variadic functions have a different calling convention than ++ normal functions. ++ + .. attribute:: errcheck + + Assign a Python function or another callable to this attribute. The +diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py +index 56ab0ad732..013b1e9ce7 100644 +--- a/Lib/test/test_unicode.py ++++ b/Lib/test/test_unicode.py +@@ -2443,11 +2443,14 @@ class CAPITest(unittest.TestCase): + def test_from_format(self): + support.import_module('ctypes') + from ctypes import ( ++ c_char_p, + pythonapi, py_object, sizeof, + c_int, c_long, c_longlong, c_ssize_t, + c_uint, c_ulong, c_ulonglong, c_size_t, c_void_p) + name = "PyUnicode_FromFormat" + _PyUnicode_FromFormat = getattr(pythonapi, name) ++ _PyUnicode_FromFormat.argtypes = (c_char_p,) ++ _PyUnicode_FromFormat.variadic = True + _PyUnicode_FromFormat.restype = py_object + + def PyUnicode_FromFormat(format, *args): +diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c +index 24d64858ed..351f274ad3 100644 +--- a/Modules/_ctypes/_ctypes.c ++++ b/Modules/_ctypes/_ctypes.c +@@ -3120,6 +3120,34 @@ PyCFuncPtr_get_restype(PyCFuncPtrObject *self, void *Py_UNUSED(ignored)) + } + } + ++static int ++PyCFuncPtr_set_variadic(PyCFuncPtrObject *self, PyObject *ob) ++{ ++ StgDictObject *dict = PyObject_stgdict((PyObject *)self); ++ assert(dict); ++ int r = PyObject_IsTrue(ob); ++ if (r == 1) { ++ dict->flags |= FUNCFLAG_VARIADIC; ++ return 0; ++ } else if (r == 0) { ++ dict->flags &= ~FUNCFLAG_VARIADIC; ++ return 0; ++ } else { ++ return -1; ++ } ++} ++ ++static PyObject * ++PyCFuncPtr_get_variadic(PyCFuncPtrObject *self) ++{ ++ StgDictObject *dict = PyObject_stgdict((PyObject *)self); ++ assert(dict); /* Cannot be NULL for PyCFuncPtrObject instances */ ++ if (dict->flags & FUNCFLAG_VARIADIC) ++ Py_RETURN_TRUE; ++ else ++ Py_RETURN_FALSE; ++} ++ + static int + PyCFuncPtr_set_argtypes(PyCFuncPtrObject *self, PyObject *ob, void *Py_UNUSED(ignored)) + { +@@ -3166,6 +3194,8 @@ static PyGetSetDef PyCFuncPtr_getsets[] = { + { "argtypes", (getter)PyCFuncPtr_get_argtypes, + (setter)PyCFuncPtr_set_argtypes, + "specify the argument types", NULL }, ++ { "variadic", (getter)PyCFuncPtr_get_variadic, (setter)PyCFuncPtr_set_variadic, ++ "specify if function takes variable number of arguments", NULL }, + { NULL, NULL } + }; + +@@ -5576,6 +5606,7 @@ PyInit__ctypes(void) + PyModule_AddObject(m, "FUNCFLAG_USE_ERRNO", PyLong_FromLong(FUNCFLAG_USE_ERRNO)); + PyModule_AddObject(m, "FUNCFLAG_USE_LASTERROR", PyLong_FromLong(FUNCFLAG_USE_LASTERROR)); + PyModule_AddObject(m, "FUNCFLAG_PYTHONAPI", PyLong_FromLong(FUNCFLAG_PYTHONAPI)); ++ PyModule_AddObject(m, "FUNCFLAG_VARIADIC", PyLong_FromLong(FUNCFLAG_VARIADIC)); + PyModule_AddStringConstant(m, "__version__", "1.1.0"); + + PyModule_AddObject(m, "_memmove_addr", PyLong_FromVoidPtr(memmove)); +diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c +index 2bb289bce0..12951eadbf 100644 +--- a/Modules/_ctypes/callproc.c ++++ b/Modules/_ctypes/callproc.c +@@ -752,7 +754,8 @@ static int _call_function_pointer(int flags, + ffi_type **atypes, + ffi_type *restype, + void *resmem, +- int argcount) ++ int argcount, ++ int argtypecount) + { + #ifdef WITH_THREAD + PyThreadState *_save = NULL; /* For Py_BLOCK_THREADS and Py_UNBLOCK_THREADS */ +@@ -780,15 +783,39 @@ static int _call_function_pointer(int flags, + if ((flags & FUNCFLAG_CDECL) == 0) + cc = FFI_STDCALL; + #endif +- if (FFI_OK != ffi_prep_cif(&cif, +- cc, +- argcount, +- restype, +- atypes)) { +- PyErr_SetString(PyExc_RuntimeError, +- "ffi_prep_cif failed"); +- return -1; ++ ++#if HAVE_FFI_PREP_CIF_VAR ++ /* Everyone SHOULD set f.variadic=True on variadic function pointers, but ++ * lots of existing code will not. If there's at least one arg and more ++ * args are passed than are defined in the prototype, then it must be a ++ * variadic function. */ ++ if ((flags & FUNCFLAG_VARIADIC) || ++ (argtypecount != 0 && argcount > argtypecount)) ++ { ++ if (FFI_OK != ffi_prep_cif_var(&cif, ++ cc, ++ argtypecount, ++ argcount, ++ restype, ++ atypes)) { ++ PyErr_SetString(PyExc_RuntimeError, ++ "ffi_prep_cif_var failed"); ++ return -1; ++ } ++ } else { ++#endif ++ if (FFI_OK != ffi_prep_cif(&cif, ++ cc, ++ argcount, ++ restype, ++ atypes)) { ++ PyErr_SetString(PyExc_RuntimeError, ++ "ffi_prep_cif failed"); ++ return -1; ++ } ++#if HAVE_FFI_PREP_CIF_VAR + } ++#endif + + if (flags & (FUNCFLAG_USE_ERRNO | FUNCFLAG_USE_LASTERROR)) { + error_object = _ctypes_get_errobj(&space); +@@ -1181,9 +1208,8 @@ PyObject *_ctypes_callproc(PPROC pProc, + + if (-1 == _call_function_pointer(flags, pProc, avalues, atypes, + rtype, resbuf, +- Py_SAFE_DOWNCAST(argcount, +- Py_ssize_t, +- int))) ++ Py_SAFE_DOWNCAST(argcount, Py_ssize_t, int), ++ Py_SAFE_DOWNCAST(argtype_count, Py_ssize_t, int))) + goto cleanup; + + #ifdef WORDS_BIGENDIAN +diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h +index 5d3b966338..1299ec25aa 100644 +--- a/Modules/_ctypes/ctypes.h ++++ b/Modules/_ctypes/ctypes.h +@@ -285,6 +285,7 @@ PyObject *_ctypes_callproc(PPROC pProc, + #define FUNCFLAG_PYTHONAPI 0x4 + #define FUNCFLAG_USE_ERRNO 0x8 + #define FUNCFLAG_USE_LASTERROR 0x10 ++#define FUNCFLAG_VARIADIC 0x20 + + #define TYPEFLAG_ISPOINTER 0x100 + #define TYPEFLAG_HASPOINTER 0x200 +diff --git a/setup.py b/setup.py +index 8e03c77997..3b124c4b7b 100644 +--- a/setup.py ++++ b/setup.py +@@ -167,6 +167,13 @@ def macosx_sdk_specified(): + macosx_sdk_root() + return MACOS_SDK_SPECIFIED + ++def is_macosx_at_least(vers): ++ if host_platform == 'darwin': ++ dep_target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET') ++ if dep_target: ++ return tuple(map(int, str(dep_target).split('.'))) >= vers ++ return False ++ + def is_macosx_sdk_path(path): + """ + Returns True if 'path' can be located in an OSX SDK +@@ -175,6 +182,13 @@ def is_macosx_sdk_path(path): + or path.startswith('/System/') + or path.startswith('/Library/') ) + ++def grep_headers_for(function, headers): ++ for header in headers: ++ with open(header, 'r') as f: ++ if function in f.read(): ++ return True ++ return False ++ + def find_file(filename, std_dirs, paths): + """Searches for the directory where a given file is located, + and returns a possibly-empty list of additional directories, or None +@@ -2115,7 +2129,11 @@ class PyBuildExt(build_ext): + return True + + def detect_ctypes(self, inc_dirs, lib_dirs): +- self.use_system_libffi = False ++ if not sysconfig.get_config_var("LIBFFI_INCLUDEDIR") and is_macosx_at_least((10,15)): ++ self.use_system_libffi = True ++ else: ++ self.use_system_libffi = '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS") ++ + include_dirs = [] + extra_compile_args = [] + extra_link_args = [] +@@ -2162,20 +2180,30 @@ class PyBuildExt(build_ext): + libraries=math_libs) + self.extensions.extend([ext, ext_test]) + ++ ffi_inc = sysconfig.get_config_var("LIBFFI_INCLUDEDIR") ++ ffi_lib = None ++ inc_dirs = self.compiler.include_dirs[:] ++ + if host_platform == 'darwin': +- if '--with-system-ffi' not in sysconfig.get_config_var("CONFIG_ARGS"): +- return +- # OS X 10.5 comes with libffi.dylib; the include files are +- # in /usr/include/ffi +- inc_dirs.append('/usr/include/ffi') ++ if not self.use_system_libffi: ++ return ++ ffi_in_sdk = os.path.join(macosx_sdk_root(), "usr/include/ffi") ++ if os.path.exists(ffi_in_sdk): ++ ffi_inc = ffi_in_sdk ++ ffi_lib = 'ffi' ++ else: ++ # OS X 10.5 comes with libffi.dylib; the include files are ++ # in /usr/include/ffi ++ inc_dirs.append('/usr/include/ffi') + elif '--without-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS"): + return + +- ffi_inc = [sysconfig.get_config_var("LIBFFI_INCLUDEDIR")] +- if not ffi_inc or ffi_inc[0] == '': +- ffi_inc = find_file('ffi.h', [], inc_dirs) +- if ffi_inc is not None: +- ffi_h = ffi_inc[0] + '/ffi.h' ++ if not ffi_inc: ++ found = find_file('ffi.h', [], inc_dirs) ++ if found: ++ ffi_inc = found[0] ++ if ffi_inc: ++ ffi_h = ffi_inc + '/ffi.h' + with open(ffi_h) as f: + for line in f: + line = line.strip() +@@ -2186,15 +2214,22 @@ class PyBuildExt(build_ext): + ffi_inc = None + print('Header file {} does not define LIBFFI_H or ' + 'ffi_wrapper_h'.format(ffi_h)) +- ffi_lib = None +- if ffi_inc is not None: ++ if ffi_lib is None and ffi_inc is not None: + for lib_name in ('ffi', 'ffi_pic'): + if (self.compiler.find_library_file(lib_dirs, lib_name)): + ffi_lib = lib_name + break + + if ffi_inc and ffi_lib: +- ext.include_dirs.extend(ffi_inc) ++ ffi_headers = glob(os.path.join(ffi_inc, '*.h')) ++ if grep_headers_for('ffi_closure_alloc', ffi_headers): ++ try: ++ sources.remove('_ctypes/malloc_closure.c') ++ except ValueError: ++ pass ++ if grep_headers_for('ffi_prep_cif_var', ffi_headers): ++ ext.extra_compile_args.append("-DHAVE_FFI_PREP_CIF_VAR=1") ++ ext.include_dirs.append(ffi_inc) + ext.libraries.append(ffi_lib) + self.use_system_libffi = True + +-- +2.30.1 (Apple Git-130) + diff --git a/plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0005-BPO-41100-Support-macOS-11-when-building-GH-21113.patch b/plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0005-BPO-41100-Support-macOS-11-when-building-GH-21113.patch new file mode 100644 index 00000000..9d48c81d --- /dev/null +++ b/plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0005-BPO-41100-Support-macOS-11-when-building-GH-21113.patch @@ -0,0 +1,48 @@ +From 8ea6353f60625c96ce96588c70ff24a77f8c71f9 Mon Sep 17 00:00:00 2001 +From: Ronald Oussoren +Date: Thu, 25 Jun 2020 16:55:48 +0200 +Subject: [PATCH] BPO-41100: Support macOS 11 when building (GH-21113) + +--- + Misc/NEWS.d/next/macOS/2020-06-24-13-51-57.bpo-41100.mcHdc5.rst | 1 + + configure | 2 +- + configure.ac | 2 +- + 3 files changed, 3 insertions(+), 2 deletions(-) + create mode 100644 Misc/NEWS.d/next/macOS/2020-06-24-13-51-57.bpo-41100.mcHdc5.rst + +diff --git a/Misc/NEWS.d/next/macOS/2020-06-24-13-51-57.bpo-41100.mcHdc5.rst b/Misc/NEWS.d/next/macOS/2020-06-24-13-51-57.bpo-41100.mcHdc5.rst +new file mode 100644 +index 0000000000..ded66b567a +--- /dev/null ++++ b/Misc/NEWS.d/next/macOS/2020-06-24-13-51-57.bpo-41100.mcHdc5.rst +@@ -0,0 +1 @@ ++Support macOS 11 when building. +diff --git a/configure b/configure +index c51f396824..5024860ca4 100755 +--- a/configure ++++ b/configure +@@ -3375,7 +3375,7 @@ $as_echo "#define _BSD_SOURCE 1" >>confdefs.h + # has no effect, don't bother defining them + Darwin/[6789].*) + define_xopen_source=no;; +- Darwin/1[0-9].*) ++ Darwin/[12][0-9].*) + define_xopen_source=no;; + # On AIX 4 and 5.1, mbstate_t is defined only when _XOPEN_SOURCE == 500 but + # used in wcsnrtombs() and mbsnrtowcs() even if _XOPEN_SOURCE is not defined +diff --git a/configure.ac b/configure.ac +index 70deefb6b9..5a3e340aa3 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -495,7 +495,7 @@ case $ac_sys_system/$ac_sys_release in + # has no effect, don't bother defining them + Darwin/@<:@6789@:>@.*) + define_xopen_source=no;; +- Darwin/1@<:@0-9@:>@.*) ++ Darwin/@<:@[12]@:>@@<:@0-9@:>@.*) + define_xopen_source=no;; + # On AIX 4 and 5.1, mbstate_t is defined only when _XOPEN_SOURCE == 500 but + # used in wcsnrtombs() and mbsnrtowcs() even if _XOPEN_SOURCE is not defined +-- +2.30.1 (Apple Git-130) + diff --git a/plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0006-bpo-41100-fix-_decimal-for-arm64-Mac-OS-GH-21228.patch b/plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0006-bpo-41100-fix-_decimal-for-arm64-Mac-OS-GH-21228.patch new file mode 100644 index 00000000..12022a4f --- /dev/null +++ b/plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0006-bpo-41100-fix-_decimal-for-arm64-Mac-OS-GH-21228.patch @@ -0,0 +1,37 @@ +From 604d95e235d86465b8c17f02095edcaf18464d4c Mon Sep 17 00:00:00 2001 +From: Lawrence D'Anna <64555057+lawrence-danna-apple@users.noreply.github.com> +Date: Tue, 30 Jun 2020 02:15:46 -0700 +Subject: [PATCH] bpo-41100: fix _decimal for arm64 Mac OS (GH-21228) + +Patch by Lawrence Danna. +--- + .../Core and Builtins/2020-06-30-04-44-29.bpo-41100.PJwA6F.rst | 1 + + Modules/_decimal/libmpdec/mpdecimal.h | 3 +++ + 2 files changed, 4 insertions(+) + create mode 100644 Misc/NEWS.d/next/Core and Builtins/2020-06-30-04-44-29.bpo-41100.PJwA6F.rst + +diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-06-30-04-44-29.bpo-41100.PJwA6F.rst b/Misc/NEWS.d/next/Core and Builtins/2020-06-30-04-44-29.bpo-41100.PJwA6F.rst +new file mode 100644 +index 0000000000..d6176d69f0 +--- /dev/null ++++ b/Misc/NEWS.d/next/Core and Builtins/2020-06-30-04-44-29.bpo-41100.PJwA6F.rst +@@ -0,0 +1 @@ ++add arm64 to the allowable Mac OS arches in mpdecimal.h +\ No newline at end of file +diff --git a/Modules/_decimal/libmpdec/mpdecimal.h b/Modules/_decimal/libmpdec/mpdecimal.h +index 108b76efa8..35ce429f60 100644 +--- a/Modules/_decimal/libmpdec/mpdecimal.h ++++ b/Modules/_decimal/libmpdec/mpdecimal.h +@@ -135,6 +135,9 @@ const char *mpd_version(void); + #elif defined(__x86_64__) + #define CONFIG_64 + #define ASM ++ #elif defined(__arm64__) ++ #define CONFIG_64 ++ #define ANSI + #else + #error "unknown architecture for universal build." + #endif +-- +2.30.1 (Apple Git-130) +