diff options
author | sjmulder <sjmulder@pkgsrc.org> | 2020-11-12 10:58:20 +0000 |
---|---|---|
committer | sjmulder <sjmulder@pkgsrc.org> | 2020-11-12 10:58:20 +0000 |
commit | cf39a582219d187fbfda344205aabfaa10d75ffc (patch) | |
tree | 89b788aab06570b5c02c6de1dd23474b3fe2457c /lang/python39 | |
parent | a59cc839c3fb0dc9ffcae898e79644a1ef71c1b6 (diff) | |
download | pkgsrc-cf39a582219d187fbfda344205aabfaa10d75ffc.tar.gz |
lang/python39: Fix for macOS 11 and Apple Silicon
(Apple Silicon being their aarch64 platform.)
Patches consist of:
- Upstream work: https://github.com/python/cpython/pull/22855
- Fix for setup.py to find libbz2.tbd and libz.tbd now that with the
shared library cache there's nothing in /usr/lib.
See: https://bugs.python.org/issue41116
- Addition of __arch64__ case to fix _decimal module. A very similar fix
has since been committed upstream.
Diffstat (limited to 'lang/python39')
24 files changed, 2910 insertions, 24 deletions
diff --git a/lang/python39/distinfo b/lang/python39/distinfo index 4cb329a6409..d680ecb7e0e 100644 --- a/lang/python39/distinfo +++ b/lang/python39/distinfo @@ -1,21 +1,41 @@ -$NetBSD: distinfo,v 1.1 2020/10/10 20:19:47 adam Exp $ +$NetBSD: distinfo,v 1.2 2020/11/12 10:58:20 sjmulder Exp $ SHA1 (Python-3.9.0.tar.xz) = ff1fc8c37d5d4b09ec3bf0d84f3e5b97745c6704 RMD160 (Python-3.9.0.tar.xz) = 822fd1ea11f3ca303a08317f6db61f2a1e03e5ef SHA512 (Python-3.9.0.tar.xz) = b141039c9701a8cb0d15cd11a279153077524af4d0599e7d2c7279d4c18d05fda06b33ef82342d875de996c7117b7dc6eb154dc3669d38a1efa99801aeec6c5e Size (Python-3.9.0.tar.xz) = 18866140 bytes +SHA1 (patch-Lib___osx__support.py) = 4ccccb81381cd7bf4a8bbc3e376d1234cf2266d5 +SHA1 (patch-Lib_ctypes_macholib_dyld.py) = d7f3e0c63d6926db253fbe923dd97995478d528c +SHA1 (patch-Lib_ctypes_test_test__macholib.py) = bd887357759975b7a497c4079bc730e9c578ceed SHA1 (patch-Lib_ctypes_util.py) = 032cc99ebad93ddddfd89073c60424a952e3faa3 SHA1 (patch-Lib_distutils_command_install.py) = 6fc6f5d918b7581fc62cd0fe55857ee932c3a341 SHA1 (patch-Lib_distutils_sysconfig.py) = 6822eafb4dfded86d7f7353831816aeb8119e6cf +SHA1 (patch-Lib_distutils_tests_test__build__ext.py) = 145a0f01b3602c582e033081a35d4d86245575f9 SHA1 (patch-Lib_distutils_unixccompiler.py) = 2e65a8dd5dd3fe25957206c062106fa7a6fc4e69 SHA1 (patch-Lib_lib2to3_pgen2_driver.py) = 5d6dab14197f27363394ff1aeee22a8ced8026d2 SHA1 (patch-Lib_sysconfig.py) = a4f009ed73ebbd9d9c4bf7e12b7981182ed8fd7c +SHA1 (patch-Lib_test_test__bytes.py) = 72559fdcb09f2c0b0c7b62649c249775d359d72e +SHA1 (patch-Lib_test_test__platform.py) = 36311733729ac95159b3177dc0c16e6f4aa2f2b9 +SHA1 (patch-Lib_test_test__unicode.py) = 14fe4dd1011dbe262459f735a643774e0d38c99e +SHA1 (patch-Mac_BuildScript_build-installer.py) = 24641c70facfded736ccc2be069d0e2ae63f63fd +SHA1 (patch-Mac_Tools_pythonw.c) = fe128efe942853f0825c1a1fa17842201716dfdf SHA1 (patch-Makefile.pre.in) = d42f9f5bca1dd663f64122dc95b49111452fe6e8 +SHA1 (patch-Modules___ctypes_callbacks.c) = 95750090d396a647fc12f7f7fad8c591ca4dcdec +SHA1 (patch-Modules___ctypes_callproc.c) = 86f27c466a67ebf72d863febece33aa8b1f9f719 +SHA1 (patch-Modules___ctypes_ctypes.h) = 641c0af4d550c9140549ce2f2df6239c2c954a06 +SHA1 (patch-Modules___ctypes_malloc__closure.c) = 7e8f491ce66acb6d07e8830ee881edbf0aaac538 +SHA1 (patch-Modules___decimal_libmpdec_mpdecimal.h) = 8d302abacc5737fe7620d4738fff6c5c3ed387c7 +SHA1 (patch-Modules_getpath.c) = d7114d21d7d9c7167fad259b115cb02e4153c531 SHA1 (patch-Modules_makesetup) = a06786eebffadecedba5e3a50a9785fb47613567 SHA1 (patch-Modules_nismodule.c) = 1bafe9b06359586d027a77011b103877590d947d +SHA1 (patch-Modules_posixmodule.c) = c592ef4ebe650f672a15ff9887cbeed2ca73b666 SHA1 (patch-Modules_socketmodule.c) = 02c447f980a08e2185df78d2f13373574f414304 SHA1 (patch-Modules_socketmodule.h) = 61fe96a79d4ccf3e7768eb79dd7e29a50a85328b +SHA1 (patch-Modules_timemodule.c) = 8c8e9e43b6d165c1a7df6142a6bcd430003ed165 +SHA1 (patch-Python_bootstrap__hash.c) = cbc2839675182a344591ba672187b166f166499b +SHA1 (patch-Python_pytime.c) = 1bb39b7060c1f337562208dc6611672eaf2f586b SHA1 (patch-Python_thread__pthread.h) = fb81eaa604b4ed7c1b64c3f4731d58a8aee257be -SHA1 (patch-configure) = fdb9594b1f738c38672bf247dd91da95d9160a3c -SHA1 (patch-pyconfig.h.in) = 4bc6e95441cb5faae94d1d52aeaaa10ae01385b6 -SHA1 (patch-setup.py) = 5cd3600318a883a4308b0bb2d51e3feadf9f5ff5 +SHA1 (patch-configure) = 371a65a2cb10fe7709d30a16358b48bc2e0a4aa6 +SHA1 (patch-configure.ac) = 4ce75ef922e015adf095cb481c829b11c0454efe +SHA1 (patch-pyconfig.h.in) = 7c1c997c089f882fbd334b81c04a03dbaebb2c41 +SHA1 (patch-setup.py) = a9e467f8aed7085a982af6a1273b883550d06610 diff --git a/lang/python39/patches/patch-Lib___osx__support.py b/lang/python39/patches/patch-Lib___osx__support.py new file mode 100644 index 00000000000..cc9c6c410cc --- /dev/null +++ b/lang/python39/patches/patch-Lib___osx__support.py @@ -0,0 +1,81 @@ +$NetBSD: patch-Lib___osx__support.py,v 1.1 2020/11/12 10:58:21 sjmulder Exp $ + +Support for macOS 11 and Apple Silicon (ARM). Backported from: +https://github.com/python/cpython/pull/22855 + +--- Lib/_osx_support.py.orig 2020-10-05 15:07:58.000000000 +0000 ++++ Lib/_osx_support.py +@@ -110,6 +110,26 @@ def _get_system_version(): + + return _SYSTEM_VERSION + ++_SYSTEM_VERSION_TUPLE = None ++def _get_system_version_tuple(): ++ """ ++ Return the macOS system version as a tuple ++ ++ The return value is safe to use to compare ++ two version numbers. ++ """ ++ global _SYSTEM_VERSION_TUPLE ++ if _SYSTEM_VERSION_TUPLE is None: ++ osx_version = _get_system_version() ++ if osx_version: ++ try: ++ _SYSTEM_VERSION_TUPLE = tuple(int(i) for i in osx_version.split('.')) ++ except ValueError: ++ _SYSTEM_VERSION_TUPLE = () ++ ++ return _SYSTEM_VERSION_TUPLE ++ ++ + def _remove_original_values(_config_vars): + """Remove original unmodified values for testing""" + # This is needed for higher-level cross-platform tests of get_platform. +@@ -132,14 +152,18 @@ def _supports_universal_builds(): + # builds, in particular -isysroot and -arch arguments to the compiler. This + # is in support of allowing 10.4 universal builds to run on 10.3.x systems. + +- osx_version = _get_system_version() +- if osx_version: +- try: +- osx_version = tuple(int(i) for i in osx_version.split('.')) +- except ValueError: +- osx_version = '' ++ osx_version = _get_system_version_tuple() + return bool(osx_version >= (10, 4)) if osx_version else False + ++def _supports_arm64_builds(): ++ """Returns True if arm64 builds are supported on this system""" ++ # There are two sets of systems supporting macOS/arm64 builds: ++ # 1. macOS 11 and later, unconditionally ++ # 2. macOS 10.15 with Xcode 12.2 or later ++ # For now the second category is ignored. ++ osx_version = _get_system_version_tuple() ++ return osx_version >= (11, 0) if osx_version else False ++ + + def _find_appropriate_compiler(_config_vars): + """Find appropriate C compiler for extension module builds""" +@@ -331,6 +355,12 @@ def compiler_fixup(compiler_so, cc_args) + except ValueError: + break + ++ elif not _supports_arm64_builds(): ++ # Look for "-arch arm64" and drop that ++ for idx in range(len(compiler_so)): ++ if compiler_so[idx] == '-arch' and compiler_so[idx+1] == "arm64": ++ del compiler_so[idx:idx+2] ++ + if 'ARCHFLAGS' in os.environ and not stripArch: + # User specified different -arch flags in the environ, + # see also distutils.sysconfig +@@ -481,6 +511,8 @@ def get_platform_osx(_config_vars, osnam + + if len(archs) == 1: + machine = archs[0] ++ elif archs == ('arm64', 'x86_64'): ++ machine = 'universal2' + elif archs == ('i386', 'ppc'): + machine = 'fat' + elif archs == ('i386', 'x86_64'): diff --git a/lang/python39/patches/patch-Lib_ctypes_macholib_dyld.py b/lang/python39/patches/patch-Lib_ctypes_macholib_dyld.py new file mode 100644 index 00000000000..a4f2d2acb1e --- /dev/null +++ b/lang/python39/patches/patch-Lib_ctypes_macholib_dyld.py @@ -0,0 +1,35 @@ +$NetBSD: patch-Lib_ctypes_macholib_dyld.py,v 1.1 2020/11/12 10:58:21 sjmulder Exp $ + +Support for macOS 11 and Apple Silicon (ARM). Backported from: +https://github.com/python/cpython/pull/22855 + +--- Lib/ctypes/macholib/dyld.py.orig 2020-10-05 15:07:58.000000000 +0000 ++++ Lib/ctypes/macholib/dyld.py +@@ -6,6 +6,11 @@ import os + from ctypes.macholib.framework import framework_info + from ctypes.macholib.dylib import dylib_info + from itertools import * ++try: ++ from _ctypes import _dyld_shared_cache_contains_path ++except ImportError: ++ def _dyld_shared_cache_contains_path(*args): ++ raise NotImplementedError + + __all__ = [ + 'dyld_find', 'framework_find', +@@ -122,8 +127,15 @@ def dyld_find(name, executable_path=None + dyld_executable_path_search(name, executable_path), + dyld_default_search(name, env), + ), env): ++ + if os.path.isfile(path): + return path ++ try: ++ if _dyld_shared_cache_contains_path(path): ++ return path ++ except NotImplementedError: ++ pass ++ + raise ValueError("dylib %s could not be found" % (name,)) + + def framework_find(fn, executable_path=None, env=None): diff --git a/lang/python39/patches/patch-Lib_ctypes_test_test__macholib.py b/lang/python39/patches/patch-Lib_ctypes_test_test__macholib.py new file mode 100644 index 00000000000..b41064bb036 --- /dev/null +++ b/lang/python39/patches/patch-Lib_ctypes_test_test__macholib.py @@ -0,0 +1,36 @@ +$NetBSD: patch-Lib_ctypes_test_test__macholib.py,v 1.1 2020/11/12 10:58:21 sjmulder Exp $ + +Support for macOS 11 and Apple Silicon (ARM). Backported from: +https://github.com/python/cpython/pull/22855 + +--- Lib/ctypes/test/test_macholib.py.orig 2020-10-05 15:07:58.000000000 +0000 ++++ Lib/ctypes/test/test_macholib.py +@@ -45,19 +45,22 @@ def find_lib(name): + class MachOTest(unittest.TestCase): + @unittest.skipUnless(sys.platform == "darwin", 'OSX-specific test') + def test_find(self): +- +- self.assertEqual(find_lib('pthread'), +- '/usr/lib/libSystem.B.dylib') ++ # On Mac OS 11, system dylibs are only present in the shared cache, ++ # so symlinks like libpthread.dylib -> libSystem.B.dylib will not ++ # be resolved by dyld_find ++ self.assertIn(find_lib('pthread'), ++ ('/usr/lib/libSystem.B.dylib', '/usr/lib/libpthread.dylib')) + + result = find_lib('z') + # Issue #21093: dyld default search path includes $HOME/lib and + # /usr/local/lib before /usr/lib, which caused test failures if + # a local copy of libz exists in one of them. Now ignore the head + # of the path. +- self.assertRegex(result, r".*/lib/libz\..*.*\.dylib") ++ self.assertRegex(result, r".*/lib/libz.*\.dylib") + +- self.assertEqual(find_lib('IOKit'), +- '/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit') ++ self.assertIn(find_lib('IOKit'), ++ ('/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit', ++ '/System/Library/Frameworks/IOKit.framework/IOKit')) + + if __name__ == "__main__": + unittest.main() diff --git a/lang/python39/patches/patch-Lib_distutils_tests_test__build__ext.py b/lang/python39/patches/patch-Lib_distutils_tests_test__build__ext.py new file mode 100644 index 00000000000..2a1fd4adc22 --- /dev/null +++ b/lang/python39/patches/patch-Lib_distutils_tests_test__build__ext.py @@ -0,0 +1,13 @@ +$NetBSD: patch-Lib_distutils_tests_test__build__ext.py,v 1.1 2020/11/12 10:58:21 sjmulder Exp $ + +--- Lib/distutils/tests/test_build_ext.py.orig 2020-10-05 15:07:58.000000000 +0000 ++++ Lib/distutils/tests/test_build_ext.py +@@ -492,7 +492,7 @@ class BuildExtTestCase(TempdirManager, + # format the target value as defined in the Apple + # Availability Macros. We can't use the macro names since + # at least one value we test with will not exist yet. +- if target[1] < 10: ++ if target[:2] < (10, 10): + # for 10.1 through 10.9.x -> "10n0" + target = '%02d%01d0' % target + else: diff --git a/lang/python39/patches/patch-Lib_test_test__bytes.py b/lang/python39/patches/patch-Lib_test_test__bytes.py new file mode 100644 index 00000000000..5ad794d926b --- /dev/null +++ b/lang/python39/patches/patch-Lib_test_test__bytes.py @@ -0,0 +1,15 @@ +$NetBSD: patch-Lib_test_test__bytes.py,v 1.1 2020/11/12 10:58:21 sjmulder Exp $ + +Support for macOS 11 and Apple Silicon (ARM). Backported from: +https://github.com/python/cpython/pull/22855 + +--- Lib/test/test_bytes.py.orig 2020-10-05 15:07:58.000000000 +0000 ++++ Lib/test/test_bytes.py +@@ -1034,6 +1034,7 @@ class BytesTest(BaseBytesTest, unittest. + c_char_p) + + PyBytes_FromFormat = pythonapi.PyBytes_FromFormat ++ PyBytes_FromFormat.argtypes = (c_char_p,) + PyBytes_FromFormat.restype = py_object + + # basic tests diff --git a/lang/python39/patches/patch-Lib_test_test__platform.py b/lang/python39/patches/patch-Lib_test_test__platform.py new file mode 100644 index 00000000000..7778305ed3f --- /dev/null +++ b/lang/python39/patches/patch-Lib_test_test__platform.py @@ -0,0 +1,16 @@ +$NetBSD: patch-Lib_test_test__platform.py,v 1.1 2020/11/12 10:58:21 sjmulder Exp $ + +Support for macOS 11 and Apple Silicon (ARM). Backported from: +https://github.com/python/cpython/pull/22855 + +--- Lib/test/test_platform.py.orig 2020-10-05 15:07:58.000000000 +0000 ++++ Lib/test/test_platform.py +@@ -245,7 +245,7 @@ class PlatformTest(unittest.TestCase): + self.assertEqual(res[1], ('', '', '')) + + if sys.byteorder == 'little': +- self.assertIn(res[2], ('i386', 'x86_64')) ++ self.assertIn(res[2], ('i386', 'x86_64', 'arm64')) + else: + self.assertEqual(res[2], 'PowerPC') + diff --git a/lang/python39/patches/patch-Lib_test_test__unicode.py b/lang/python39/patches/patch-Lib_test_test__unicode.py new file mode 100644 index 00000000000..b139805ea64 --- /dev/null +++ b/lang/python39/patches/patch-Lib_test_test__unicode.py @@ -0,0 +1,21 @@ +$NetBSD: patch-Lib_test_test__unicode.py,v 1.1 2020/11/12 10:58:21 sjmulder Exp $ + +Support for macOS 11 and Apple Silicon (ARM). Backported from: +https://github.com/python/cpython/pull/22855 + +--- Lib/test/test_unicode.py.orig 2020-10-05 15:07:58.000000000 +0000 ++++ Lib/test/test_unicode.py +@@ -2523,11 +2523,13 @@ 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.restype = py_object + + def PyUnicode_FromFormat(format, *args): diff --git a/lang/python39/patches/patch-Mac_BuildScript_build-installer.py b/lang/python39/patches/patch-Mac_BuildScript_build-installer.py new file mode 100644 index 00000000000..0b2539090c8 --- /dev/null +++ b/lang/python39/patches/patch-Mac_BuildScript_build-installer.py @@ -0,0 +1,69 @@ +$NetBSD: patch-Mac_BuildScript_build-installer.py,v 1.1 2020/11/12 10:58:21 sjmulder Exp $ + +Support for macOS 11 and Apple Silicon (ARM). Backported from: +https://github.com/python/cpython/pull/22855 + +--- Mac/BuildScript/build-installer.py.orig 2020-10-05 15:07:58.000000000 +0000 ++++ Mac/BuildScript/build-installer.py +@@ -116,7 +116,8 @@ WORKDIR = "/tmp/_py" + DEPSRC = os.path.join(WORKDIR, 'third-party') + DEPSRC = os.path.expanduser('~/Universal/other-sources') + +-universal_opts_map = { '32-bit': ('i386', 'ppc',), ++universal_opts_map = { 'universal2': ('arm64', 'x86_64'), ++ '32-bit': ('i386', 'ppc',), + '64-bit': ('x86_64', 'ppc64',), + 'intel': ('i386', 'x86_64'), + 'intel-32': ('i386',), +@@ -124,6 +125,7 @@ universal_opts_map = { '32-bit': ('i386' + '3-way': ('ppc', 'i386', 'x86_64'), + 'all': ('i386', 'ppc', 'x86_64', 'ppc64',) } + default_target_map = { ++ 'universal2': '10.9', + '64-bit': '10.5', + '3-way': '10.5', + 'intel': '10.5', +@@ -190,6 +192,27 @@ EXPECTED_SHARED_LIBS = {} + def internalTk(): + return getDeptargetTuple() >= (10, 6) + ++ ++def tweak_tcl_build(basedir, archList): ++ with open("Makefile", "r") as fp: ++ contents = fp.readlines() ++ ++ # For reasons I don't understand the tcl configure script ++ # decides that some stdlib symbols aren't present, before ++ # deciding that strtod is broken. ++ new_contents = [] ++ for line in contents: ++ if line.startswith("COMPAT_OBJS"): ++ # note: the space before strtod.o is intentional, ++ # the detection of a broken strtod results in ++ # "fixstrod.o" on this line. ++ for nm in ("strstr.o", "strtoul.o", " strtod.o"): ++ line = line.replace(nm, "") ++ new_contents.append(line) ++ ++ with open("Makefile", "w") as fp: ++ fp.writelines(new_contents) ++ + # List of names of third party software built with this installer. + # The names will be inserted into the rtf version of the License. + THIRD_PARTY_LIBS = [] +@@ -231,6 +257,7 @@ def library_recipes(): + '--libdir=/Library/Frameworks/Python.framework/Versions/%s/lib'%(getVersion(),), + ], + useLDFlags=False, ++ buildrecipe=tweak_tcl_build, + install='make TCL_LIBRARY=%(TCL_LIBRARY)s && make install TCL_LIBRARY=%(TCL_LIBRARY)s DESTDIR=%(DESTDIR)s'%{ + "DESTDIR": shellQuote(os.path.join(WORKDIR, 'libraries')), + "TCL_LIBRARY": shellQuote('/Library/Frameworks/Python.framework/Versions/%s/lib/tcl8.6'%(getVersion())), +@@ -801,6 +828,7 @@ def build_universal_openssl(basedir, arc + arch_opts = { + "i386": ["darwin-i386-cc"], + "x86_64": ["darwin64-x86_64-cc", "enable-ec_nistp_64_gcc_128"], ++ "arm64": ["darwin64-arm64-cc"], + "ppc": ["darwin-ppc-cc"], + "ppc64": ["darwin64-ppc-cc"], + } diff --git a/lang/python39/patches/patch-Mac_Tools_pythonw.c b/lang/python39/patches/patch-Mac_Tools_pythonw.c new file mode 100644 index 00000000000..aaedbdbfe2b --- /dev/null +++ b/lang/python39/patches/patch-Mac_Tools_pythonw.c @@ -0,0 +1,44 @@ +$NetBSD: patch-Mac_Tools_pythonw.c,v 1.1 2020/11/12 10:58:21 sjmulder Exp $ + +Support for macOS 11 and Apple Silicon (ARM). Backported from: +https://github.com/python/cpython/pull/22855 + +--- Mac/Tools/pythonw.c.orig 2020-10-05 15:07:58.000000000 +0000 ++++ Mac/Tools/pythonw.c +@@ -95,9 +95,6 @@ setup_spawnattr(posix_spawnattr_t* spawn + size_t count; + cpu_type_t cpu_types[1]; + short flags = 0; +-#ifdef __LP64__ +- int ch; +-#endif + + if ((errno = posix_spawnattr_init(spawnattr)) != 0) { + err(2, "posix_spawnattr_int"); +@@ -119,10 +116,16 @@ setup_spawnattr(posix_spawnattr_t* spawn + + #elif defined(__ppc__) + cpu_types[0] = CPU_TYPE_POWERPC; ++ + #elif defined(__i386__) + cpu_types[0] = CPU_TYPE_X86; ++ ++#elif defined(__arm64__) ++ cpu_types[0] = CPU_TYPE_ARM64; ++ + #else + # error "Unknown CPU" ++ + #endif + + if (posix_spawnattr_setbinpref_np(spawnattr, count, +@@ -220,7 +223,8 @@ main(int argc, char **argv) { + /* We're weak-linking to posix-spawnv to ensure that + * an executable build on 10.5 can work on 10.4. + */ +- if (posix_spawn != NULL) { ++ ++ if (&posix_spawn != NULL) { + posix_spawnattr_t spawnattr = NULL; + + setup_spawnattr(&spawnattr); diff --git a/lang/python39/patches/patch-Modules___ctypes_callbacks.c b/lang/python39/patches/patch-Modules___ctypes_callbacks.c new file mode 100644 index 00000000000..748239efb6a --- /dev/null +++ b/lang/python39/patches/patch-Modules___ctypes_callbacks.c @@ -0,0 +1,76 @@ +$NetBSD: patch-Modules___ctypes_callbacks.c,v 1.1 2020/11/12 10:58:21 sjmulder Exp $ + +Support for macOS 11 and Apple Silicon (ARM). Backported from: +https://github.com/python/cpython/pull/22855 + +--- Modules/_ctypes/callbacks.c.orig 2020-10-05 15:07:58.000000000 +0000 ++++ Modules/_ctypes/callbacks.c +@@ -1,6 +1,8 @@ + #include "Python.h" + #include "frameobject.h" + ++#include <stdbool.h> ++ + #include <ffi.h> + #ifdef MS_WIN32 + #include <windows.h> +@@ -18,7 +20,7 @@ CThunkObject_dealloc(PyObject *myself) + Py_XDECREF(self->callable); + Py_XDECREF(self->restype); + if (self->pcl_write) +- ffi_closure_free(self->pcl_write); ++ Py_ffi_closure_free(self->pcl_write); + PyObject_GC_Del(self); + } + +@@ -361,8 +363,7 @@ CThunkObject *_ctypes_alloc_callback(PyO + + assert(CThunk_CheckExact((PyObject *)p)); + +- p->pcl_write = ffi_closure_alloc(sizeof(ffi_closure), +- &p->pcl_exec); ++ p->pcl_write = Py_ffi_closure_alloc(sizeof(ffi_closure), &p->pcl_exec); + if (p->pcl_write == NULL) { + PyErr_NoMemory(); + goto error; +@@ -408,13 +409,35 @@ CThunkObject *_ctypes_alloc_callback(PyO + "ffi_prep_cif failed with %d", result); + goto error; + } +-#if defined(X86_DARWIN) || defined(POWERPC_DARWIN) +- result = ffi_prep_closure(p->pcl_write, &p->cif, closure_fcn, p); ++#if HAVE_FFI_PREP_CLOSURE_LOC ++# if USING_APPLE_OS_LIBFFI ++# define HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *) ++# else ++# define HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME 1 ++# endif ++ if (HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME) { ++ result = ffi_prep_closure_loc(p->pcl_write, &p->cif, closure_fcn, ++ p, ++ p->pcl_exec); ++ } else ++#endif ++ { ++#if USING_APPLE_OS_LIBFFI && defined(__arm64__) ++ PyErr_Format(PyExc_NotImplementedError, "ffi_prep_closure_loc() is missing"); ++ goto error; + #else +- result = ffi_prep_closure_loc(p->pcl_write, &p->cif, closure_fcn, +- p, +- p->pcl_exec); ++#ifdef MACOSX ++ #pragma clang diagnostic push ++ #pragma clang diagnostic ignored "-Wdeprecated-declarations" + #endif ++ result = ffi_prep_closure(p->pcl_write, &p->cif, closure_fcn, p); ++ ++#ifdef MACOSX ++ #pragma clang diagnostic pop ++#endif ++ ++#endif ++ } + if (result != FFI_OK) { + PyErr_Format(PyExc_RuntimeError, + "ffi_prep_closure failed with %d", result); diff --git a/lang/python39/patches/patch-Modules___ctypes_callproc.c b/lang/python39/patches/patch-Modules___ctypes_callproc.c new file mode 100644 index 00000000000..00df3806fdc --- /dev/null +++ b/lang/python39/patches/patch-Modules___ctypes_callproc.c @@ -0,0 +1,190 @@ +$NetBSD: patch-Modules___ctypes_callproc.c,v 1.1 2020/11/12 10:58:21 sjmulder Exp $ + +Support for macOS 11 and Apple Silicon (ARM). Backported from: +https://github.com/python/cpython/pull/22855 + +--- Modules/_ctypes/callproc.c.orig 2020-10-05 15:07:58.000000000 +0000 ++++ Modules/_ctypes/callproc.c +@@ -57,6 +57,8 @@ + #include "Python.h" + #include "structmember.h" // PyMemberDef + ++#include <stdbool.h> ++ + #ifdef MS_WIN32 + #include <windows.h> + #include <tchar.h> +@@ -64,6 +66,10 @@ + #include "ctypes_dlfcn.h" + #endif + ++#ifdef __APPLE__ ++#include <mach-o/dyld.h> ++#endif ++ + #ifdef MS_WIN32 + #include <malloc.h> + #endif +@@ -812,7 +818,8 @@ static int _call_function_pointer(int fl + ffi_type **atypes, + ffi_type *restype, + void *resmem, +- int argcount) ++ int argcount, ++ int argtypecount) + { + PyThreadState *_save = NULL; /* For Py_BLOCK_THREADS and Py_UNBLOCK_THREADS */ + PyObject *error_object = NULL; +@@ -835,14 +842,70 @@ static int _call_function_pointer(int fl + 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 USING_APPLE_OS_LIBFFI ++# define HAVE_FFI_PREP_CIF_VAR_RUNTIME __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *) ++# elif HAVE_FFI_PREP_CIF_VAR ++# define HAVE_FFI_PREP_CIF_VAR_RUNTIME true ++# else ++# define HAVE_FFI_PREP_CIF_VAR_RUNTIME false ++# endif ++ ++ /* Even on Apple-arm64 the calling convention for variadic functions conincides ++ * with the standard calling convention in the case that the function called ++ * only with its fixed arguments. Thus, we do not need a special flag to be ++ * set on variadic functions. We treat a function as variadic if it is called ++ * with a nonzero number of variadic arguments */ ++ bool is_variadic = (argtypecount != 0 && argcount > argtypecount); ++ (void) is_variadic; ++ ++#if defined(__APPLE__) && defined(__arm64__) ++ if (is_variadic) { ++ if (HAVE_FFI_PREP_CIF_VAR_RUNTIME) { ++ } else { ++ PyErr_SetString(PyExc_NotImplementedError, "ffi_prep_cif_var() is missing"); ++ return -1; ++ } ++ } ++#endif ++ ++#if HAVE_FFI_PREP_CIF_VAR ++ if (is_variadic) { ++ if (HAVE_FFI_PREP_CIF_VAR_RUNTIME) { ++ 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 { ++ if (FFI_OK != ffi_prep_cif(&cif, ++ cc, ++ argcount, ++ restype, ++ atypes)) { ++ PyErr_SetString(PyExc_RuntimeError, ++ "ffi_prep_cif 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 (flags & (FUNCFLAG_USE_ERRNO | FUNCFLAG_USE_LASTERROR)) { +@@ -1212,9 +1275,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 +@@ -1398,6 +1460,42 @@ copy_com_pointer(PyObject *self, PyObjec + } + #else + ++#ifdef HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH ++static PyObject *py_dyld_shared_cache_contains_path(PyObject *self, PyObject *args) ++{ ++ PyObject *name, *name2; ++ char *name_str; ++ ++ if (__builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)) { ++ int r; ++ ++ if (!PyArg_ParseTuple(args, "O", &name)) ++ return NULL; ++ ++ if (name == Py_None) ++ Py_RETURN_FALSE; ++ ++ if (PyUnicode_FSConverter(name, &name2) == 0) ++ return NULL; ++ name_str = PyBytes_AS_STRING(name2); ++ ++ r = _dyld_shared_cache_contains_path(name_str); ++ Py_DECREF(name2); ++ ++ if (r) { ++ Py_RETURN_TRUE; ++ } else { ++ Py_RETURN_FALSE; ++ } ++ ++ } else { ++ PyErr_SetString(PyExc_NotImplementedError, "_dyld_shared_cache_contains_path symbol is missing"); ++ return NULL; ++ } ++ ++ } ++#endif ++ + static PyObject *py_dl_open(PyObject *self, PyObject *args) + { + PyObject *name, *name2; +@@ -1887,6 +1985,8 @@ buffer_info(PyObject *self, PyObject *ar + return Py_BuildValue("siN", dict->format, dict->ndim, shape); + } + ++ ++ + PyMethodDef _ctypes_module_methods[] = { + {"get_errno", get_errno, METH_NOARGS}, + {"set_errno", set_errno, METH_VARARGS}, +@@ -1909,6 +2009,9 @@ PyMethodDef _ctypes_module_methods[] = { + {"dlclose", py_dl_close, METH_VARARGS, "dlclose a library"}, + {"dlsym", py_dl_sym, METH_VARARGS, "find symbol in shared library"}, + #endif ++#ifdef HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH ++ {"_dyld_shared_cache_contains_path", py_dyld_shared_cache_contains_path, METH_VARARGS, "check if path is in the shared cache"}, ++#endif + {"alignment", align_func, METH_O, alignment_doc}, + {"sizeof", sizeof_func, METH_O, sizeof_doc}, + {"byref", byref, METH_VARARGS, byref_doc}, diff --git a/lang/python39/patches/patch-Modules___ctypes_ctypes.h b/lang/python39/patches/patch-Modules___ctypes_ctypes.h new file mode 100644 index 00000000000..a8942b1530c --- /dev/null +++ b/lang/python39/patches/patch-Modules___ctypes_ctypes.h @@ -0,0 +1,22 @@ +$NetBSD: patch-Modules___ctypes_ctypes.h,v 1.1 2020/11/12 10:58:21 sjmulder Exp $ + +Support for macOS 11 and Apple Silicon (ARM). Backported from: +https://github.com/python/cpython/pull/22855 + +--- Modules/_ctypes/ctypes.h.orig 2020-10-05 15:07:58.000000000 +0000 ++++ Modules/_ctypes/ctypes.h +@@ -366,6 +366,14 @@ PyObject *_ctypes_get_errobj(int **pspac + extern PyObject *ComError; + #endif + ++#if USING_MALLOC_CLOSURE_DOT_C ++void Py_ffi_closure_free(void *p); ++void *Py_ffi_closure_alloc(size_t size, void** codeloc); ++#else ++#define Py_ffi_closure_free ffi_closure_free ++#define Py_ffi_closure_alloc ffi_closure_alloc ++#endif ++ + /* + Local Variables: + compile-command: "python setup.py -q build install --home ~" diff --git a/lang/python39/patches/patch-Modules___ctypes_malloc__closure.c b/lang/python39/patches/patch-Modules___ctypes_malloc__closure.c new file mode 100644 index 00000000000..7f973c8cefb --- /dev/null +++ b/lang/python39/patches/patch-Modules___ctypes_malloc__closure.c @@ -0,0 +1,37 @@ +$NetBSD: patch-Modules___ctypes_malloc__closure.c,v 1.1 2020/11/12 10:58:21 sjmulder Exp $ + +Support for macOS 11 and Apple Silicon (ARM). Backported from: +https://github.com/python/cpython/pull/22855 + +--- Modules/_ctypes/malloc_closure.c.orig 2020-10-05 15:07:58.000000000 +0000 ++++ Modules/_ctypes/malloc_closure.c +@@ -89,16 +89,27 @@ static void more_core(void) + /******************************************************************/ + + /* put the item back into the free list */ +-void ffi_closure_free(void *p) ++void Py_ffi_closure_free(void *p) + { ++#if USING_APPLE_OS_LIBFFI && HAVE_FFI_CLOSURE_ALLOC ++ if (__builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)) { ++ ffi_closure_free(p); ++ return; ++ } ++#endif + ITEM *item = (ITEM *)p; + item->next = free_list; + free_list = item; + } + + /* return one item from the free list, allocating more if needed */ +-void *ffi_closure_alloc(size_t ignored, void** codeloc) ++void *Py_ffi_closure_alloc(size_t size, void** codeloc) + { ++#if USING_APPLE_OS_LIBFFI && HAVE_FFI_CLOSURE_ALLOC ++ if (__builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)) { ++ return ffi_closure_alloc(size, codeloc); ++ } ++#endif + ITEM *item; + if (!free_list) + more_core(); diff --git a/lang/python39/patches/patch-Modules___decimal_libmpdec_mpdecimal.h b/lang/python39/patches/patch-Modules___decimal_libmpdec_mpdecimal.h new file mode 100644 index 00000000000..8571e2bf7c0 --- /dev/null +++ b/lang/python39/patches/patch-Modules___decimal_libmpdec_mpdecimal.h @@ -0,0 +1,16 @@ +$NetBSD: patch-Modules___decimal_libmpdec_mpdecimal.h,v 1.1 2020/11/12 10:58:21 sjmulder Exp $ + +Support for macOS 11 and Apple Silicon (ARM). (Original code.) + +--- Modules/_decimal/libmpdec/mpdecimal.h.orig 2020-11-11 21:56:51.000000000 +0000 ++++ Modules/_decimal/libmpdec/mpdecimal.h +@@ -121,6 +121,9 @@ const char *mpd_version(void); + #elif defined(__x86_64__) + #define CONFIG_64 + #define ASM ++ #elif defined(__aarch64__) ++ #define CONFIG_64 ++ #define ANSI + #else + #error "unknown architecture for universal build." + #endif diff --git a/lang/python39/patches/patch-Modules_getpath.c b/lang/python39/patches/patch-Modules_getpath.c new file mode 100644 index 00000000000..ee62a5e882b --- /dev/null +++ b/lang/python39/patches/patch-Modules_getpath.c @@ -0,0 +1,19 @@ +$NetBSD: patch-Modules_getpath.c,v 1.1 2020/11/12 10:58:21 sjmulder Exp $ + +Support for macOS 11 and Apple Silicon (ARM). Backported from: +https://github.com/python/cpython/pull/22855 + +--- Modules/getpath.c.orig 2020-10-05 15:07:58.000000000 +0000 ++++ Modules/getpath.c +@@ -923,11 +923,7 @@ static PyStatus + calculate_program_macos(wchar_t **abs_path_p) + { + char execpath[MAXPATHLEN + 1]; +-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 + uint32_t nsexeclength = Py_ARRAY_LENGTH(execpath) - 1; +-#else +- unsigned long nsexeclength = Py_ARRAY_LENGTH(execpath) - 1; +-#endif + + /* On Mac OS X, if a script uses an interpreter of the form + "#!/opt/python2.3/bin/python", the kernel only passes "python" diff --git a/lang/python39/patches/patch-Modules_posixmodule.c b/lang/python39/patches/patch-Modules_posixmodule.c new file mode 100644 index 00000000000..7a28f426c06 --- /dev/null +++ b/lang/python39/patches/patch-Modules_posixmodule.c @@ -0,0 +1,1365 @@ +$NetBSD: patch-Modules_posixmodule.c,v 1.1 2020/11/12 10:58:21 sjmulder Exp $ + +Support for macOS 11 and Apple Silicon (ARM). Backported from: +https://github.com/python/cpython/pull/22855 + +--- Modules/posixmodule.c.orig 2020-10-05 15:07:58.000000000 +0000 ++++ Modules/posixmodule.c +@@ -7,18 +7,6 @@ + of the compiler used. Different compilers define their own feature + test macro, e.g. '_MSC_VER'. */ + +-#ifdef __APPLE__ +- /* +- * Step 1 of support for weak-linking a number of symbols existing on +- * OSX 10.4 and later, see the comment in the #ifdef __APPLE__ block +- * at the end of this file for more information. +- */ +-# pragma weak lchown +-# pragma weak statvfs +-# pragma weak fstatvfs +- +-#endif /* __APPLE__ */ +- + #define PY_SSIZE_T_CLEAN + + #include "Python.h" +@@ -50,6 +38,127 @@ + + #include <stdio.h> /* needed for ctermid() */ + ++/* ++ * A number of APIs are available on macOS from a certain macOS version. ++ * To support building with a new SDK while deploying to older versions ++ * the availability test is split into two: ++ * - HAVE_<FUNCTION>: The configure check for compile time availability ++ * - HAVE_<FUNCTION>_RUNTIME: Runtime check for availability ++ * ++ * The latter is always true when not on macOS, or when using a compiler ++ * that does not support __has_builtin (older versions of Xcode). ++ * ++ * Due to compiler restrictions there is one valid use of HAVE_<FUNCTION>_RUNTIME: ++ * if (HAVE_<FUNCTION>_RUNTIME) { ... } ++ * ++ * In mixing the test with other tests or using negations will result in compile ++ * errors. ++ */ ++#if defined(__APPLE__) ++ ++#if defined(__has_builtin) && __has_builtin(__builtin_available) ++# define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) ++# define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) ++# define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) ++# define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) ++# define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) ++# define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) ++# define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) ++# define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) ++# define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) ++# define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) ++# define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) ++# define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) ++# define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *) ++# define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *) ++# define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *) ++ ++# define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *) ++ ++#else /* Xcode 8 or earlier */ ++ ++ /* __builtin_available is not present in these compilers, but ++ * some of the symbols might be weak linked (10.10 SDK or later ++ * deploying on 10.9. ++ * ++ * Fall back to the older style of availability checking for ++ * symbols introduced in macOS 10.10. ++ */ ++ ++# ifdef HAVE_FSTATAT ++# define HAVE_FSTATAT_RUNTIME (fstatat != NULL) ++# endif ++ ++# ifdef HAVE_FACCESSAT ++# define HAVE_FACCESSAT_RUNTIME (faccessat != NULL) ++# endif ++ ++# ifdef HAVE_FCHMODAT ++# define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL) ++# endif ++ ++# ifdef HAVE_FCHOWNAT ++# define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL) ++# endif ++ ++# ifdef HAVE_LINKAT ++# define HAVE_LINKAT_RUNTIME (linkat != NULL) ++# endif ++ ++# ifdef HAVE_FDOPENDIR ++# define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL) ++# endif ++ ++# ifdef HAVE_MKDIRAT ++# define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL) ++# endif ++ ++# ifdef HAVE_RENAMEAT ++# define HAVE_RENAMEAT_RUNTIME (renameat != NULL) ++# endif ++ ++# ifdef HAVE_UNLINKAT ++# define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL) ++# endif ++ ++# ifdef HAVE_OPENAT ++# define HAVE_OPENAT_RUNTIME (openat != NULL) ++# endif ++ ++# ifdef HAVE_READLINKAT ++# define HAVE_READLINKAT_RUNTIME (readlinkat != NULL) ++# endif ++ ++# ifdef HAVE_SYMLINKAT ++# define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL) ++# endif ++ ++#endif ++ ++#ifdef HAVE_FUTIMESAT ++/* Some of the logic for weak linking depends on this assertion */ ++# error "HAVE_FUTIMESAT unexpectedly defined" ++#endif ++ ++#else ++# define HAVE_FSTATAT_RUNTIME 1 ++# define HAVE_FACCESSAT_RUNTIME 1 ++# define HAVE_FCHMODAT_RUNTIME 1 ++# define HAVE_FCHOWNAT_RUNTIME 1 ++# define HAVE_LINKAT_RUNTIME 1 ++# define HAVE_FDOPENDIR_RUNTIME 1 ++# define HAVE_MKDIRAT_RUNTIME 1 ++# define HAVE_RENAMEAT_RUNTIME 1 ++# define HAVE_UNLINKAT_RUNTIME 1 ++# define HAVE_OPENAT_RUNTIME 1 ++# define HAVE_READLINKAT_RUNTIME 1 ++# define HAVE_SYMLINKAT_RUNTIME 1 ++# define HAVE_FUTIMENS_RUNTIME 1 ++# define HAVE_UTIMENSAT_RUNTIME 1 ++# define HAVE_PWRITEV_RUNTIME 1 ++#endif ++ ++ + #ifdef __cplusplus + extern "C" { + #endif +@@ -2308,6 +2417,10 @@ posix_do_stat(PyObject *module, const ch + STRUCT_STAT st; + int result; + ++#ifdef HAVE_FSTATAT ++ int fstatat_unavailable = 0; ++#endif ++ + #if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT) + if (follow_symlinks_specified(function_name, follow_symlinks)) + return NULL; +@@ -2334,15 +2447,27 @@ posix_do_stat(PyObject *module, const ch + else + #endif /* HAVE_LSTAT */ + #ifdef HAVE_FSTATAT +- if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) +- result = fstatat(dir_fd, path->narrow, &st, ++ if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) { ++ if (HAVE_FSTATAT_RUNTIME) { ++ result = fstatat(dir_fd, path->narrow, &st, + follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); +- else ++ ++ } else { ++ fstatat_unavailable = 1; ++ } ++ } else + #endif /* HAVE_FSTATAT */ + result = STAT(path->narrow, &st); + #endif /* MS_WINDOWS */ + Py_END_ALLOW_THREADS + ++#ifdef HAVE_FSTATAT ++ if (fstatat_unavailable) { ++ argument_unavailable_error("stat", "dir_fd"); ++ return NULL; ++ } ++#endif ++ + if (result != 0) { + return path_error(path); + } +@@ -2760,6 +2885,10 @@ os_access_impl(PyObject *module, path_t + int result; + #endif + ++#ifdef HAVE_FACCESSAT ++ int faccessat_unavailable = 0; ++#endif ++ + #ifndef HAVE_FACCESSAT + if (follow_symlinks_specified("access", follow_symlinks)) + return -1; +@@ -2794,17 +2923,40 @@ os_access_impl(PyObject *module, path_t + if ((dir_fd != DEFAULT_DIR_FD) || + effective_ids || + !follow_symlinks) { +- int flags = 0; +- if (!follow_symlinks) +- flags |= AT_SYMLINK_NOFOLLOW; +- if (effective_ids) +- flags |= AT_EACCESS; +- result = faccessat(dir_fd, path->narrow, mode, flags); ++ ++ if (HAVE_FACCESSAT_RUNTIME) { ++ int flags = 0; ++ if (!follow_symlinks) ++ flags |= AT_SYMLINK_NOFOLLOW; ++ if (effective_ids) ++ flags |= AT_EACCESS; ++ result = faccessat(dir_fd, path->narrow, mode, flags); ++ } else { ++ faccessat_unavailable = 1; ++ } + } + else + #endif + result = access(path->narrow, mode); + Py_END_ALLOW_THREADS ++ ++#ifdef HAVE_FACCESSAT ++ if (faccessat_unavailable) { ++ if (dir_fd != DEFAULT_DIR_FD) { ++ argument_unavailable_error("access", "dir_fd"); ++ return -1; ++ } ++ if (follow_symlinks_specified("access", follow_symlinks)) ++ return -1; ++ ++ if (effective_ids) { ++ argument_unavailable_error("access", "effective_ids"); ++ return -1; ++ } ++ /* should be unreachable */ ++ return -1; ++ } ++#endif + return_value = !result; + #endif + +@@ -3002,6 +3154,7 @@ os_chmod_impl(PyObject *module, path_t * + + #ifdef HAVE_FCHMODAT + int fchmodat_nofollow_unsupported = 0; ++ int fchmodat_unsupported = 0; + #endif + + #if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD)) +@@ -3037,42 +3190,56 @@ os_chmod_impl(PyObject *module, path_t * + if (path->fd != -1) + result = fchmod(path->fd, mode); + else +-#endif ++#endif /* HAVE_CHMOD */ + #ifdef HAVE_LCHMOD + if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) + result = lchmod(path->narrow, mode); + else +-#endif ++#endif /* HAVE_LCHMOD */ + #ifdef HAVE_FCHMODAT + if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) { +- /* +- * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW! +- * The documentation specifically shows how to use it, +- * and then says it isn't implemented yet. +- * (true on linux with glibc 2.15, and openindiana 3.x) +- * +- * Once it is supported, os.chmod will automatically +- * support dir_fd and follow_symlinks=False. (Hopefully.) +- * Until then, we need to be careful what exception we raise. +- */ +- result = fchmodat(dir_fd, path->narrow, mode, +- follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); +- /* +- * But wait! We can't throw the exception without allowing threads, +- * and we can't do that in this nested scope. (Macro trickery, sigh.) +- */ +- fchmodat_nofollow_unsupported = +- result && +- ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) && +- !follow_symlinks; ++ if (HAVE_FCHMODAT_RUNTIME) { ++ /* ++ * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW! ++ * The documentation specifically shows how to use it, ++ * and then says it isn't implemented yet. ++ * (true on linux with glibc 2.15, and openindiana 3.x) ++ * ++ * Once it is supported, os.chmod will automatically ++ * support dir_fd and follow_symlinks=False. (Hopefully.) ++ * Until then, we need to be careful what exception we raise. ++ */ ++ result = fchmodat(dir_fd, path->narrow, mode, ++ follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); ++ /* ++ * But wait! We can't throw the exception without allowing threads, ++ * and we can't do that in this nested scope. (Macro trickery, sigh.) ++ */ ++ fchmodat_nofollow_unsupported = ++ result && ++ ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) && ++ !follow_symlinks; ++ } else { ++ fchmodat_unsupported = 1; ++ fchmodat_nofollow_unsupported = 1; ++ ++ result = -1; ++ } + } + else +-#endif ++#endif /* HAVE_FHCMODAT */ + result = chmod(path->narrow, mode); + Py_END_ALLOW_THREADS + + if (result) { + #ifdef HAVE_FCHMODAT ++ if (fchmodat_unsupported) { ++ if (dir_fd != DEFAULT_DIR_FD) { ++ argument_unavailable_error("chmod", "dir_fd"); ++ return NULL; ++ } ++ } ++ + if (fchmodat_nofollow_unsupported) { + if (dir_fd != DEFAULT_DIR_FD) + dir_fd_and_follow_symlinks_invalid("chmod", +@@ -3082,10 +3249,10 @@ os_chmod_impl(PyObject *module, path_t * + return NULL; + } + else +-#endif ++#endif /* HAVE_FCHMODAT */ + return path_error(path); + } +-#endif ++#endif /* MS_WINDOWS */ + + Py_RETURN_NONE; + } +@@ -3373,6 +3540,10 @@ os_chown_impl(PyObject *module, path_t * + { + int result; + ++#if defined(HAVE_FCHOWNAT) ++ int fchownat_unsupported = 0; ++#endif ++ + #if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT)) + if (follow_symlinks_specified("chown", follow_symlinks)) + return NULL; +@@ -3381,19 +3552,6 @@ os_chown_impl(PyObject *module, path_t * + fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks)) + return NULL; + +-#ifdef __APPLE__ +- /* +- * This is for Mac OS X 10.3, which doesn't have lchown. +- * (But we still have an lchown symbol because of weak-linking.) +- * It doesn't have fchownat either. So there's no possibility +- * of a graceful failover. +- */ +- if ((!follow_symlinks) && (lchown == NULL)) { +- follow_symlinks_specified("chown", follow_symlinks); +- return NULL; +- } +-#endif +- + if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, + dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { + return NULL; +@@ -3411,14 +3569,28 @@ os_chown_impl(PyObject *module, path_t * + else + #endif + #ifdef HAVE_FCHOWNAT +- if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) ++ if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) { ++ if (HAVE_FCHOWNAT_RUNTIME) { + result = fchownat(dir_fd, path->narrow, uid, gid, + follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); +- else ++ } else { ++ fchownat_unsupported = 1; ++ } ++ } else + #endif + result = chown(path->narrow, uid, gid); + Py_END_ALLOW_THREADS + ++#ifdef HAVE_FCHOWNAT ++ if (fchownat_unsupported) { ++ /* This would be incorrect if the current platform ++ * doesn't support lchown. ++ */ ++ argument_unavailable_error(NULL, "dir_fd"); ++ return NULL; ++ } ++#endif ++ + if (result) + return path_error(path); + +@@ -3664,6 +3836,9 @@ os_link_impl(PyObject *module, path_t *s + #else + int result; + #endif ++#if defined(HAVE_LINKAT) ++ int linkat_unavailable = 0; ++#endif + + #ifndef HAVE_LINKAT + if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) { +@@ -3698,15 +3873,43 @@ os_link_impl(PyObject *module, path_t *s + #ifdef HAVE_LINKAT + if ((src_dir_fd != DEFAULT_DIR_FD) || + (dst_dir_fd != DEFAULT_DIR_FD) || +- (!follow_symlinks)) +- result = linkat(src_dir_fd, src->narrow, +- dst_dir_fd, dst->narrow, +- follow_symlinks ? AT_SYMLINK_FOLLOW : 0); ++ (!follow_symlinks)) { ++ ++ if (HAVE_LINKAT_RUNTIME) { ++ ++ result = linkat(src_dir_fd, src->narrow, ++ dst_dir_fd, dst->narrow, ++ follow_symlinks ? AT_SYMLINK_FOLLOW : 0); ++ ++ } ++#ifdef __APPLE__ ++ else { ++ if (src_dir_fd == DEFAULT_DIR_FD && dst_dir_fd == DEFAULT_DIR_FD) { ++ /* See issue 41355: This matches the behaviour of !HAVE_LINKAT */ ++ result = link(src->narrow, dst->narrow); ++ } else { ++ linkat_unavailable = 1; ++ } ++ } ++#endif ++ } + else + #endif /* HAVE_LINKAT */ + result = link(src->narrow, dst->narrow); + Py_END_ALLOW_THREADS + ++#ifdef HAVE_LINKAT ++ if (linkat_unavailable) { ++ /* Either or both dir_fd arguments were specified */ ++ if (src_dir_fd != DEFAULT_DIR_FD) { ++ argument_unavailable_error("link", "src_dir_fd"); ++ } else { ++ argument_unavailable_error("link", "dst_dir_fd"); ++ } ++ return NULL; ++ } ++#endif ++ + if (result) + return path_error2(src, dst); + #endif /* MS_WINDOWS */ +@@ -3829,6 +4032,7 @@ _posix_listdir(path_t *path, PyObject *l + errno = 0; + #ifdef HAVE_FDOPENDIR + if (path->fd != -1) { ++ if (HAVE_FDOPENDIR_RUNTIME) { + /* closedir() closes the FD, so we duplicate it */ + fd = _Py_dup(path->fd); + if (fd == -1) +@@ -3839,6 +4043,11 @@ _posix_listdir(path_t *path, PyObject *l + Py_BEGIN_ALLOW_THREADS + dirp = fdopendir(fd); + Py_END_ALLOW_THREADS ++ } else { ++ PyErr_SetString(PyExc_TypeError, ++ "listdir: path should be string, bytes, os.PathLike or None, not int"); ++ return NULL; ++ } + } + else + #endif +@@ -4152,6 +4361,9 @@ os_mkdir_impl(PyObject *module, path_t * + /*[clinic end generated code: output=a70446903abe821f input=e965f68377e9b1ce]*/ + { + int result; ++#ifdef HAVE_MKDIRAT ++ int mkdirat_unavailable = 0; ++#endif + + if (PySys_Audit("os.mkdir", "Oii", path->object, mode, + dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { +@@ -4168,9 +4380,14 @@ os_mkdir_impl(PyObject *module, path_t * + #else + Py_BEGIN_ALLOW_THREADS + #if HAVE_MKDIRAT +- if (dir_fd != DEFAULT_DIR_FD) ++ if (dir_fd != DEFAULT_DIR_FD) { ++ if (HAVE_MKDIRAT_RUNTIME) { + result = mkdirat(dir_fd, path->narrow, mode); +- else ++ ++ } else { ++ mkdirat_unavailable = 1; ++ } ++ } else + #endif + #if defined(__WATCOMC__) && !defined(__QNX__) + result = mkdir(path->narrow); +@@ -4178,6 +4395,14 @@ os_mkdir_impl(PyObject *module, path_t * + result = mkdir(path->narrow, mode); + #endif + Py_END_ALLOW_THREADS ++ ++#if HAVE_MKDIRAT ++ if (mkdirat_unavailable) { ++ argument_unavailable_error(NULL, "dir_fd"); ++ return NULL; ++ } ++#endif ++ + if (result < 0) + return path_error(path); + #endif /* MS_WINDOWS */ +@@ -4287,6 +4512,10 @@ internal_rename(path_t *src, path_t *dst + const char *function_name = is_replace ? "replace" : "rename"; + int dir_fd_specified; + ++#ifdef HAVE_RENAMEAT ++ int renameat_unavailable = 0; ++#endif ++ + #ifdef MS_WINDOWS + BOOL result; + int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0; +@@ -4326,13 +4555,25 @@ internal_rename(path_t *src, path_t *dst + + Py_BEGIN_ALLOW_THREADS + #ifdef HAVE_RENAMEAT +- if (dir_fd_specified) +- result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow); +- else ++ if (dir_fd_specified) { ++ if (HAVE_RENAMEAT_RUNTIME) { ++ result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow); ++ } else { ++ renameat_unavailable = 1; ++ } ++ } else + #endif + result = rename(src->narrow, dst->narrow); + Py_END_ALLOW_THREADS + ++ ++#ifdef HAVE_RENAMEAT ++ if (renameat_unavailable) { ++ argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd"); ++ return NULL; ++ } ++#endif ++ + if (result) + return path_error2(src, dst); + #endif +@@ -4408,6 +4649,9 @@ os_rmdir_impl(PyObject *module, path_t * + /*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/ + { + int result; ++#ifdef HAVE_UNLINKAT ++ int unlinkat_unavailable = 0; ++#endif + + if (PySys_Audit("os.rmdir", "Oi", path->object, + dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { +@@ -4420,14 +4664,26 @@ os_rmdir_impl(PyObject *module, path_t * + result = !RemoveDirectoryW(path->wide); + #else + #ifdef HAVE_UNLINKAT +- if (dir_fd != DEFAULT_DIR_FD) ++ if (dir_fd != DEFAULT_DIR_FD) { ++ if (HAVE_UNLINKAT_RUNTIME) { + result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR); +- else ++ } else { ++ unlinkat_unavailable = 1; ++ result = -1; ++ } ++ } else + #endif + result = rmdir(path->narrow); + #endif + Py_END_ALLOW_THREADS + ++#ifdef HAVE_UNLINKAT ++ if (unlinkat_unavailable) { ++ argument_unavailable_error("rmdir", "dir_fd"); ++ return NULL; ++ } ++#endif ++ + if (result) + return path_error(path); + +@@ -4571,6 +4827,9 @@ os_unlink_impl(PyObject *module, path_t + /*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/ + { + int result; ++#ifdef HAVE_UNLINKAT ++ int unlinkat_unavailable = 0; ++#endif + + if (PySys_Audit("os.remove", "Oi", path->object, + dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { +@@ -4584,15 +4843,27 @@ os_unlink_impl(PyObject *module, path_t + result = !Py_DeleteFileW(path->wide); + #else + #ifdef HAVE_UNLINKAT +- if (dir_fd != DEFAULT_DIR_FD) ++ if (dir_fd != DEFAULT_DIR_FD) { ++ if (HAVE_UNLINKAT_RUNTIME) { ++ + result = unlinkat(dir_fd, path->narrow, 0); +- else ++ } else { ++ unlinkat_unavailable = 1; ++ } ++ } else + #endif /* HAVE_UNLINKAT */ + result = unlink(path->narrow); + #endif + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + ++#ifdef HAVE_UNLINKAT ++ if (unlinkat_unavailable) { ++ argument_unavailable_error(NULL, "dir_fd"); ++ return NULL; ++ } ++#endif ++ + if (result) + return path_error(path); + +@@ -4763,7 +5034,16 @@ typedef struct { + static int + utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks) + { +-#ifdef HAVE_UTIMENSAT ++#if defined(__APPLE__) && defined(HAVE_UTIMENSAT) ++ if (HAVE_UTIMENSAT_RUNTIME) { ++ int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW; ++ UTIME_TO_TIMESPEC; ++ return utimensat(dir_fd, path, time, flags); ++ } else { ++ errno = ENOSYS; ++ return -1; ++ } ++#elif defined(HAVE_UTIMENSAT) + int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW; + UTIME_TO_TIMESPEC; + return utimensat(dir_fd, path, time, flags); +@@ -4790,11 +5070,30 @@ static int + utime_fd(utime_t *ut, int fd) + { + #ifdef HAVE_FUTIMENS ++ ++ if (HAVE_FUTIMENS_RUNTIME) { ++ + UTIME_TO_TIMESPEC; + return futimens(fd, time); +-#else ++ ++ } else ++#ifndef HAVE_FUTIMES ++ { ++ /* Not sure if this can happen */ ++ PyErr_SetString( ++ PyExc_RuntimeError, ++ "neither futimens nor futimes are supported" ++ " on this system"); ++ return -1; ++ } ++#endif ++ ++#endif ++#ifdef HAVE_FUTIMES ++ { + UTIME_TO_TIMEVAL; + return futimes(fd, time); ++ } + #endif + } + +@@ -4813,11 +5112,27 @@ static int + utime_nofollow_symlinks(utime_t *ut, const char *path) + { + #ifdef HAVE_UTIMENSAT +- UTIME_TO_TIMESPEC; +- return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW); +-#else ++ if (HAVE_UTIMENSAT_RUNTIME) { ++ UTIME_TO_TIMESPEC; ++ return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW); ++ } else ++#ifndef HAVE_LUTIMES ++ { ++ /* Not sure if this can happen */ ++ PyErr_SetString( ++ PyExc_RuntimeError, ++ "neither utimensat nor lutimes are supported" ++ " on this system"); ++ return -1; ++ } ++#endif ++#endif ++ ++#ifdef HAVE_LUTIMES ++ { + UTIME_TO_TIMEVAL; + return lutimes(path, time); ++ } + #endif + } + +@@ -4828,7 +5143,15 @@ utime_nofollow_symlinks(utime_t *ut, con + static int + utime_default(utime_t *ut, const char *path) + { +-#ifdef HAVE_UTIMENSAT ++#if defined(__APPLE__) && defined(HAVE_UTIMENSAT) ++ if (HAVE_UTIMENSAT_RUNTIME) { ++ UTIME_TO_TIMESPEC; ++ return utimensat(DEFAULT_DIR_FD, path, time, 0); ++ } else { ++ UTIME_TO_TIMEVAL; ++ return utimes(path, time); ++ } ++#elif defined(HAVE_UTIMENSAT) + UTIME_TO_TIMESPEC; + return utimensat(DEFAULT_DIR_FD, path, time, 0); + #elif defined(HAVE_UTIMES) +@@ -5037,9 +5360,10 @@ os_utime_impl(PyObject *module, path_t * + #endif + + #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT) +- if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) ++ if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) { + result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks); +- else ++ ++ } else + #endif + + #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS) +@@ -5052,6 +5376,14 @@ os_utime_impl(PyObject *module, path_t * + + Py_END_ALLOW_THREADS + ++#if defined(__APPLE__) && defined(HAVE_UTIMENSAT) ++ /* See utime_dir_fd implementation */ ++ if (result == -1 && errno == ENOSYS) { ++ argument_unavailable_error(NULL, "dir_fd"); ++ return NULL; ++ } ++#endif ++ + if (result < 0) { + /* see previous comment about not putting filename in error here */ + posix_error(); +@@ -5450,6 +5782,9 @@ parse_posix_spawn_flags(PyObject *module + } + + if (setsid) { ++#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME ++ if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) { ++#endif + #ifdef POSIX_SPAWN_SETSID + all_flags |= POSIX_SPAWN_SETSID; + #elif defined(POSIX_SPAWN_SETSID_NP) +@@ -5458,6 +5793,14 @@ parse_posix_spawn_flags(PyObject *module + argument_unavailable_error(func_name, "setsid"); + return -1; + #endif ++ ++#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME ++ } else { ++ argument_unavailable_error(func_name, "setsid"); ++ return -1; ++ } ++#endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */ ++ + } + + if (setsigmask) { +@@ -8068,16 +8411,30 @@ os_readlink_impl(PyObject *module, path_ + #if defined(HAVE_READLINK) + char buffer[MAXPATHLEN+1]; + ssize_t length; ++#ifdef HAVE_READLINKAT ++ int readlinkat_unavailable = 0; ++#endif + + Py_BEGIN_ALLOW_THREADS + #ifdef HAVE_READLINKAT +- if (dir_fd != DEFAULT_DIR_FD) +- length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN); +- else ++ if (dir_fd != DEFAULT_DIR_FD) { ++ if (HAVE_READLINKAT_RUNTIME) { ++ length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN); ++ } else { ++ readlinkat_unavailable = 1; ++ } ++ } else + #endif + length = readlink(path->narrow, buffer, MAXPATHLEN); + Py_END_ALLOW_THREADS + ++#ifdef HAVE_READLINKAT ++ if (readlinkat_unavailable) { ++ argument_unavailable_error(NULL, "dir_fd"); ++ return NULL; ++ } ++#endif ++ + if (length < 0) { + return path_error(path); + } +@@ -8273,6 +8630,9 @@ os_symlink_impl(PyObject *module, path_t + static int windows_has_symlink_unprivileged_flag = TRUE; + #else + int result; ++#ifdef HAVE_SYMLINKAT ++ int symlinkat_unavailable = 0; ++#endif + #endif + + if (PySys_Audit("os.symlink", "OOi", src->object, dst->object, +@@ -8335,14 +8695,25 @@ os_symlink_impl(PyObject *module, path_t + } + + Py_BEGIN_ALLOW_THREADS +-#if HAVE_SYMLINKAT +- if (dir_fd != DEFAULT_DIR_FD) +- result = symlinkat(src->narrow, dir_fd, dst->narrow); +- else ++#ifdef HAVE_SYMLINKAT ++ if (dir_fd != DEFAULT_DIR_FD) { ++ if (HAVE_SYMLINKAT_RUNTIME) { ++ result = symlinkat(src->narrow, dir_fd, dst->narrow); ++ } else { ++ symlinkat_unavailable = 1; ++ } ++ } else + #endif + result = symlink(src->narrow, dst->narrow); + Py_END_ALLOW_THREADS + ++#ifdef HAVE_SYMLINKAT ++ if (symlinkat_unavailable) { ++ argument_unavailable_error(NULL, "dir_fd"); ++ return NULL; ++ } ++#endif ++ + if (result) + return path_error2(src, dst); + #endif +@@ -8613,6 +8984,9 @@ os_open_impl(PyObject *module, path_t *p + { + int fd; + int async_err = 0; ++#ifdef HAVE_OPENAT ++ int openat_unavailable = 0; ++#endif + + #ifdef O_CLOEXEC + int *atomic_flag_works = &_Py_open_cloexec_works; +@@ -8637,9 +9011,15 @@ os_open_impl(PyObject *module, path_t *p + fd = _wopen(path->wide, flags, mode); + #else + #ifdef HAVE_OPENAT +- if (dir_fd != DEFAULT_DIR_FD) +- fd = openat(dir_fd, path->narrow, flags, mode); +- else ++ if (dir_fd != DEFAULT_DIR_FD) { ++ if (HAVE_OPENAT_RUNTIME) { ++ fd = openat(dir_fd, path->narrow, flags, mode); ++ ++ } else { ++ openat_unavailable = 1; ++ fd = -1; ++ } ++ } else + #endif /* HAVE_OPENAT */ + fd = open(path->narrow, flags, mode); + #endif /* !MS_WINDOWS */ +@@ -8647,6 +9027,13 @@ os_open_impl(PyObject *module, path_t *p + } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + _Py_END_SUPPRESS_IPH + ++#ifdef HAVE_OPENAT ++ if (openat_unavailable) { ++ argument_unavailable_error(NULL, "dir_fd"); ++ return -1; ++ } ++#endif ++ + if (fd < 0) { + if (!async_err) + PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object); +@@ -9229,12 +9616,25 @@ os_preadv_impl(PyObject *module, int fd, + } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + #else + do { ++#ifdef __APPLE__ ++/* This entire function will be removed from the module dict when the API ++ * is not available. ++ */ ++#pragma clang diagnostic push ++#pragma clang diagnostic ignored "-Wunguarded-availability" ++#pragma clang diagnostic ignored "-Wunguarded-availability-new" ++#endif + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + n = preadv(fd, iov, cnt, offset); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); ++ ++#ifdef __APPLE__ ++#pragma clang diagnostic pop ++#endif ++ + #endif + + iov_cleanup(iov, buf, cnt); +@@ -9841,6 +10241,15 @@ os_pwritev_impl(PyObject *module, int fd + Py_END_ALLOW_THREADS + } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + #else ++ ++#ifdef __APPLE__ ++/* This entire function will be removed from the module dict when the API ++ * is not available. ++ */ ++#pragma clang diagnostic push ++#pragma clang diagnostic ignored "-Wunguarded-availability" ++#pragma clang diagnostic ignored "-Wunguarded-availability-new" ++#endif + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH +@@ -9848,6 +10257,11 @@ os_pwritev_impl(PyObject *module, int fd + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); ++ ++#ifdef __APPLE__ ++#pragma clang diagnostic pop ++#endif ++ + #endif + + iov_cleanup(iov, buf, cnt); +@@ -10737,13 +11151,6 @@ os_statvfs_impl(PyObject *module, path_t + Py_BEGIN_ALLOW_THREADS + #ifdef HAVE_FSTATVFS + if (path->fd != -1) { +-#ifdef __APPLE__ +- /* handle weak-linking on Mac OS X 10.3 */ +- if (fstatvfs == NULL) { +- fd_specified("statvfs", path->fd); +- return NULL; +- } +-#endif + result = fstatvfs(path->fd, &st); + } + else +@@ -12817,12 +13224,16 @@ DirEntry_fetch_stat(PyObject *module, Di + const char *path = PyBytes_AS_STRING(ub); + if (self->dir_fd != DEFAULT_DIR_FD) { + #ifdef HAVE_FSTATAT ++ if (HAVE_FSTATAT_RUNTIME) { + result = fstatat(self->dir_fd, path, &st, + follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); +-#else ++ } else ++#endif /* HAVE_FSTATAT */ ++ { ++ Py_DECREF(ub); + PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat"); + return NULL; +-#endif /* HAVE_FSTATAT */ ++ } + } + else + #endif +@@ -13609,6 +14020,7 @@ os_scandir_impl(PyObject *module, path_t + errno = 0; + #ifdef HAVE_FDOPENDIR + if (path->fd != -1) { ++ if (HAVE_FDOPENDIR_RUNTIME) { + /* closedir() closes the FD, so we duplicate it */ + fd = _Py_dup(path->fd); + if (fd == -1) +@@ -13617,6 +14029,11 @@ os_scandir_impl(PyObject *module, path_t + Py_BEGIN_ALLOW_THREADS + iterator->dirp = fdopendir(fd); + Py_END_ALLOW_THREADS ++ } else { ++ PyErr_SetString(PyExc_TypeError, ++ "scandir: path should be string, bytes, os.PathLike or None, not int"); ++ return NULL; ++ } + } + else + #endif +@@ -14687,137 +15104,210 @@ all_ins(PyObject *m) + } + + +-static const char * const have_functions[] = { ++ ++#define PROBE(name, test) \ ++ static int name(void) \ ++ { \ ++ if (test) { \ ++ return 1; \ ++ } else { \ ++ return 0; \ ++ } \ ++ } ++ ++#ifdef HAVE_FSTATAT ++PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME) ++#endif + + #ifdef HAVE_FACCESSAT +- "HAVE_FACCESSAT", ++PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME) ++#endif ++ ++#ifdef HAVE_FCHMODAT ++PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME) ++#endif ++ ++#ifdef HAVE_FCHOWNAT ++PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME) ++#endif ++ ++#ifdef HAVE_LINKAT ++PROBE(probe_linkat, HAVE_LINKAT_RUNTIME) ++#endif ++ ++#ifdef HAVE_FDOPENDIR ++PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME) ++#endif ++ ++#ifdef HAVE_MKDIRAT ++PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME) ++#endif ++ ++#ifdef HAVE_RENAMEAT ++PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME) ++#endif ++ ++#ifdef HAVE_UNLINKAT ++PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME) ++#endif ++ ++#ifdef HAVE_OPENAT ++PROBE(probe_openat, HAVE_OPENAT_RUNTIME) ++#endif ++ ++#ifdef HAVE_READLINKAT ++PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME) ++#endif ++ ++#ifdef HAVE_SYMLINKAT ++PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME) ++#endif ++ ++#ifdef HAVE_FUTIMENS ++PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME) ++#endif ++ ++#ifdef HAVE_UTIMENSAT ++PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME) ++#endif ++ ++ ++ ++ ++static const struct have_function { ++ const char * const label; ++ int (*probe)(void); ++} have_functions[] = { ++ ++#ifdef HAVE_FACCESSAT ++ { "HAVE_FACCESSAT", probe_faccessat }, + #endif + + #ifdef HAVE_FCHDIR +- "HAVE_FCHDIR", ++ { "HAVE_FCHDIR", NULL }, + #endif + + #ifdef HAVE_FCHMOD +- "HAVE_FCHMOD", ++ { "HAVE_FCHMOD", NULL }, + #endif + + #ifdef HAVE_FCHMODAT +- "HAVE_FCHMODAT", ++ { "HAVE_FCHMODAT", probe_fchmodat }, + #endif + + #ifdef HAVE_FCHOWN +- "HAVE_FCHOWN", ++ { "HAVE_FCHOWN", NULL }, + #endif + + #ifdef HAVE_FCHOWNAT +- "HAVE_FCHOWNAT", ++ { "HAVE_FCHOWNAT", probe_fchownat }, + #endif + + #ifdef HAVE_FEXECVE +- "HAVE_FEXECVE", ++ { "HAVE_FEXECVE", NULL }, + #endif + + #ifdef HAVE_FDOPENDIR +- "HAVE_FDOPENDIR", ++ { "HAVE_FDOPENDIR", probe_fdopendir }, + #endif + + #ifdef HAVE_FPATHCONF +- "HAVE_FPATHCONF", ++ { "HAVE_FPATHCONF", NULL }, + #endif + + #ifdef HAVE_FSTATAT +- "HAVE_FSTATAT", ++ { "HAVE_FSTATAT", probe_fstatat }, + #endif + + #ifdef HAVE_FSTATVFS +- "HAVE_FSTATVFS", ++ { "HAVE_FSTATVFS", NULL }, + #endif + + #if defined HAVE_FTRUNCATE || defined MS_WINDOWS +- "HAVE_FTRUNCATE", ++ { "HAVE_FTRUNCATE", NULL }, + #endif + + #ifdef HAVE_FUTIMENS +- "HAVE_FUTIMENS", ++ { "HAVE_FUTIMENS", probe_futimens }, + #endif + + #ifdef HAVE_FUTIMES +- "HAVE_FUTIMES", ++ { "HAVE_FUTIMES", NULL }, + #endif + + #ifdef HAVE_FUTIMESAT +- "HAVE_FUTIMESAT", ++ { "HAVE_FUTIMESAT", NULL }, + #endif + + #ifdef HAVE_LINKAT +- "HAVE_LINKAT", ++ { "HAVE_LINKAT", probe_linkat }, + #endif + + #ifdef HAVE_LCHFLAGS +- "HAVE_LCHFLAGS", ++ { "HAVE_LCHFLAGS", NULL }, + #endif + + #ifdef HAVE_LCHMOD +- "HAVE_LCHMOD", ++ { "HAVE_LCHMOD", NULL }, + #endif + + #ifdef HAVE_LCHOWN +- "HAVE_LCHOWN", ++ { "HAVE_LCHOWN", NULL }, + #endif + + #ifdef HAVE_LSTAT +- "HAVE_LSTAT", ++ { "HAVE_LSTAT", NULL }, + #endif + + #ifdef HAVE_LUTIMES +- "HAVE_LUTIMES", ++ { "HAVE_LUTIMES", NULL }, + #endif + + #ifdef HAVE_MEMFD_CREATE +- "HAVE_MEMFD_CREATE", ++ { "HAVE_MEMFD_CREATE", NULL }, + #endif + + #ifdef HAVE_MKDIRAT +- "HAVE_MKDIRAT", ++ { "HAVE_MKDIRAT", probe_mkdirat }, + #endif + + #ifdef HAVE_MKFIFOAT +- "HAVE_MKFIFOAT", ++ { "HAVE_MKFIFOAT", NULL }, + #endif + + #ifdef HAVE_MKNODAT +- "HAVE_MKNODAT", ++ { "HAVE_MKNODAT", NULL }, + #endif + + #ifdef HAVE_OPENAT +- "HAVE_OPENAT", ++ { "HAVE_OPENAT", probe_openat }, + #endif + + #ifdef HAVE_READLINKAT +- "HAVE_READLINKAT", ++ { "HAVE_READLINKAT", probe_readlinkat }, + #endif + + #ifdef HAVE_RENAMEAT +- "HAVE_RENAMEAT", ++ { "HAVE_RENAMEAT", probe_renameat }, + #endif + + #ifdef HAVE_SYMLINKAT +- "HAVE_SYMLINKAT", ++ { "HAVE_SYMLINKAT", probe_symlinkat }, + #endif + + #ifdef HAVE_UNLINKAT +- "HAVE_UNLINKAT", ++ { "HAVE_UNLINKAT", probe_unlinkat }, + #endif + + #ifdef HAVE_UTIMENSAT +- "HAVE_UTIMENSAT", ++ { "HAVE_UTIMENSAT", probe_utimensat }, + #endif + + #ifdef MS_WINDOWS +- "MS_WINDOWS", ++ { "MS_WINDOWS", NULL }, + #endif + +- NULL ++ { NULL, NULL } + }; + + +@@ -14826,6 +15316,23 @@ posixmodule_exec(PyObject *m) + { + _posixstate *state = get_posix_state(m); + ++#if defined(HAVE_PWRITEV) ++ if (HAVE_PWRITEV_RUNTIME) {} else { ++ PyObject* dct = PyModule_GetDict(m); ++ ++ if (dct == NULL) { ++ return -1; ++ } ++ ++ if (PyDict_DelItemString(dct, "pwritev") == -1) { ++ PyErr_Clear(); ++ } ++ if (PyDict_DelItemString(dct, "preadv") == -1) { ++ PyErr_Clear(); ++ } ++ } ++#endif ++ + /* Initialize environ dictionary */ + PyObject *v = convertenviron(); + Py_XINCREF(v); +@@ -14938,44 +15445,6 @@ posixmodule_exec(PyObject *m) + PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType); + state->UnameResultType = (PyObject *)UnameResultType; + +-#ifdef __APPLE__ +- /* +- * Step 2 of weak-linking support on Mac OS X. +- * +- * The code below removes functions that are not available on the +- * currently active platform. +- * +- * This block allow one to use a python binary that was build on +- * OSX 10.4 on OSX 10.3, without losing access to new APIs on +- * OSX 10.4. +- */ +-#ifdef HAVE_FSTATVFS +- if (fstatvfs == NULL) { +- if (PyObject_DelAttrString(m, "fstatvfs") == -1) { +- return -1; +- } +- } +-#endif /* HAVE_FSTATVFS */ +- +-#ifdef HAVE_STATVFS +- if (statvfs == NULL) { +- if (PyObject_DelAttrString(m, "statvfs") == -1) { +- return -1; +- } +- } +-#endif /* HAVE_STATVFS */ +- +-# ifdef HAVE_LCHOWN +- if (lchown == NULL) { +- if (PyObject_DelAttrString(m, "lchown") == -1) { +- return -1; +- } +- } +-#endif /* HAVE_LCHOWN */ +- +- +-#endif /* __APPLE__ */ +- + if ((state->billion = PyLong_FromLong(1000000000)) == NULL) + return -1; + #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) +@@ -15005,14 +15474,17 @@ posixmodule_exec(PyObject *m) + if (!list) { + return -1; + } +- for (const char * const *trace = have_functions; *trace; trace++) { +- PyObject *unicode = PyUnicode_DecodeASCII(*trace, strlen(*trace), NULL); ++ for (const struct have_function *trace = have_functions; trace->label; trace++) { ++ PyObject *unicode; ++ if (trace->probe && !trace->probe()) continue; ++ unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL); + if (!unicode) + return -1; + if (PyList_Append(list, unicode)) + return -1; + Py_DECREF(unicode); + } ++ + PyModule_AddObject(m, "_have_functions", list); + + return 0; diff --git a/lang/python39/patches/patch-Modules_timemodule.c b/lang/python39/patches/patch-Modules_timemodule.c new file mode 100644 index 00000000000..e3b177a6094 --- /dev/null +++ b/lang/python39/patches/patch-Modules_timemodule.c @@ -0,0 +1,322 @@ +$NetBSD: patch-Modules_timemodule.c,v 1.1 2020/11/12 10:58:21 sjmulder Exp $ + +Support for macOS 11 and Apple Silicon (ARM). Backported from: +https://github.com/python/cpython/pull/22855 + +--- Modules/timemodule.c.orig 2020-10-05 15:07:58.000000000 +0000 ++++ Modules/timemodule.c +@@ -51,6 +51,15 @@ + #define _Py_tzname tzname + #endif + ++#if defined(__APPLE__ ) && defined(__has_builtin) ++# if __has_builtin(__builtin_available) ++# define HAVE_CLOCK_GETTIME_RUNTIME __builtin_available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) ++# endif ++#endif ++#ifndef HAVE_CLOCK_GETTIME_RUNTIME ++# define HAVE_CLOCK_GETTIME_RUNTIME 1 ++#endif ++ + #define SEC_TO_NS (1000 * 1000 * 1000) + + /* Forward declarations */ +@@ -149,6 +158,16 @@ perf_counter(_Py_clock_info_t *info) + } + + #ifdef HAVE_CLOCK_GETTIME ++ ++#ifdef __APPLE__ ++/* ++ * The clock_* functions will be removed from the module ++ * dict entirely when the C API is not available. ++ */ ++#pragma clang diagnostic push ++#pragma clang diagnostic ignored "-Wunguarded-availability" ++#endif ++ + static PyObject * + time_clock_gettime(PyObject *self, PyObject *args) + { +@@ -297,6 +316,11 @@ PyDoc_STRVAR(clock_getres_doc, + "clock_getres(clk_id) -> floating point number\n\ + \n\ + Return the resolution (precision) of the specified clock clk_id."); ++ ++#ifdef __APPLE__ ++#pragma clang diagnostic pop ++#endif ++ + #endif /* HAVE_CLOCK_GETRES */ + + #ifdef HAVE_PTHREAD_GETCPUCLOCKID +@@ -1162,31 +1186,35 @@ _PyTime_GetProcessTimeWithInfo(_PyTime_t + #if defined(HAVE_CLOCK_GETTIME) \ + && (defined(CLOCK_PROCESS_CPUTIME_ID) || defined(CLOCK_PROF)) + struct timespec ts; ++ ++ if (HAVE_CLOCK_GETTIME_RUNTIME) { ++ + #ifdef CLOCK_PROF +- const clockid_t clk_id = CLOCK_PROF; +- const char *function = "clock_gettime(CLOCK_PROF)"; ++ const clockid_t clk_id = CLOCK_PROF; ++ const char *function = "clock_gettime(CLOCK_PROF)"; + #else +- const clockid_t clk_id = CLOCK_PROCESS_CPUTIME_ID; +- const char *function = "clock_gettime(CLOCK_PROCESS_CPUTIME_ID)"; ++ const clockid_t clk_id = CLOCK_PROCESS_CPUTIME_ID; ++ const char *function = "clock_gettime(CLOCK_PROCESS_CPUTIME_ID)"; + #endif + +- if (clock_gettime(clk_id, &ts) == 0) { +- if (info) { +- struct timespec res; +- info->implementation = function; +- info->monotonic = 1; +- info->adjustable = 0; +- if (clock_getres(clk_id, &res)) { +- PyErr_SetFromErrno(PyExc_OSError); +- return -1; ++ if (clock_gettime(clk_id, &ts) == 0) { ++ if (info) { ++ struct timespec res; ++ info->implementation = function; ++ info->monotonic = 1; ++ info->adjustable = 0; ++ if (clock_getres(clk_id, &res)) { ++ PyErr_SetFromErrno(PyExc_OSError); ++ return -1; ++ } ++ info->resolution = res.tv_sec + res.tv_nsec * 1e-9; + } +- info->resolution = res.tv_sec + res.tv_nsec * 1e-9; +- } + +- if (_PyTime_FromTimespec(tp, &ts) < 0) { +- return -1; ++ if (_PyTime_FromTimespec(tp, &ts) < 0) { ++ return -1; ++ } ++ return 0; + } +- return 0; + } + #endif + +@@ -1373,6 +1401,16 @@ _PyTime_GetThreadTimeWithInfo(_PyTime_t + + #elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID) + #define HAVE_THREAD_TIME ++ ++#if defined(__APPLE__) && defined(__has_attribute) && __has_attribute(availability) ++static int ++_PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) ++ __attribute__((availability(macos, introduced=10.12))) ++ __attribute__((availability(ios, introduced=10.0))) ++ __attribute__((availability(tvos, introduced=10.0))) ++ __attribute__((availability(watchos, introduced=3.0))); ++#endif ++ + static int + _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) + { +@@ -1404,6 +1442,15 @@ _PyTime_GetThreadTimeWithInfo(_PyTime_t + #endif + + #ifdef HAVE_THREAD_TIME ++#ifdef __APPLE__ ++/* ++ * The clock_* functions will be removed from the module ++ * dict entirely when the C API is not available. ++ */ ++#pragma clang diagnostic push ++#pragma clang diagnostic ignored "-Wunguarded-availability" ++#endif ++ + static PyObject * + time_thread_time(PyObject *self, PyObject *unused) + { +@@ -1434,6 +1481,11 @@ PyDoc_STRVAR(thread_time_ns_doc, + \n\ + Thread time for profiling as nanoseconds:\n\ + sum of the kernel and user-space CPU time."); ++ ++#ifdef __APPLE__ ++#pragma clang diagnostic pop ++#endif ++ + #endif + + +@@ -1483,9 +1535,19 @@ time_get_clock_info(PyObject *self, PyOb + } + #ifdef HAVE_THREAD_TIME + else if (strcmp(name, "thread_time") == 0) { +- if (_PyTime_GetThreadTimeWithInfo(&t, &info) < 0) { ++ ++#ifdef __APPLE__ ++ if (HAVE_CLOCK_GETTIME_RUNTIME) { ++#endif ++ if (_PyTime_GetThreadTimeWithInfo(&t, &info) < 0) { ++ return NULL; ++ } ++#ifdef __APPLE__ ++ } else { ++ PyErr_SetString(PyExc_ValueError, "unknown clock"); + return NULL; + } ++#endif + } + #endif + else { +@@ -1766,68 +1828,116 @@ if it is -1, mktime() should guess based + static int + time_exec(PyObject *module) + { ++#if defined(__APPLE__) && defined(HAVE_CLOCK_GETTIME) ++ if (HAVE_CLOCK_GETTIME_RUNTIME) { ++ /* pass: ^^^ cannot use '!' here */ ++ } else { ++ PyObject* dct = PyModule_GetDict(module); ++ if (dct == NULL) { ++ return -1; ++ } ++ ++ if (PyDict_DelItemString(dct, "clock_gettime") == -1) { ++ PyErr_Clear(); ++ } ++ if (PyDict_DelItemString(dct, "clock_gettime_ns") == -1) { ++ PyErr_Clear(); ++ } ++ if (PyDict_DelItemString(dct, "clock_settime") == -1) { ++ PyErr_Clear(); ++ } ++ if (PyDict_DelItemString(dct, "clock_settime_ns") == -1) { ++ PyErr_Clear(); ++ } ++ if (PyDict_DelItemString(dct, "clock_getres") == -1) { ++ PyErr_Clear(); ++ } ++ } ++#endif ++#if defined(__APPLE__) && defined(HAVE_THREAD_TIME) ++ if (HAVE_CLOCK_GETTIME_RUNTIME) { ++ /* pass: ^^^ cannot use '!' here */ ++ } else { ++ PyObject* dct = PyModule_GetDict(module); ++ ++ if (PyDict_DelItemString(dct, "thread_time") == -1) { ++ PyErr_Clear(); ++ } ++ if (PyDict_DelItemString(dct, "thread_time_ns") == -1) { ++ PyErr_Clear(); ++ } ++ } ++#endif + /* Set, or reset, module variables like time.timezone */ + if (init_timezone(module) < 0) { + return -1; + } + + #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_SETTIME) || defined(HAVE_CLOCK_GETRES) ++ if (HAVE_CLOCK_GETTIME_RUNTIME) { + + #ifdef CLOCK_REALTIME +- if (PyModule_AddIntMacro(module, CLOCK_REALTIME) < 0) { +- return -1; +- } ++ if (PyModule_AddIntMacro(module, CLOCK_REALTIME) < 0) { ++ return -1; ++ } + #endif ++ + #ifdef CLOCK_MONOTONIC +- if (PyModule_AddIntMacro(module, CLOCK_MONOTONIC) < 0) { +- return -1; +- } ++ ++ if (PyModule_AddIntMacro(module, CLOCK_MONOTONIC) < 0) { ++ return -1; ++ } ++ + #endif + #ifdef CLOCK_MONOTONIC_RAW +- if (PyModule_AddIntMacro(module, CLOCK_MONOTONIC_RAW) < 0) { +- return -1; +- } ++ if (PyModule_AddIntMacro(module, CLOCK_MONOTONIC_RAW) < 0) { ++ return -1; ++ } + #endif ++ + #ifdef CLOCK_HIGHRES +- if (PyModule_AddIntMacro(module, CLOCK_HIGHRES) < 0) { +- return -1; +- } ++ if (PyModule_AddIntMacro(module, CLOCK_HIGHRES) < 0) { ++ return -1; ++ } + #endif + #ifdef CLOCK_PROCESS_CPUTIME_ID +- if (PyModule_AddIntMacro(module, CLOCK_PROCESS_CPUTIME_ID) < 0) { +- return -1; +- } ++ if (PyModule_AddIntMacro(module, CLOCK_PROCESS_CPUTIME_ID) < 0) { ++ return -1; ++ } + #endif ++ + #ifdef CLOCK_THREAD_CPUTIME_ID +- if (PyModule_AddIntMacro(module, CLOCK_THREAD_CPUTIME_ID) < 0) { +- return -1; +- } ++ if (PyModule_AddIntMacro(module, CLOCK_THREAD_CPUTIME_ID) < 0) { ++ return -1; ++ } + #endif + #ifdef CLOCK_PROF +- if (PyModule_AddIntMacro(module, CLOCK_PROF) < 0) { +- return -1; +- } ++ if (PyModule_AddIntMacro(module, CLOCK_PROF) < 0) { ++ return -1; ++ } + #endif + #ifdef CLOCK_BOOTTIME +- if (PyModule_AddIntMacro(module, CLOCK_BOOTTIME) < 0) { +- return -1; +- } ++ if (PyModule_AddIntMacro(module, CLOCK_BOOTTIME) < 0) { ++ return -1; ++ } + #endif + #ifdef CLOCK_TAI +- if (PyModule_AddIntMacro(module, CLOCK_TAI) < 0) { +- return -1; +- } ++ if (PyModule_AddIntMacro(module, CLOCK_TAI) < 0) { ++ return -1; ++ } + #endif + #ifdef CLOCK_UPTIME +- if (PyModule_AddIntMacro(module, CLOCK_UPTIME) < 0) { +- return -1; +- } ++ if (PyModule_AddIntMacro(module, CLOCK_UPTIME) < 0) { ++ return -1; ++ } + #endif + #ifdef CLOCK_UPTIME_RAW +- if (PyModule_AddIntMacro(module, CLOCK_UPTIME_RAW) < 0) { +- return -1; +- } ++ ++ if (PyModule_AddIntMacro(module, CLOCK_UPTIME_RAW) < 0) { ++ return -1; ++ } + #endif ++ } + + #endif /* defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_SETTIME) || defined(HAVE_CLOCK_GETRES) */ + diff --git a/lang/python39/patches/patch-Python_bootstrap__hash.c b/lang/python39/patches/patch-Python_bootstrap__hash.c new file mode 100644 index 00000000000..301c566d9ba --- /dev/null +++ b/lang/python39/patches/patch-Python_bootstrap__hash.c @@ -0,0 +1,73 @@ +$NetBSD: patch-Python_bootstrap__hash.c,v 1.1 2020/11/12 10:58:21 sjmulder Exp $ + +Support for macOS 11 and Apple Silicon (ARM). Backported from: +https://github.com/python/cpython/pull/22855 + +--- Python/bootstrap_hash.c.orig 2020-10-05 15:07:58.000000000 +0000 ++++ Python/bootstrap_hash.c +@@ -25,6 +25,16 @@ + # include <sanitizer/msan_interface.h> + #endif + ++#if defined(__APPLE__) && defined(__has_builtin) ++# if __has_builtin(__builtin_available) ++# define HAVE_GETENTRYPY_GETRANDOM_RUNTIME __builtin_available(macOS 10.12, iOS 10.10, tvOS 10.0, watchOS 3.0, *) ++# endif ++#endif ++#ifndef HAVE_GETENTRYPY_GETRANDOM_RUNTIME ++# define HAVE_GETENTRYPY_GETRANDOM_RUNTIME 1 ++#endif ++ ++ + #ifdef Py_DEBUG + int _Py_HashSecret_Initialized = 0; + #else +@@ -208,6 +218,16 @@ py_getrandom(void *buffer, Py_ssize_t si + error. + + getentropy() is retried if it failed with EINTR: interrupted by a signal. */ ++ ++#if defined(__APPLE__) && defined(__has_attribute) && __has_attribute(availability) ++static int ++py_getentropy(char *buffer, Py_ssize_t size, int raise) ++ __attribute__((availability(macos,introduced=10.12))) ++ __attribute__((availability(ios,introduced=10.0))) ++ __attribute__((availability(tvos,introduced=10.0))) ++ __attribute__((availability(watchos,introduced=3.0))); ++#endif ++ + static int + py_getentropy(char *buffer, Py_ssize_t size, int raise) + { +@@ -498,19 +518,21 @@ pyurandom(void *buffer, Py_ssize_t size, + #else + + #if defined(PY_GETRANDOM) || defined(PY_GETENTROPY) ++ if (HAVE_GETENTRYPY_GETRANDOM_RUNTIME) { + #ifdef PY_GETRANDOM +- res = py_getrandom(buffer, size, blocking, raise); ++ res = py_getrandom(buffer, size, blocking, raise); + #else +- res = py_getentropy(buffer, size, raise); ++ res = py_getentropy(buffer, size, raise); + #endif +- if (res < 0) { +- return -1; +- } +- if (res == 1) { +- return 0; +- } +- /* getrandom() or getentropy() function is not available: failed with +- ENOSYS or EPERM. Fall back on reading from /dev/urandom. */ ++ if (res < 0) { ++ return -1; ++ } ++ if (res == 1) { ++ return 0; ++ } ++ /* getrandom() or getentropy() function is not available: failed with ++ ENOSYS or EPERM. Fall back on reading from /dev/urandom. */ ++ } /* end of availability block */ + #endif + + return dev_urandom(buffer, size, raise); diff --git a/lang/python39/patches/patch-Python_pytime.c b/lang/python39/patches/patch-Python_pytime.c new file mode 100644 index 00000000000..31235692d27 --- /dev/null +++ b/lang/python39/patches/patch-Python_pytime.c @@ -0,0 +1,73 @@ +$NetBSD: patch-Python_pytime.c,v 1.1 2020/11/12 10:58:21 sjmulder Exp $ + +Support for macOS 11 and Apple Silicon (ARM). Backported from: +https://github.com/python/cpython/pull/22855 + +--- Python/pytime.c.orig 2020-10-05 15:07:58.000000000 +0000 ++++ Python/pytime.c +@@ -5,6 +5,12 @@ + + #if defined(__APPLE__) + #include <mach/mach_time.h> /* mach_absolute_time(), mach_timebase_info() */ ++ ++#if defined(__APPLE__) && defined(__has_builtin) ++# if __has_builtin(__builtin_available) ++# define HAVE_CLOCK_GETTIME_RUNTIME __builtin_available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) ++# endif ++#endif + #endif + + #define _PyTime_check_mul_overflow(a, b) \ +@@ -683,15 +689,22 @@ pygettimeofday(_PyTime_t *tp, _Py_clock_ + + #else /* MS_WINDOWS */ + int err; +-#ifdef HAVE_CLOCK_GETTIME ++#if defined(HAVE_CLOCK_GETTIME) + struct timespec ts; +-#else ++#endif ++ ++#if !defined(HAVE_CLOCK_GETTIME) || defined(__APPLE__) + struct timeval tv; + #endif + + assert(info == NULL || raise); + + #ifdef HAVE_CLOCK_GETTIME ++ ++#ifdef HAVE_CLOCK_GETTIME_RUNTIME ++ if (HAVE_CLOCK_GETTIME_RUNTIME) { ++#endif ++ + err = clock_gettime(CLOCK_REALTIME, &ts); + if (err) { + if (raise) { +@@ -715,7 +728,14 @@ pygettimeofday(_PyTime_t *tp, _Py_clock_ + info->resolution = 1e-9; + } + } +-#else /* HAVE_CLOCK_GETTIME */ ++ ++#ifdef HAVE_CLOCK_GETTIME_RUNTIME ++ } else { ++#endif ++ ++#endif ++ ++#if !defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_GETTIME_RUNTIME) + + /* test gettimeofday() */ + err = gettimeofday(&tv, (struct timezone *)NULL); +@@ -735,6 +755,11 @@ pygettimeofday(_PyTime_t *tp, _Py_clock_ + info->monotonic = 0; + info->adjustable = 1; + } ++ ++#if defined(HAVE_CLOCK_GETTIME_RUNTIME) && defined(HAVE_CLOCK_GETTIME) ++ } /* end of availibity block */ ++#endif ++ + #endif /* !HAVE_CLOCK_GETTIME */ + #endif /* !MS_WINDOWS */ + return 0; diff --git a/lang/python39/patches/patch-configure b/lang/python39/patches/patch-configure index 48a5cc682a3..cc2a0ca8c98 100644 --- a/lang/python39/patches/patch-configure +++ b/lang/python39/patches/patch-configure @@ -1,13 +1,34 @@ -$NetBSD: patch-configure,v 1.1 2020/10/10 20:20:12 adam Exp $ +$NetBSD: patch-configure,v 1.2 2020/11/12 10:58:21 sjmulder Exp $ -Use gnu99 instead of c99 to avoid "alloca() undefined" problems. -Fix linking on Darwin; don't use -stack_size. -Changes for consistency across pkgsrc platforms. -Simplify _sysconfigdata to include only platform name. + - Use gnu99 instead of c99 to avoid "alloca() undefined" problems. + - Fix linking on Darwin; don't use -stack_size. + - Changes for consistency across pkgsrc platforms. + - Simplify _sysconfigdata to include only platform name. + - Support for macOS 11 and Apple Silicon (ARM). Backported from: + https://github.com/python/cpython/pull/22855 --- configure.orig 2020-10-05 15:07:58.000000000 +0000 +++ configure -@@ -6961,7 +6961,7 @@ UNIVERSAL_ARCH_FLAGS= +@@ -1510,8 +1510,8 @@ Optional Packages: + specify the kind of universal binary that should be + created. this option is only valid when + --enable-universalsdk is set; options are: +- ("32-bit", "64-bit", "3-way", "intel", "intel-32", +- "intel-64", or "all") see Mac/README.rst ++ ("universal2", "32-bit", "64-bit", "3-way", "intel", ++ "intel-32", "intel-64", or "all") see Mac/README.rst + --with-framework-name=FRAMEWORK + specify the name for the python framework on macOS + only valid when --enable-framework is set. see +@@ -6954,14 +6954,14 @@ fi + + + +-# The -arch flags for universal builds on OSX ++# The -arch flags for universal builds on macOS + UNIVERSAL_ARCH_FLAGS= + + # tweak BASECFLAGS based on compiler and platform case $GCC in yes) @@ -16,7 +37,51 @@ Simplify _sysconfigdata to include only platform name. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -Wextra" >&5 $as_echo_n "checking for -Wextra... " >&6; } -@@ -9617,7 +9617,6 @@ then +@@ -7481,6 +7481,11 @@ $as_echo "$CC" >&6; } + LIPO_32BIT_FLAGS="-extract ppc7400 -extract i386" + ARCH_RUN_32BIT="/usr/bin/arch -i386 -ppc" + ;; ++ universal2) ++ UNIVERSAL_ARCH_FLAGS="-arch arm64 -arch x86_64" ++ LIPO_32BIT_FLAGS="" ++ ARCH_RUN_32BIT="true" ++ ;; + intel) + UNIVERSAL_ARCH_FLAGS="-arch i386 -arch x86_64" + LIPO_32BIT_FLAGS="-extract i386" +@@ -7502,7 +7507,7 @@ $as_echo "$CC" >&6; } + ARCH_RUN_32BIT="/usr/bin/arch -i386 -ppc" + ;; + *) +- as_fn_error $? "proper usage is --with-universal-arch=32-bit|64-bit|all|intel|3-way" "$LINENO" 5 ++ as_fn_error $? "proper usage is --with-universal-arch=universal2|32-bit|64-bit|all|intel|3-way" "$LINENO" 5 + ;; + esac + +@@ -9334,7 +9339,7 @@ fi + MACOSX_DEFAULT_ARCH="ppc" + ;; + *) +- as_fn_error $? "Unexpected output of 'arch' on OSX" "$LINENO" 5 ++ as_fn_error $? "Unexpected output of 'arch' on macOS" "$LINENO" 5 + ;; + esac + else +@@ -9344,9 +9349,12 @@ fi + ;; + ppc) + MACOSX_DEFAULT_ARCH="ppc64" ++ ;; ++ arm64) ++ MACOSX_DEFAULT_ARCH="arm64" + ;; + *) +- as_fn_error $? "Unexpected output of 'arch' on OSX" "$LINENO" 5 ++ as_fn_error $? "Unexpected output of 'arch' on macOS" "$LINENO" 5 + ;; + esac + +@@ -9617,7 +9625,6 @@ then # to ensure that tests don't crash # Note: This matches the value of THREAD_STACK_SIZE in # thread_pthread.h @@ -24,7 +89,39 @@ Simplify _sysconfigdata to include only platform name. if test "$enable_framework" then -@@ -14437,10 +14436,10 @@ _ACEOF +@@ -11989,6 +11996,31 @@ $as_echo "no" >&6; } + + fi + rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _dyld_shared_cache_contains_path" >&5 ++$as_echo_n "checking for _dyld_shared_cache_contains_path... " >&6; } ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <mach-o/dyld.h> ++int ++main () ++{ ++void *x=_dyld_shared_cache_contains_path ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ ++$as_echo "#define HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH 1" >>confdefs.h ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 ++$as_echo "yes" >&6; } ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++ ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for memfd_create" >&5 + $as_echo_n "checking for memfd_create... " >&6; } +@@ -14437,10 +14469,10 @@ _ACEOF if ac_fn_c_try_compile "$LINENO"; then : @@ -37,7 +134,7 @@ Simplify _sysconfigdata to include only platform name. if test "$ax_cv_c_float_words_bigendian" = unknown; then ax_cv_c_float_words_bigendian=no else -@@ -15326,8 +15325,6 @@ fi +@@ -15326,8 +15358,6 @@ fi case $ac_sys_system in @@ -46,7 +143,7 @@ Simplify _sysconfigdata to include only platform name. *) EXT_SUFFIX=${SHLIB_SUFFIX};; esac -@@ -15383,11 +15380,7 @@ fi +@@ -15383,11 +15413,7 @@ fi diff --git a/lang/python39/patches/patch-configure.ac b/lang/python39/patches/patch-configure.ac new file mode 100644 index 00000000000..4e10110ca26 --- /dev/null +++ b/lang/python39/patches/patch-configure.ac @@ -0,0 +1,82 @@ +$NetBSD: patch-configure.ac,v 1.1 2020/11/12 10:58:21 sjmulder Exp $ + +Support for macOS 11 and Apple Silicon (ARM). Backported from: +https://github.com/python/cpython/pull/22855 + +--- configure.ac.orig 2020-10-05 15:07:58.000000000 +0000 ++++ configure.ac +@@ -218,7 +218,7 @@ AC_ARG_WITH(universal-archs, + AS_HELP_STRING([--with-universal-archs=ARCH], + [specify the kind of universal binary that should be created. this option is + only valid when --enable-universalsdk is set; options are: +- ("32-bit", "64-bit", "3-way", "intel", "intel-32", "intel-64", or "all") ++ ("universal2", "32-bit", "64-bit", "3-way", "intel", "intel-32", "intel-64", or "all") + see Mac/README.rst]), + [ + UNIVERSAL_ARCHS="$withval" +@@ -1587,7 +1587,7 @@ AC_SUBST(BASECFLAGS) + AC_SUBST(CFLAGS_NODIST) + AC_SUBST(LDFLAGS_NODIST) + +-# The -arch flags for universal builds on OSX ++# The -arch flags for universal builds on macOS + UNIVERSAL_ARCH_FLAGS= + AC_SUBST(UNIVERSAL_ARCH_FLAGS) + +@@ -1888,6 +1888,11 @@ yes) + LIPO_32BIT_FLAGS="-extract ppc7400 -extract i386" + ARCH_RUN_32BIT="/usr/bin/arch -i386 -ppc" + ;; ++ universal2) ++ UNIVERSAL_ARCH_FLAGS="-arch arm64 -arch x86_64" ++ LIPO_32BIT_FLAGS="" ++ ARCH_RUN_32BIT="true" ++ ;; + intel) + UNIVERSAL_ARCH_FLAGS="-arch i386 -arch x86_64" + LIPO_32BIT_FLAGS="-extract i386" +@@ -1909,7 +1914,7 @@ yes) + ARCH_RUN_32BIT="/usr/bin/arch -i386 -ppc" + ;; + *) +- AC_MSG_ERROR([proper usage is --with-universal-arch=32-bit|64-bit|all|intel|3-way]) ++ AC_MSG_ERROR([proper usage is --with-universal-arch=universal2|32-bit|64-bit|all|intel|3-way]) + ;; + esac + +@@ -2479,7 +2484,7 @@ case $ac_sys_system/$ac_sys_release in + MACOSX_DEFAULT_ARCH="ppc" + ;; + *) +- AC_MSG_ERROR([Unexpected output of 'arch' on OSX]) ++ AC_MSG_ERROR([Unexpected output of 'arch' on macOS]) + ;; + esac + else +@@ -2489,9 +2494,12 @@ 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]) ++ AC_MSG_ERROR([Unexpected output of 'arch' on macOS]) + ;; + esac + +@@ -3770,6 +3778,12 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + AC_MSG_RESULT(yes)], + [AC_MSG_RESULT(no) + ]) ++AC_MSG_CHECKING(for _dyld_shared_cache_contains_path) ++AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <mach-o/dyld.h>]], [[void *x=_dyld_shared_cache_contains_path]])], ++ [AC_DEFINE(HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH, 1, Define if you have the '_dyld_shared_cache_contains_path' function.) ++ AC_MSG_RESULT(yes)], ++ [AC_MSG_RESULT(no) ++]) + + AC_MSG_CHECKING(for memfd_create) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ diff --git a/lang/python39/patches/patch-pyconfig.h.in b/lang/python39/patches/patch-pyconfig.h.in index 8067cfa16c6..1fe5a3ff9f4 100644 --- a/lang/python39/patches/patch-pyconfig.h.in +++ b/lang/python39/patches/patch-pyconfig.h.in @@ -1,10 +1,12 @@ -$NetBSD: patch-pyconfig.h.in,v 1.1 2020/10/10 20:20:12 adam Exp $ +$NetBSD: patch-pyconfig.h.in,v 1.2 2020/11/12 10:58:21 sjmulder Exp $ -detect netcan/can.h on NetBSD + - detect netcan/can.h on NetBSD + - Support for macOS 11 and Apple Silicon (ARM). Backported from: + https://github.com/python/cpython/pull/22855 ---- pyconfig.h.in.orig 2019-09-06 08:21:57.000000000 +0000 +--- pyconfig.h.in.orig 2020-10-05 15:07:58.000000000 +0000 +++ pyconfig.h.in -@@ -631,6 +631,9 @@ +@@ -637,6 +637,9 @@ /* Define to 1 if you have the <linux/memfd.h> header file. */ #undef HAVE_LINUX_MEMFD_H @@ -14,3 +16,13 @@ detect netcan/can.h on NetBSD /* Define to 1 if you have the <linux/netlink.h> header file. */ #undef HAVE_LINUX_NETLINK_H +@@ -778,6 +781,9 @@ + /* Define if you have the 'prlimit' functions. */ + #undef HAVE_PRLIMIT + ++/* Define if you have the '_dyld_shared_cache_contains_path' function. */ ++#undef HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH ++ + /* Define to 1 if you have the <process.h> header file. */ + #undef HAVE_PROCESS_H + diff --git a/lang/python39/patches/patch-setup.py b/lang/python39/patches/patch-setup.py index 7918106e9ff..48406836472 100644 --- a/lang/python39/patches/patch-setup.py +++ b/lang/python39/patches/patch-setup.py @@ -1,10 +1,12 @@ -$NetBSD: patch-setup.py,v 1.1 2020/10/10 20:20:12 adam Exp $ +$NetBSD: patch-setup.py,v 1.2 2020/11/12 10:58:21 sjmulder Exp $ -Disable certain modules, so they can be built as separate packages. -Do not look for ncursesw. -Assume panel_library is correct; this is a fix for ncurses' gnupanel - which will get transformed to panel in buildlink. -Also look for uuid/uuid.h. + - Disable certain modules, so they can be built as separate packages. + - Do not look for ncursesw. + - Assume panel_library is correct; this is a fix for ncurses' gnupanel + which will get transformed to panel in buildlink. + - Also look for uuid/uuid.h. + - Support for macOS 11 and Apple Silicon (ARM). Backported from: + https://github.com/python/cpython/pull/22855 --- setup.py.orig 2020-10-05 15:07:58.000000000 +0000 +++ setup.py @@ -26,6 +28,20 @@ Also look for uuid/uuid.h. def get_platform(): +@@ -239,6 +239,13 @@ def is_macosx_sdk_path(path): + 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 @@ -740,15 +740,15 @@ class PyBuildExt(build_ext): add_dir_to_list(dir_list, directory) @@ -51,6 +67,16 @@ Also look for uuid/uuid.h. self.add_multiarch_paths() self.add_ldflags_cppflags() +@@ -803,6 +803,9 @@ class PyBuildExt(build_ext): + self.lib_dirs += ['/usr/lib/hpux64', '/usr/lib/hpux32'] + + if MACOS: ++ self.inc_dirs.append(macosx_sdk_root() + '/usr/include') ++ self.lib_dirs.append(macosx_sdk_root() + '/usr/lib') ++ + # This should work on any unixy platform ;-) + # If the user has bothered specifying additional -I and -L flags + # in OPT and LDFLAGS we might as well use them here. @@ -1013,8 +1013,6 @@ class PyBuildExt(build_ext): # use the same library for the readline and curses modules. if 'curses' in readline_termcap_library: @@ -120,6 +146,132 @@ Also look for uuid/uuid.h. if uuid_incs is not None: if self.compiler.find_library_file(self.lib_dirs, 'uuid'): uuid_libs = ['uuid'] +@@ -2101,43 +2108,17 @@ class PyBuildExt(build_ext): + library_dirs=added_lib_dirs)) + return True + +- def configure_ctypes_darwin(self, ext): +- # Darwin (OS X) uses preconfigured files, in +- # the Modules/_ctypes/libffi_osx directory. +- ffi_srcdir = os.path.abspath(os.path.join(self.srcdir, 'Modules', +- '_ctypes', 'libffi_osx')) +- sources = [os.path.join(ffi_srcdir, p) +- for p in ['ffi.c', +- 'x86/darwin64.S', +- 'x86/x86-darwin.S', +- 'x86/x86-ffi_darwin.c', +- 'x86/x86-ffi64.c', +- 'powerpc/ppc-darwin.S', +- 'powerpc/ppc-darwin_closure.S', +- 'powerpc/ppc-ffi_darwin.c', +- 'powerpc/ppc64-darwin_closure.S', +- ]] +- +- # Add .S (preprocessed assembly) to C compiler source extensions. +- self.compiler.src_extensions.append('.S') +- +- include_dirs = [os.path.join(ffi_srcdir, 'include'), +- os.path.join(ffi_srcdir, 'powerpc')] +- ext.include_dirs.extend(include_dirs) +- ext.sources.extend(sources) +- return True +- + def configure_ctypes(self, ext): +- if not self.use_system_libffi: +- if MACOS: +- return self.configure_ctypes_darwin(ext) +- print('INFO: Could not locate ffi libs and/or headers') +- return False + return True + + def detect_ctypes(self): + # Thomas Heller's _ctypes module +- self.use_system_libffi = False ++ ++ if (not sysconfig.get_config_var("LIBFFI_INCLUDEDIR") and MACOS): ++ 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 = ['-DPy_BUILD_CORE_MODULE'] + extra_link_args = [] +@@ -2150,11 +2131,9 @@ class PyBuildExt(build_ext): + + if MACOS: + sources.append('_ctypes/malloc_closure.c') +- sources.append('_ctypes/darwin/dlfcn_simple.c') ++ extra_compile_args.append('-DUSING_MALLOC_CLOSURE_DOT_C=1') + extra_compile_args.append('-DMACOSX') + include_dirs.append('_ctypes/darwin') +- # XXX Is this still needed? +- # extra_link_args.extend(['-read_only_relocs', 'warning']) + + elif HOST_PLATFORM == 'sunos5': + # XXX This shouldn't be necessary; it appears that some +@@ -2184,31 +2163,48 @@ class PyBuildExt(build_ext): + sources=['_ctypes/_ctypes_test.c'], + libraries=['m'])) + ++ ffi_inc = sysconfig.get_config_var("LIBFFI_INCLUDEDIR") ++ ffi_lib = None ++ + ffi_inc_dirs = self.inc_dirs.copy() + if MACOS: +- 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 +- ffi_inc_dirs.append('/usr/include/ffi') +- +- ffi_inc = [sysconfig.get_config_var("LIBFFI_INCLUDEDIR")] +- if not ffi_inc or ffi_inc[0] == '': +- ffi_inc = find_file('ffi.h', [], ffi_inc_dirs) +- if ffi_inc is not None: +- ffi_h = ffi_inc[0] + '/ffi.h' ++ ffi_in_sdk = os.path.join(macosx_sdk_root(), "usr/include/ffi") ++ ++ if not ffi_inc: ++ if os.path.exists(ffi_in_sdk): ++ ext.extra_compile_args.append("-DUSING_APPLE_OS_LIBFFI=1") ++ 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 ++ ffi_inc_dirs.append('/usr/include/ffi') ++ ++ if not ffi_inc: ++ found = find_file('ffi.h', [], ffi_inc_dirs) ++ if found: ++ ffi_inc = found[0] ++ if ffi_inc: ++ ffi_h = ffi_inc + '/ffi.h' + if not os.path.exists(ffi_h): + ffi_inc = None + print('Header file {} does not exist'.format(ffi_h)) +- ffi_lib = None +- if ffi_inc is not None: ++ if ffi_lib is None and ffi_inc: + for lib_name in ('ffi', 'ffi_pic'): + if (self.compiler.find_library_file(self.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_prep_cif_var', ffi_headers): ++ ext.extra_compile_args.append("-DHAVE_FFI_PREP_CIF_VAR=1") ++ if grep_headers_for('ffi_prep_closure_loc', ffi_headers): ++ ext.extra_compile_args.append("-DHAVE_FFI_PREP_CLOSURE_LOC=1") ++ if grep_headers_for('ffi_closure_alloc', ffi_headers): ++ ext.extra_compile_args.append("-DHAVE_FFI_CLOSURE_ALLOC=1") ++ ++ ext.include_dirs.append(ffi_inc) + ext.libraries.append(ffi_lib) + self.use_system_libffi = True + @@ -2226,10 +2250,7 @@ class PyBuildExt(build_ext): sources = ['_decimal/_decimal.c'] depends = ['_decimal/docstrings.h'] |