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).pull/2208/head
| @ -0,0 +1,41 @@ | |||
| From 002501946bad91a308f37a09204393c172f03c3e Mon Sep 17 00:00:00 2001 | |||
| From: Takumi Sueda <puhitaku@gmail.com> | |||
| 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) | |||
| @ -0,0 +1,93 @@ | |||
| From c7302116573d853d3181133477d9d0e4d4d3abfd Mon Sep 17 00:00:00 2001 | |||
| From: Ned Deily <nad@python.org> | |||
| 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 - </dev/null 2>%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) | |||
| @ -0,0 +1,240 @@ | |||
| From 942db3e6b96225ef8330f5329c702d62483c6ef8 Mon Sep 17 00:00:00 2001 | |||
| From: Takumi Sueda <puhitaku@gmail.com> | |||
| 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) | |||
| @ -0,0 +1,315 @@ | |||
| From: Christian Hammond <christian@beanbaginc.com> | |||
| 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) | |||
| @ -0,0 +1,48 @@ | |||
| From 8ea6353f60625c96ce96588c70ff24a77f8c71f9 Mon Sep 17 00:00:00 2001 | |||
| From: Ronald Oussoren <ronaldoussoren@mac.com> | |||
| 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) | |||
| @ -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) | |||