pkgsrc-Changes archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

CVS commit: pkgsrc/lang/python38



Module Name:    pkgsrc
Committed By:   sjmulder
Date:           Tue Nov 17 19:33:15 UTC 2020

Modified Files:
        pkgsrc/lang/python38: Makefile distinfo
        pkgsrc/lang/python38/patches: patch-configure patch-pyconfig.h.in
            patch-setup.py
Added Files:
        pkgsrc/lang/python38/patches: patch-Lib___osx__support.py
            patch-Lib_ctypes_macholib_dyld.py
            patch-Lib_ctypes_test_test__macholib.py
            patch-Lib_distutils_tests_test__build__ext.py
            patch-Lib_test_test__bytes.py patch-Lib_test_test__platform.py
            patch-Lib_test_test__unicode.py
            patch-Mac_BuildScript_build-installer.py patch-Mac_Tools_pythonw.c
            patch-Modules___ctypes_callbacks.c
            patch-Modules___ctypes_callproc.c patch-Modules___ctypes_ctypes.h
            patch-Modules___ctypes_malloc__closure.c
            patch-Modules___decimal_libmpdec_mpdecimal.h
            patch-Modules_getpath.c patch-Modules_posixmodule.c
            patch-Modules_timemodule.c patch-Python_bootstrap__hash.c
            patch-Python_pytime.c patch-configure.ac

Log Message:
lang/python38: Fix for macOS 11 and Apple Silicon

(Apple Silicon being their aarch64 platform.)

This is backport of the same in lang/python39. Only minor changes were
needed.

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.


To generate a diff of this commit:
cvs rdiff -u -r1.13 -r1.14 pkgsrc/lang/python38/Makefile
cvs rdiff -u -r1.12 -r1.13 pkgsrc/lang/python38/distinfo
cvs rdiff -u -r0 -r1.1 \
    pkgsrc/lang/python38/patches/patch-Lib___osx__support.py \
    pkgsrc/lang/python38/patches/patch-Lib_ctypes_macholib_dyld.py \
    pkgsrc/lang/python38/patches/patch-Lib_ctypes_test_test__macholib.py \
    pkgsrc/lang/python38/patches/patch-Lib_distutils_tests_test__build__ext.py \
    pkgsrc/lang/python38/patches/patch-Lib_test_test__bytes.py \
    pkgsrc/lang/python38/patches/patch-Lib_test_test__platform.py \
    pkgsrc/lang/python38/patches/patch-Lib_test_test__unicode.py \
    pkgsrc/lang/python38/patches/patch-Mac_BuildScript_build-installer.py \
    pkgsrc/lang/python38/patches/patch-Mac_Tools_pythonw.c \
    pkgsrc/lang/python38/patches/patch-Modules___ctypes_callbacks.c \
    pkgsrc/lang/python38/patches/patch-Modules___ctypes_callproc.c \
    pkgsrc/lang/python38/patches/patch-Modules___ctypes_ctypes.h \
    pkgsrc/lang/python38/patches/patch-Modules___ctypes_malloc__closure.c \
    pkgsrc/lang/python38/patches/patch-Modules___decimal_libmpdec_mpdecimal.h \
    pkgsrc/lang/python38/patches/patch-Modules_getpath.c \
    pkgsrc/lang/python38/patches/patch-Modules_posixmodule.c \
    pkgsrc/lang/python38/patches/patch-Modules_timemodule.c \
    pkgsrc/lang/python38/patches/patch-Python_bootstrap__hash.c \
    pkgsrc/lang/python38/patches/patch-Python_pytime.c \
    pkgsrc/lang/python38/patches/patch-configure.ac
cvs rdiff -u -r1.4 -r1.5 pkgsrc/lang/python38/patches/patch-configure
cvs rdiff -u -r1.1 -r1.2 pkgsrc/lang/python38/patches/patch-pyconfig.h.in
cvs rdiff -u -r1.3 -r1.4 pkgsrc/lang/python38/patches/patch-setup.py

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: pkgsrc/lang/python38/Makefile
diff -u pkgsrc/lang/python38/Makefile:1.13 pkgsrc/lang/python38/Makefile:1.14
--- pkgsrc/lang/python38/Makefile:1.13  Fri Aug 14 19:28:44 2020
+++ pkgsrc/lang/python38/Makefile       Tue Nov 17 19:33:14 2020
@@ -1,8 +1,9 @@
-# $NetBSD: Makefile,v 1.13 2020/08/14 19:28:44 schmonz Exp $
+# $NetBSD: Makefile,v 1.14 2020/11/17 19:33:14 sjmulder Exp $
 
 .include "dist.mk"
 
 PKGNAME=       python38-${PY_DISTVERSION}
+PKGREVISION=   1
 CATEGORIES=    lang python
 
 MAINTAINER=    pkgsrc-users%NetBSD.org@localhost

Index: pkgsrc/lang/python38/distinfo
diff -u pkgsrc/lang/python38/distinfo:1.12 pkgsrc/lang/python38/distinfo:1.13
--- pkgsrc/lang/python38/distinfo:1.12  Mon Sep 28 19:31:55 2020
+++ pkgsrc/lang/python38/distinfo       Tue Nov 17 19:33:14 2020
@@ -1,21 +1,41 @@
-$NetBSD: distinfo,v 1.12 2020/09/28 19:31:55 adam Exp $
+$NetBSD: distinfo,v 1.13 2020/11/17 19:33:14 sjmulder Exp $
 
 SHA1 (Python-3.8.6.tar.xz) = 6ee446eaacf901a3305565bd6569e2de135168e3
 RMD160 (Python-3.8.6.tar.xz) = 89c134d2d1bc02975cf959cc4a7ee63dba5c5388
 SHA512 (Python-3.8.6.tar.xz) = 22faec84f6e172e1ac7c6bd6fd37e9b6ae4afc91cf5136aa8cac8ebbed8d18793f9196e8749b8ccc43447cb6c41cb450f65ea72dd363c06dfaeb14e0455f5560
 Size (Python-3.8.6.tar.xz) = 18233864 bytes
+SHA1 (patch-Lib___osx__support.py) = 95c729132e5bdbda72789f02b37ed111d0d9d11e
+SHA1 (patch-Lib_ctypes_macholib_dyld.py) = 3acfa836e06bb1ca994357bc4b687af1ce1641e0
+SHA1 (patch-Lib_ctypes_test_test__macholib.py) = db352894c47cbb4bed4905b4a7dde272577c65d8
 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) = 481dce36ddb258707470d18f84c300700326dc1e
 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) = 6de71f3d00cc2079f1c2fcf1a56eca993a4dc43a
+SHA1 (patch-Lib_test_test__platform.py) = ce6825dba49024fcd200638614209b31ae24df0a
+SHA1 (patch-Lib_test_test__unicode.py) = 915a80e2c7b9e056e58fc8600b099e86634f28dd
+SHA1 (patch-Mac_BuildScript_build-installer.py) = 731aa225a7cf33a21431bbd34d50cb5f629ab0df
+SHA1 (patch-Mac_Tools_pythonw.c) = aa2e7bfc5c515d48916f817d04fe2bb9775ea3c3
 SHA1 (patch-Makefile.pre.in) = d42f9f5bca1dd663f64122dc95b49111452fe6e8
+SHA1 (patch-Modules___ctypes_callbacks.c) = 99d821b1db08e680bc8ed3faecbda07f31e389e0
+SHA1 (patch-Modules___ctypes_callproc.c) = ec013388ecf599d3faad20a3945e852bed94a5e7
+SHA1 (patch-Modules___ctypes_ctypes.h) = bfa5574db6be78f71584e6b0b92965804cb469ba
+SHA1 (patch-Modules___ctypes_malloc__closure.c) = eadb811e15c4b821790480d7c4a4908753773e0f
+SHA1 (patch-Modules___decimal_libmpdec_mpdecimal.h) = 3710f2e524a8786470d01e7b2fc812600f0ec169
+SHA1 (patch-Modules_getpath.c) = c6930e41e57e31e3f46b4b9e0d0f5fcc8a0e5163
 SHA1 (patch-Modules_makesetup) = a06786eebffadecedba5e3a50a9785fb47613567
 SHA1 (patch-Modules_nismodule.c) = 1bafe9b06359586d027a77011b103877590d947d
+SHA1 (patch-Modules_posixmodule.c) = ea24a1aa19b596b5d4457a4eff761e516406145f
 SHA1 (patch-Modules_socketmodule.c) = e99fd9e30e3feafef1747a2f52446d8fec543362
 SHA1 (patch-Modules_socketmodule.h) = 13a3290eb72078067060d3e71b7baa08f3eb591c
+SHA1 (patch-Modules_timemodule.c) = bc8ba8c63e6be1411067480d661bd3b23dfa14c0
+SHA1 (patch-Python_bootstrap__hash.c) = 2e7d24ded1369624b2983b15784988517a9697a5
+SHA1 (patch-Python_pytime.c) = 41981f821e0b420abcb0334312148deb9a9fed5e
 SHA1 (patch-Python_thread__pthread.h) = fb81eaa604b4ed7c1b64c3f4731d58a8aee257be
-SHA1 (patch-configure) = 11991489b71557cc934e268981703e9b1dbba4c6
-SHA1 (patch-pyconfig.h.in) = 4bc6e95441cb5faae94d1d52aeaaa10ae01385b6
-SHA1 (patch-setup.py) = ee2adad91434f2739a266c8b5eaad07767b9571a
+SHA1 (patch-configure) = c63ae7364c69fed98d366fd2b6a727a71b10defc
+SHA1 (patch-configure.ac) = 2b341061350671d820d696a659176a35a93d800d
+SHA1 (patch-pyconfig.h.in) = 6e24f401286768641c7d69dd75cfe18f1d8df1e7
+SHA1 (patch-setup.py) = 2211bfe01c6c53f5c9852f9569a31975f7b7cb5e

Index: pkgsrc/lang/python38/patches/patch-configure
diff -u pkgsrc/lang/python38/patches/patch-configure:1.4 pkgsrc/lang/python38/patches/patch-configure:1.5
--- pkgsrc/lang/python38/patches/patch-configure:1.4    Fri May 15 08:24:50 2020
+++ pkgsrc/lang/python38/patches/patch-configure        Tue Nov 17 19:33:15 2020
@@ -1,13 +1,30 @@
-$NetBSD: patch-configure,v 1.4 2020/05/15 08:24:50 adam Exp $
+$NetBSD: patch-configure,v 1.5 2020/11/17 19:33:15 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). Mostly backported from:
+   https://github.com/python/cpython/pull/22855
 
---- configure.orig     2020-05-13 17:31:54.000000000 +0000
+--- configure.orig     2020-09-23 12:36:32.000000000 +0000
 +++ configure
-@@ -6924,7 +6924,7 @@ UNIVERSAL_ARCH_FLAGS=
+@@ -1502,9 +1502,11 @@ Optional Packages:
+   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+   --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+   --with-universal-archs=ARCH
+-                          select architectures for universal build ("32-bit",
+-                          "64-bit", "3-way", "intel", "intel-32", "intel-64",
+-                          or "all")
++                          specify the kind of universal binary that should be
++                          created. this option is only valid when
++                          --enable-universalsdk is set; options are:
++                          ("universal2", "32-bit", "64-bit", "3-way", "intel",
++                          "intel-32", "intel-64", or "all") see Mac/README.rst
+   --with-framework-name=FRAMEWORK
+                           specify an alternate name of the framework built
+                           with --enable-framework
+@@ -6924,7 +6926,7 @@ UNIVERSAL_ARCH_FLAGS=
  # tweak BASECFLAGS based on compiler and platform
  case $GCC in
  yes)
@@ -16,7 +33,38 @@ Simplify _sysconfigdata to include only 
  
      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -Wextra" >&5
  $as_echo_n "checking for -Wextra... " >&6; }
-@@ -9536,7 +9536,6 @@ then
+@@ -7403,6 +7405,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"
+@@ -7424,7 +7431,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
+ 
+@@ -9263,6 +9270,9 @@ fi
+               ;;
+       ppc)
+               MACOSX_DEFAULT_ARCH="ppc64"
++              ;;
++      arm64)
++              MACOSX_DEFAULT_ARCH="arm64"
+               ;;
+       *)
+               as_fn_error $? "Unexpected output of 'arch' on OSX" "$LINENO" 5
+@@ -9536,7 +9546,6 @@ then
                # to ensure that tests don't crash
                # Note: This matches the value of THREAD_STACK_SIZE in
                # thread_pthread.h
@@ -24,7 +72,39 @@ Simplify _sysconfigdata to include only 
  
                if test "$enable_framework"
                then
-@@ -14303,10 +14302,10 @@ _ACEOF
+@@ -11824,6 +11833,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; }
+@@ -14303,10 +14337,10 @@ _ACEOF
  if ac_fn_c_try_compile "$LINENO"; then :
  
  
@@ -37,7 +117,7 @@ Simplify _sysconfigdata to include only 
    if test "$ax_cv_c_float_words_bigendian" = unknown; then
      ax_cv_c_float_words_bigendian=no
    else
-@@ -15192,8 +15191,6 @@ fi
+@@ -15192,8 +15226,6 @@ fi
  
  
  case $ac_sys_system in
@@ -46,7 +126,7 @@ Simplify _sysconfigdata to include only 
      *)
        EXT_SUFFIX=${SHLIB_SUFFIX};;
  esac
-@@ -15213,11 +15210,7 @@ else
+@@ -15213,11 +15245,7 @@ else
  fi
  
  

Index: pkgsrc/lang/python38/patches/patch-pyconfig.h.in
diff -u pkgsrc/lang/python38/patches/patch-pyconfig.h.in:1.1 pkgsrc/lang/python38/patches/patch-pyconfig.h.in:1.2
--- pkgsrc/lang/python38/patches/patch-pyconfig.h.in:1.1        Tue Oct 15 16:50:11 2019
+++ pkgsrc/lang/python38/patches/patch-pyconfig.h.in    Tue Nov 17 19:33:15 2020
@@ -1,10 +1,12 @@
-$NetBSD: patch-pyconfig.h.in,v 1.1 2019/10/15 16:50:11 adam Exp $
+$NetBSD: patch-pyconfig.h.in,v 1.2 2020/11/17 19:33:15 sjmulder Exp $
 
-detect netcan/can.h on NetBSD
+ - detect netcan/can.h on NetBSD
+ - Support for macOS 11 and Apple Silicon (ARM). Mostly 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-09-23 12:36:32.000000000 +0000
 +++ pyconfig.h.in
-@@ -631,6 +631,9 @@
+@@ -634,6 +634,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
  
+@@ -772,6 +775,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
+ 

Index: pkgsrc/lang/python38/patches/patch-setup.py
diff -u pkgsrc/lang/python38/patches/patch-setup.py:1.3 pkgsrc/lang/python38/patches/patch-setup.py:1.4
--- pkgsrc/lang/python38/patches/patch-setup.py:1.3     Tue Jul 14 19:12:31 2020
+++ pkgsrc/lang/python38/patches/patch-setup.py Tue Nov 17 19:33:15 2020
@@ -1,12 +1,14 @@
-$NetBSD: patch-setup.py,v 1.3 2020/07/14 19:12:31 adam Exp $
+$NetBSD: patch-setup.py,v 1.4 2020/11/17 19:33:15 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). Mostly backported from:
+   https://github.com/python/cpython/pull/22855
 
---- setup.py.orig      2020-07-13 12:11:53.000000000 +0000
+--- setup.py.orig      2020-09-23 12:36:32.000000000 +0000
 +++ setup.py
 @@ -10,7 +10,7 @@ import sys
  import sysconfig
@@ -26,7 +28,21 @@ Also look for uuid/uuid.h.
  
  
  def get_platform():
-@@ -645,15 +645,15 @@ class PyBuildExt(build_ext):
+@@ -188,6 +188,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
+@@ -645,15 +652,15 @@ class PyBuildExt(build_ext):
                          add_dir_to_list(dir_list, directory)
  
      def configure_compiler(self):
@@ -51,7 +67,17 @@ Also look for uuid/uuid.h.
          self.add_multiarch_paths()
          self.add_ldflags_cppflags()
  
-@@ -912,8 +912,6 @@ class PyBuildExt(build_ext):
+@@ -701,6 +708,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.
+@@ -912,8 +922,6 @@ class PyBuildExt(build_ext):
          # use the same library for the readline and curses modules.
          if 'curses' in readline_termcap_library:
              curses_library = readline_termcap_library
@@ -60,7 +86,7 @@ Also look for uuid/uuid.h.
          # Issue 36210: OSS provided ncurses does not link on AIX
          # Use IBM supplied 'curses' for successful build of _curses
          elif AIX and self.compiler.find_library_file(self.lib_dirs, 'curses'):
-@@ -1015,8 +1013,7 @@ class PyBuildExt(build_ext):
+@@ -1015,8 +1023,7 @@ class PyBuildExt(build_ext):
          # If the curses module is enabled, check for the panel module
          # _curses_panel needs some form of ncurses
          skip_curses_panel = True if AIX else False
@@ -70,7 +96,7 @@ Also look for uuid/uuid.h.
              self.add(Extension('_curses_panel', ['_curses_panel.c'],
                                 include_dirs=curses_includes,
                                 define_macros=curses_defines,
-@@ -1263,6 +1260,31 @@ class PyBuildExt(build_ext):
+@@ -1263,6 +1270,31 @@ class PyBuildExt(build_ext):
          dbm_order = ['gdbm']
          # The standard Unix dbm module:
          if not CYGWIN:
@@ -102,7 +128,7 @@ Also look for uuid/uuid.h.
              config_args = [arg.strip("'")
                             for arg in sysconfig.get_config_var("CONFIG_ARGS").split()]
              dbm_args = [arg for arg in config_args
-@@ -1274,7 +1296,7 @@ class PyBuildExt(build_ext):
+@@ -1274,7 +1306,7 @@ class PyBuildExt(build_ext):
              dbmext = None
              for cand in dbm_order:
                  if cand == "ndbm":
@@ -111,7 +137,7 @@ Also look for uuid/uuid.h.
                          # Some systems have -lndbm, others have -lgdbm_compat,
                          # others don't have either
                          if self.compiler.find_library_file(self.lib_dirs,
-@@ -1674,6 +1696,8 @@ class PyBuildExt(build_ext):
+@@ -1674,6 +1706,8 @@ class PyBuildExt(build_ext):
      def detect_uuid(self):
          # Build the _uuid module if possible
          uuid_incs = find_file("uuid.h", self.inc_dirs, ["/usr/include/uuid"])
@@ -120,7 +146,133 @@ 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']
-@@ -2081,10 +2105,7 @@ class PyBuildExt(build_ext):
+@@ -1956,43 +1990,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 = []
+         extra_link_args = []
+@@ -2005,11 +2013,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
+@@ -2039,31 +2045,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
+ 
+@@ -2081,10 +2104,7 @@ class PyBuildExt(build_ext):
              sources = ['_decimal/_decimal.c']
              depends = ['_decimal/docstrings.h']
          else:
@@ -132,7 +284,7 @@ Also look for uuid/uuid.h.
              libraries = ['m']
              sources = [
                '_decimal/_decimal.c',
-@@ -2424,7 +2445,7 @@ def main():
+@@ -2424,7 +2444,7 @@ def main():
            # If you change the scripts installed here, you also need to
            # check the PyBuildScripts command above, and change the links
            # created by the bininstall target in Makefile.pre.in

Added files:

Index: pkgsrc/lang/python38/patches/patch-Lib___osx__support.py
diff -u /dev/null pkgsrc/lang/python38/patches/patch-Lib___osx__support.py:1.1
--- /dev/null   Tue Nov 17 19:33:15 2020
+++ pkgsrc/lang/python38/patches/patch-Lib___osx__support.py    Tue Nov 17 19:33:15 2020
@@ -0,0 +1,80 @@
+$NetBSD: patch-Lib___osx__support.py,v 1.1 2020/11/17 19:33:15 sjmulder Exp $
+
+Support for macOS 11 and Apple Silicon (ARM). Mostly backported from:
+https://github.com/python/cpython/pull/22855
+
+--- Lib/_osx_support.py.orig   2020-09-23 12:36:32.000000000 +0000
++++ Lib/_osx_support.py
+@@ -110,6 +110,25 @@ 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 +151,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 +354,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 +510,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'):
Index: pkgsrc/lang/python38/patches/patch-Lib_ctypes_macholib_dyld.py
diff -u /dev/null pkgsrc/lang/python38/patches/patch-Lib_ctypes_macholib_dyld.py:1.1
--- /dev/null   Tue Nov 17 19:33:15 2020
+++ pkgsrc/lang/python38/patches/patch-Lib_ctypes_macholib_dyld.py      Tue Nov 17 19:33:15 2020
@@ -0,0 +1,35 @@
+$NetBSD: patch-Lib_ctypes_macholib_dyld.py,v 1.1 2020/11/17 19:33:15 sjmulder Exp $
+
+Support for macOS 11 and Apple Silicon (ARM). Mostly backported from:
+https://github.com/python/cpython/pull/22855
+
+--- Lib/ctypes/macholib/dyld.py.orig   2020-09-23 12:36:32.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):
Index: pkgsrc/lang/python38/patches/patch-Lib_ctypes_test_test__macholib.py
diff -u /dev/null pkgsrc/lang/python38/patches/patch-Lib_ctypes_test_test__macholib.py:1.1
--- /dev/null   Tue Nov 17 19:33:15 2020
+++ pkgsrc/lang/python38/patches/patch-Lib_ctypes_test_test__macholib.py        Tue Nov 17 19:33:15 2020
@@ -0,0 +1,36 @@
+$NetBSD: patch-Lib_ctypes_test_test__macholib.py,v 1.1 2020/11/17 19:33:15 sjmulder Exp $
+
+Support for macOS 11 and Apple Silicon (ARM). Mostly backported from:
+https://github.com/python/cpython/pull/22855
+
+--- Lib/ctypes/test/test_macholib.py.orig      2020-09-23 12:36:32.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()
Index: pkgsrc/lang/python38/patches/patch-Lib_distutils_tests_test__build__ext.py
diff -u /dev/null pkgsrc/lang/python38/patches/patch-Lib_distutils_tests_test__build__ext.py:1.1
--- /dev/null   Tue Nov 17 19:33:15 2020
+++ pkgsrc/lang/python38/patches/patch-Lib_distutils_tests_test__build__ext.py  Tue Nov 17 19:33:15 2020
@@ -0,0 +1,16 @@
+$NetBSD: patch-Lib_distutils_tests_test__build__ext.py,v 1.1 2020/11/17 19:33:15 sjmulder Exp $
+
+Support for macOS 11 and Apple Silicon (ARM). Mostly backported from:
+https://github.com/python/cpython/pull/22855
+
+--- Lib/distutils/tests/test_build_ext.py.orig 2020-09-23 12:36:32.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:
Index: pkgsrc/lang/python38/patches/patch-Lib_test_test__bytes.py
diff -u /dev/null pkgsrc/lang/python38/patches/patch-Lib_test_test__bytes.py:1.1
--- /dev/null   Tue Nov 17 19:33:15 2020
+++ pkgsrc/lang/python38/patches/patch-Lib_test_test__bytes.py  Tue Nov 17 19:33:15 2020
@@ -0,0 +1,15 @@
+$NetBSD: patch-Lib_test_test__bytes.py,v 1.1 2020/11/17 19:33:15 sjmulder Exp $
+
+Support for macOS 11 and Apple Silicon (ARM). Mostly backported from:
+https://github.com/python/cpython/pull/22855
+
+--- Lib/test/test_bytes.py.orig        2020-09-23 12:36:32.000000000 +0000
++++ Lib/test/test_bytes.py
+@@ -963,6 +963,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
Index: pkgsrc/lang/python38/patches/patch-Lib_test_test__platform.py
diff -u /dev/null pkgsrc/lang/python38/patches/patch-Lib_test_test__platform.py:1.1
--- /dev/null   Tue Nov 17 19:33:15 2020
+++ pkgsrc/lang/python38/patches/patch-Lib_test_test__platform.py       Tue Nov 17 19:33:15 2020
@@ -0,0 +1,16 @@
+$NetBSD: patch-Lib_test_test__platform.py,v 1.1 2020/11/17 19:33:15 sjmulder Exp $
+
+Support for macOS 11 and Apple Silicon (ARM). Mostly backported from:
+https://github.com/python/cpython/pull/22855
+
+--- Lib/test/test_platform.py.orig     2020-09-23 12:36:32.000000000 +0000
++++ Lib/test/test_platform.py
+@@ -217,7 +217,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')
+ 
Index: pkgsrc/lang/python38/patches/patch-Lib_test_test__unicode.py
diff -u /dev/null pkgsrc/lang/python38/patches/patch-Lib_test_test__unicode.py:1.1
--- /dev/null   Tue Nov 17 19:33:15 2020
+++ pkgsrc/lang/python38/patches/patch-Lib_test_test__unicode.py        Tue Nov 17 19:33:15 2020
@@ -0,0 +1,21 @@
+$NetBSD: patch-Lib_test_test__unicode.py,v 1.1 2020/11/17 19:33:15 sjmulder Exp $
+
+Support for macOS 11 and Apple Silicon (ARM). Mostly backported from:
+https://github.com/python/cpython/pull/22855
+
+--- Lib/test/test_unicode.py.orig      2020-09-23 12:36:32.000000000 +0000
++++ Lib/test/test_unicode.py
+@@ -2454,11 +2454,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):
Index: pkgsrc/lang/python38/patches/patch-Mac_BuildScript_build-installer.py
diff -u /dev/null pkgsrc/lang/python38/patches/patch-Mac_BuildScript_build-installer.py:1.1
--- /dev/null   Tue Nov 17 19:33:15 2020
+++ pkgsrc/lang/python38/patches/patch-Mac_BuildScript_build-installer.py       Tue Nov 17 19:33:15 2020
@@ -0,0 +1,68 @@
+$NetBSD: patch-Mac_BuildScript_build-installer.py,v 1.1 2020/11/17 19:33:15 sjmulder Exp $
+
+Support for macOS 11 and Apple Silicon (ARM). Mostly backported from:
+https://github.com/python/cpython/pull/22855
+
+--- Mac/BuildScript/build-installer.py.orig    2020-09-23 12:36:32.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,26 @@ 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 +253,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 +824,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"],
+         }
Index: pkgsrc/lang/python38/patches/patch-Mac_Tools_pythonw.c
diff -u /dev/null pkgsrc/lang/python38/patches/patch-Mac_Tools_pythonw.c:1.1
--- /dev/null   Tue Nov 17 19:33:15 2020
+++ pkgsrc/lang/python38/patches/patch-Mac_Tools_pythonw.c      Tue Nov 17 19:33:15 2020
@@ -0,0 +1,44 @@
+$NetBSD: patch-Mac_Tools_pythonw.c,v 1.1 2020/11/17 19:33:15 sjmulder Exp $
+
+Support for macOS 11 and Apple Silicon (ARM). Mostly backported from:
+https://github.com/python/cpython/pull/22855
+
+--- Mac/Tools/pythonw.c.orig   2020-09-23 12:36:32.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);
Index: pkgsrc/lang/python38/patches/patch-Modules___ctypes_callbacks.c
diff -u /dev/null pkgsrc/lang/python38/patches/patch-Modules___ctypes_callbacks.c:1.1
--- /dev/null   Tue Nov 17 19:33:15 2020
+++ pkgsrc/lang/python38/patches/patch-Modules___ctypes_callbacks.c     Tue Nov 17 19:33:15 2020
@@ -0,0 +1,76 @@
+$NetBSD: patch-Modules___ctypes_callbacks.c,v 1.1 2020/11/17 19:33:15 sjmulder Exp $
+
+Support for macOS 11 and Apple Silicon (ARM). Mostly backported from:
+https://github.com/python/cpython/pull/22855
+
+--- Modules/_ctypes/callbacks.c.orig   2020-09-23 12:36:32.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);
Index: pkgsrc/lang/python38/patches/patch-Modules___ctypes_callproc.c
diff -u /dev/null pkgsrc/lang/python38/patches/patch-Modules___ctypes_callproc.c:1.1
--- /dev/null   Tue Nov 17 19:33:15 2020
+++ pkgsrc/lang/python38/patches/patch-Modules___ctypes_callproc.c      Tue Nov 17 19:33:15 2020
@@ -0,0 +1,190 @@
+$NetBSD: patch-Modules___ctypes_callproc.c,v 1.1 2020/11/17 19:33:15 sjmulder Exp $
+
+Support for macOS 11 and Apple Silicon (ARM). Mostly backported from:
+https://github.com/python/cpython/pull/22855
+
+--- Modules/_ctypes/callproc.c.orig    2020-09-23 12:36:32.000000000 +0000
++++ Modules/_ctypes/callproc.c
+@@ -57,6 +57,8 @@
+ #include "Python.h"
+ #include "structmember.h"
+ 
++#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
+@@ -813,7 +819,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;
+@@ -836,14 +843,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)) {
+@@ -1213,9 +1276,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
+@@ -1399,6 +1461,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;
+@@ -1889,6 +1987,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},
+@@ -1911,6 +2011,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},
Index: pkgsrc/lang/python38/patches/patch-Modules___ctypes_ctypes.h
diff -u /dev/null pkgsrc/lang/python38/patches/patch-Modules___ctypes_ctypes.h:1.1
--- /dev/null   Tue Nov 17 19:33:15 2020
+++ pkgsrc/lang/python38/patches/patch-Modules___ctypes_ctypes.h        Tue Nov 17 19:33:15 2020
@@ -0,0 +1,22 @@
+$NetBSD: patch-Modules___ctypes_ctypes.h,v 1.1 2020/11/17 19:33:15 sjmulder Exp $
+
+Support for macOS 11 and Apple Silicon (ARM). Mostly backported from:
+https://github.com/python/cpython/pull/22855
+
+--- Modules/_ctypes/ctypes.h.orig      2020-09-23 12:36:32.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 ~"
Index: pkgsrc/lang/python38/patches/patch-Modules___ctypes_malloc__closure.c
diff -u /dev/null pkgsrc/lang/python38/patches/patch-Modules___ctypes_malloc__closure.c:1.1
--- /dev/null   Tue Nov 17 19:33:15 2020
+++ pkgsrc/lang/python38/patches/patch-Modules___ctypes_malloc__closure.c       Tue Nov 17 19:33:15 2020
@@ -0,0 +1,37 @@
+$NetBSD: patch-Modules___ctypes_malloc__closure.c,v 1.1 2020/11/17 19:33:15 sjmulder Exp $
+
+Support for macOS 11 and Apple Silicon (ARM). Mostly backported from:
+https://github.com/python/cpython/pull/22855
+
+--- Modules/_ctypes/malloc_closure.c.orig      2020-09-23 12:36:32.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();
Index: pkgsrc/lang/python38/patches/patch-Modules___decimal_libmpdec_mpdecimal.h
diff -u /dev/null pkgsrc/lang/python38/patches/patch-Modules___decimal_libmpdec_mpdecimal.h:1.1
--- /dev/null   Tue Nov 17 19:33:15 2020
+++ pkgsrc/lang/python38/patches/patch-Modules___decimal_libmpdec_mpdecimal.h   Tue Nov 17 19:33:15 2020
@@ -0,0 +1,17 @@
+$NetBSD: patch-Modules___decimal_libmpdec_mpdecimal.h,v 1.1 2020/11/17 19:33:15 sjmulder Exp $
+
+Support for macOS 11 and Apple Silicon (ARM). Mostly backported from:
+https://github.com/python/cpython/pull/22855
+
+--- Modules/_decimal/libmpdec/mpdecimal.h.orig 2020-09-23 12:36:32.000000000 +0000
++++ Modules/_decimal/libmpdec/mpdecimal.h
+@@ -135,6 +135,9 @@ const char *mpd_version(void);
+   #elif defined(__x86_64__)
+     #define CONFIG_64
+     #define ASM
++  #elif defined(__aarch64__)
++    #define CONFIG_64
++    #define ANSI
+   #else
+     #error "unknown architecture for universal build."
+   #endif
Index: pkgsrc/lang/python38/patches/patch-Modules_getpath.c
diff -u /dev/null pkgsrc/lang/python38/patches/patch-Modules_getpath.c:1.1
--- /dev/null   Tue Nov 17 19:33:15 2020
+++ pkgsrc/lang/python38/patches/patch-Modules_getpath.c        Tue Nov 17 19:33:15 2020
@@ -0,0 +1,19 @@
+$NetBSD: patch-Modules_getpath.c,v 1.1 2020/11/17 19:33:15 sjmulder Exp $
+
+Support for macOS 11 and Apple Silicon (ARM). Mostly backported from:
+https://github.com/python/cpython/pull/22855
+
+--- Modules/getpath.c.orig     2020-09-23 12:36:32.000000000 +0000
++++ Modules/getpath.c
+@@ -777,11 +777,7 @@ calculate_program_full_path(PyCalculateP
+ 
+ #ifdef __APPLE__
+     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
+ #endif
+ 
+     /* If there is no slash in the argv0 path, then we have to
Index: pkgsrc/lang/python38/patches/patch-Modules_posixmodule.c
diff -u /dev/null pkgsrc/lang/python38/patches/patch-Modules_posixmodule.c:1.1
--- /dev/null   Tue Nov 17 19:33:15 2020
+++ pkgsrc/lang/python38/patches/patch-Modules_posixmodule.c    Tue Nov 17 19:33:15 2020
@@ -0,0 +1,1373 @@
+$NetBSD: patch-Modules_posixmodule.c,v 1.1 2020/11/17 19:33:15 sjmulder Exp $
+
+Support for macOS 11 and Apple Silicon (ARM). Mostly backported from:
+https://github.com/python/cpython/pull/22855
+
+--- Modules/posixmodule.c.orig 2020-09-23 12:36:32.000000000 +0000
++++ Modules/posixmodule.c
+@@ -8,20 +8,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"
+@@ -53,6 +39,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
+@@ -2235,6 +2342,10 @@ posix_do_stat(const char *function_name,
+     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;
+@@ -2261,15 +2372,27 @@ posix_do_stat(const char *function_name,
+     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);
+     }
+@@ -2692,6 +2815,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;
+@@ -2726,17 +2853,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
+ 
+@@ -2923,6 +3073,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))
+@@ -2958,42 +3109,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",
+@@ -3003,10 +3168,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;
+ }
+@@ -3294,6 +3459,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;
+@@ -3302,19 +3471,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;
+@@ -3332,14 +3488,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);
+ 
+@@ -3585,6 +3755,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)) {
+@@ -3619,15 +3792,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 */
+@@ -3750,6 +3951,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)
+@@ -3760,6 +3962,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
+@@ -4077,6 +4284,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) {
+@@ -4093,9 +4303,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);
+@@ -4103,6 +4318,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 */
+@@ -4212,6 +4435,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;
+@@ -4251,13 +4478,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
+@@ -4333,6 +4572,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) {
+@@ -4345,14 +4587,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);
+ 
+@@ -4496,6 +4750,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) {
+@@ -4509,15 +4766,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);
+ 
+@@ -4690,7 +4959,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);
+@@ -4717,11 +4995,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
+ }
+ 
+@@ -4740,11 +5037,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
+ }
+ 
+@@ -4755,7 +5068,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)
+@@ -4964,9 +5285,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)
+@@ -4979,6 +5301,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();
+@@ -5377,6 +5707,9 @@ parse_posix_spawn_flags(const char *func
+     }
+ 
+     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)
+@@ -5385,6 +5718,14 @@ parse_posix_spawn_flags(const char *func
+         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) {
+@@ -7931,16 +8272,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);
+     }
+@@ -8136,6 +8491,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,
+@@ -8198,14 +8556,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
+@@ -8477,6 +8846,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;
+@@ -8501,9 +8873,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 */
+@@ -8511,6 +8889,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);
+@@ -9081,12 +9466,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);
+@@ -9651,6 +10049,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
+@@ -9658,6 +10065,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);
+@@ -10553,13 +10965,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
+@@ -12617,12 +13022,16 @@ DirEntry_fetch_stat(DirEntry *self, int 
+     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
+@@ -13428,6 +13837,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)
+@@ -13436,6 +13846,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
+@@ -14425,137 +14840,210 @@ static struct PyModuleDef posixmodule = 
+ };
+ 
+ 
+-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
++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",
++    { "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 }
+ };
+ 
+ 
+@@ -14564,12 +15052,28 @@ INITFUNC(void)
+ {
+     PyObject *m, *v;
+     PyObject *list;
+-    const char * const *trace;
+ 
+     m = PyModule_Create(&posixmodule);
+     if (m == NULL)
+         return NULL;
+ 
++#if defined(HAVE_PWRITEV)
++    if (HAVE_PWRITEV_RUNTIME) {} else {
++        PyObject* dct = PyModule_GetDict(m);
++
++        if (dct == NULL) {
++            return NULL;
++        }
++
++        if (PyDict_DelItemString(dct, "pwritev") == -1) {
++            PyErr_Clear();
++        }
++        if (PyDict_DelItemString(dct, "preadv") == -1) {
++            PyErr_Clear();
++        }
++    }
++#endif
++
+     /* Initialize environ dictionary */
+     v = convertenviron();
+     Py_XINCREF(v);
+@@ -14676,44 +15180,6 @@ INITFUNC(void)
+     }
+     PyModule_AddObject(m, "uname_result", (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 NULL;
+-        }
+-    }
+-#endif /* HAVE_FSTATVFS */
+-
+-#ifdef HAVE_STATVFS
+-    if (statvfs == NULL) {
+-        if (PyObject_DelAttrString(m, "statvfs") == -1) {
+-            return NULL;
+-        }
+-    }
+-#endif /* HAVE_STATVFS */
+-
+-# ifdef HAVE_LCHOWN
+-    if (lchown == NULL) {
+-        if (PyObject_DelAttrString(m, "lchown") == -1) {
+-            return NULL;
+-        }
+-    }
+-#endif /* HAVE_LCHOWN */
+-
+-
+-#endif /* __APPLE__ */
+-
+     Py_INCREF(TerminalSizeType);
+     PyModule_AddObject(m, "terminal_size", (PyObject*)TerminalSizeType);
+ 
+@@ -14738,14 +15204,17 @@ INITFUNC(void)
+     list = PyList_New(0);
+     if (!list)
+         return NULL;
+-    for (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 NULL;
+         if (PyList_Append(list, unicode))
+             return NULL;
+         Py_DECREF(unicode);
+     }
++
+     PyModule_AddObject(m, "_have_functions", list);
+ 
+     Py_INCREF((PyObject *) &DirEntryType);
Index: pkgsrc/lang/python38/patches/patch-Modules_timemodule.c
diff -u /dev/null pkgsrc/lang/python38/patches/patch-Modules_timemodule.c:1.1
--- /dev/null   Tue Nov 17 19:33:15 2020
+++ pkgsrc/lang/python38/patches/patch-Modules_timemodule.c     Tue Nov 17 19:33:15 2020
@@ -0,0 +1,271 @@
+$NetBSD: patch-Modules_timemodule.c,v 1.1 2020/11/17 19:33:15 sjmulder Exp $
+
+Support for macOS 11 and Apple Silicon (ARM). Mostly backported from:
+https://github.com/python/cpython/pull/22855
+
+--- Modules/timemodule.c.orig  2020-09-23 12:36:32.000000000 +0000
++++ Modules/timemodule.c
+@@ -48,6 +48,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 */
+@@ -146,6 +155,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)
+ {
+@@ -294,6 +313,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
+@@ -1159,31 +1183,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
+ 
+@@ -1346,6 +1374,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)
+ {
+@@ -1377,6 +1415,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)
+ {
+@@ -1407,6 +1454,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
+ 
+ 
+@@ -1456,9 +1508,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 {
+@@ -1757,43 +1819,88 @@ PyInit_time(void)
+     if (m == NULL)
+         return NULL;
+ 
++#if defined(__APPLE__) && defined(HAVE_CLOCK_GETTIME)
++    if (HAVE_CLOCK_GETTIME_RUNTIME) {
++        /* pass: ^^^ cannot use '!' here */
++    } else {
++        PyObject* dct = PyModule_GetDict(m);
++        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(m);
++
++        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(m) < 0) {
+         return NULL;
+     }
+ 
+ #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_SETTIME) || defined(HAVE_CLOCK_GETRES)
++    if (HAVE_CLOCK_GETTIME_RUNTIME) {
+ 
+ #ifdef CLOCK_REALTIME
+-    PyModule_AddIntMacro(m, CLOCK_REALTIME);
++        PyModule_AddIntMacro(m, CLOCK_REALTIME);
+ #endif
++
+ #ifdef CLOCK_MONOTONIC
+-    PyModule_AddIntMacro(m, CLOCK_MONOTONIC);
++        PyModule_AddIntMacro(m, CLOCK_MONOTONIC);
+ #endif
+ #ifdef CLOCK_MONOTONIC_RAW
+-    PyModule_AddIntMacro(m, CLOCK_MONOTONIC_RAW);
++        PyModule_AddIntMacro(m, CLOCK_MONOTONIC_RAW);
+ #endif
++
+ #ifdef CLOCK_HIGHRES
+-    PyModule_AddIntMacro(m, CLOCK_HIGHRES);
++        PyModule_AddIntMacro(m, CLOCK_HIGHRES);
+ #endif
+ #ifdef CLOCK_PROCESS_CPUTIME_ID
+-    PyModule_AddIntMacro(m, CLOCK_PROCESS_CPUTIME_ID);
++        PyModule_AddIntMacro(m, CLOCK_PROCESS_CPUTIME_ID);
+ #endif
++
+ #ifdef CLOCK_THREAD_CPUTIME_ID
+-    PyModule_AddIntMacro(m, CLOCK_THREAD_CPUTIME_ID);
++        PyModule_AddIntMacro(m, CLOCK_THREAD_CPUTIME_ID);
+ #endif
+ #ifdef CLOCK_PROF
+-    PyModule_AddIntMacro(m, CLOCK_PROF);
++        PyModule_AddIntMacro(m, CLOCK_PROF);
+ #endif
+ #ifdef CLOCK_BOOTTIME
+-    PyModule_AddIntMacro(m, CLOCK_BOOTTIME);
++        PyModule_AddIntMacro(m, CLOCK_BOOTTIME);
+ #endif
+ #ifdef CLOCK_UPTIME
+-    PyModule_AddIntMacro(m, CLOCK_UPTIME);
++        PyModule_AddIntMacro(m, CLOCK_UPTIME);
+ #endif
+ #ifdef CLOCK_UPTIME_RAW
+-    PyModule_AddIntMacro(m, CLOCK_UPTIME_RAW);
++        PyModule_AddIntMacro(m, CLOCK_UPTIME_RAW);
+ #endif
++    }
+ 
+ #endif  /* defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_SETTIME) || defined(HAVE_CLOCK_GETRES) */
+ 
Index: pkgsrc/lang/python38/patches/patch-Python_bootstrap__hash.c
diff -u /dev/null pkgsrc/lang/python38/patches/patch-Python_bootstrap__hash.c:1.1
--- /dev/null   Tue Nov 17 19:33:15 2020
+++ pkgsrc/lang/python38/patches/patch-Python_bootstrap__hash.c Tue Nov 17 19:33:15 2020
@@ -0,0 +1,73 @@
+$NetBSD: patch-Python_bootstrap__hash.c,v 1.1 2020/11/17 19:33:15 sjmulder Exp $
+
+Support for macOS 11 and Apple Silicon (ARM). Mostly backported from:
+https://github.com/python/cpython/pull/22855
+
+--- Python/bootstrap_hash.c.orig       2020-09-23 12:36:32.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);
Index: pkgsrc/lang/python38/patches/patch-Python_pytime.c
diff -u /dev/null pkgsrc/lang/python38/patches/patch-Python_pytime.c:1.1
--- /dev/null   Tue Nov 17 19:33:15 2020
+++ pkgsrc/lang/python38/patches/patch-Python_pytime.c  Tue Nov 17 19:33:15 2020
@@ -0,0 +1,73 @@
+$NetBSD: patch-Python_pytime.c,v 1.1 2020/11/17 19:33:15 sjmulder Exp $
+
+Support for macOS 11 and Apple Silicon (ARM). Mostly backported from:
+https://github.com/python/cpython/pull/22855
+
+--- Python/pytime.c.orig       2020-09-23 12:36:32.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() */
+ #ifdef GETTIMEOFDAY_NO_TZ
+@@ -739,6 +759,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;
Index: pkgsrc/lang/python38/patches/patch-configure.ac
diff -u /dev/null pkgsrc/lang/python38/patches/patch-configure.ac:1.1
--- /dev/null   Tue Nov 17 19:33:15 2020
+++ pkgsrc/lang/python38/patches/patch-configure.ac     Tue Nov 17 19:33:15 2020
@@ -0,0 +1,64 @@
+$NetBSD: patch-configure.ac,v 1.1 2020/11/17 19:33:15 sjmulder Exp $
+
+Support for macOS 11 and Apple Silicon (ARM). Mostly backported from:
+https://github.com/python/cpython/pull/22855
+
+--- configure.ac.orig  2020-09-23 12:36:32.000000000 +0000
++++ configure.ac
+@@ -212,7 +212,11 @@ fi
+ AC_SUBST(LIPO_32BIT_FLAGS)
+ AC_MSG_CHECKING(for --with-universal-archs)
+ AC_ARG_WITH(universal-archs,
+-    AS_HELP_STRING([--with-universal-archs=ARCH], [select architectures for universal build ("32-bit", "64-bit", "3-way", "intel", "intel-32", "intel-64", or "all")]),
++    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:
++                    ("universal2", "32-bit", "64-bit", "3-way", "intel", "intel-32", "intel-64", or "all")
++                    see Mac/README.rst]),
+ [
+       UNIVERSAL_ARCHS="$withval"
+ ],
+@@ -1843,6 +1847,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"
+@@ -1864,7 +1873,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
+ 
+@@ -2441,6 +2450,9 @@ case $ac_sys_system/$ac_sys_release in
+               ;;
+       ppc)
+               MACOSX_DEFAULT_ARCH="ppc64"
++              ;;
++      arm64)
++              MACOSX_DEFAULT_ARCH="arm64"
+               ;;
+       *)
+               AC_MSG_ERROR([Unexpected output of 'arch' on OSX])
+@@ -3666,6 +3678,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([[



Home | Main Index | Thread Index | Old Index