From 5d4878c1c1a3066d310402136a46730f8efec4eb Mon Sep 17 00:00:00 2001 From: Lawrence D'Anna <lawrence_danna@apple.com> Date: Mon, 20 Jul 2020 22:54:14 -0700 Subject: [PATCH 1/7] add runtime checks for MACOSX_DEPLOYMENT_TARGET=10.10 In order to support a universal2 build, supporitng Mac OS 11 on arm64 and Mac OS on x86_64 going back to 10.10, we need to add in runtime checks for functions that will be detected as present by autoconf, because they are in the SDK, but which did not exist in Mac OS 10.10. This fixes all the instances of -WWunguarded-availability-new when building with MACOSX_DEPLOYMENT_TARGET=10.10 --- Modules/posixmodule.c | 308 +++++++++++++++++++++++++--------------- Modules/timemodule.c | 300 ++++++++++++++++++++++++-------------- Python/bootstrap_hash.c | 30 +++- Python/pytime.c | 89 ++++++------ configure | 35 +++++ configure.ac | 13 ++ pyconfig.h.in | 3 + 7 files changed, 513 insertions(+), 265 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index efd99544f5a997..20238ddef10145 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -79,6 +79,28 @@ corresponding Unix manual entries for more information on calls."); # include <sys/stat.h> #endif /* HAVE_SYS_STAT_H */ +#if defined(__APPLE__) +#include <TargetConditionals.h> +#endif + +#if defined(__APPLE__) && HAVE_BUILTIN_AVAILABLE && !(TARGET_OS_OSX && __arm64__) +#define HAVE_UTIMENSAT_RUNTIME __builtin_available(macos 10.13, ios 11, tvos 11, watchos 4, *) +#define HAVE_FUTIMENS_RUNTIME __builtin_available(macos 10.13, ios 11, tvos 11, watchos 4, *) +#define HAVE_PREADV_RUNTIME __builtin_available(macos 10.16, ios 14, tvos 14, watchos 7, *) +#define HAVE_PWRITEV_RUNTIME __builtin_available(macos 10.16, ios 14, tvos 14, watchos 7, *) +#define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macos 10.15, ios 13, tvos 13, watchos 6, *) +#else +#define HAVE_UTIMENSAT_RUNTIME 1 +#define HAVE_FUTIMENS_RUNTIME 1 +#define HAVE_PREADV_RUNTIME 1 +#define HAVE_PWRITEV_RUNTIME 1 +#define HAVE_POSIX_SPAWN_SETSID_RUNTIME 1 +#endif + +#if defined(__APPLE__) && TARGET_OS_OSX && __arm64__ && __clang__ +#pragma clang diagnostic ignored "-Wunguarded-availability-new" +#endif + #ifdef HAVE_SYS_WAIT_H # include <sys/wait.h> // WNOHANG #endif @@ -4826,9 +4848,14 @@ static int utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks) { #ifdef HAVE_UTIMENSAT - int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW; - UTIME_TO_TIMESPEC; - return utimensat(dir_fd, path, time, flags); + if (HAVE_UTIMENSAT_RUNTIME) { + int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW; + UTIME_TO_TIMESPEC; + return utimensat(dir_fd, path, time, flags); + } else { + PyErr_SetString(PyExc_NotImplementedError, "utimensat is not available"); + return -1; + } #elif defined(HAVE_FUTIMESAT) UTIME_TO_TIMEVAL; /* @@ -4841,7 +4868,16 @@ utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks) #endif } - #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter +static int +utime_dir_fd_converter(PyObject *o, void *p) +{ + if (HAVE_UTIMENSAT_RUNTIME) + return dir_fd_converter(o,p); + else + return dir_fd_unavailable(o, p); +} + + #define FUTIMENSAT_DIR_FD_CONVERTER utime_dir_fd_converter #else #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable #endif @@ -4852,12 +4888,15 @@ static int utime_fd(utime_t *ut, int fd) { #ifdef HAVE_FUTIMENS - UTIME_TO_TIMESPEC; - return futimens(fd, time); -#else - UTIME_TO_TIMEVAL; - return futimes(fd, time); + if (HAVE_FUTIMENS_RUNTIME) { + UTIME_TO_TIMESPEC; + return futimens(fd, time); + } else #endif + { + UTIME_TO_TIMEVAL; + return futimes(fd, time); + } } #define PATH_UTIME_HAVE_FD 1 @@ -4875,12 +4914,15 @@ 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 - UTIME_TO_TIMEVAL; - return lutimes(path, time); + if (HAVE_FUTIMENS_RUNTIME) { + UTIME_TO_TIMESPEC; + return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW); + } else #endif + { + UTIME_TO_TIMEVAL; + return lutimes(path, time); + } } #endif @@ -4891,9 +4933,12 @@ static int utime_default(utime_t *ut, const char *path) { #ifdef HAVE_UTIMENSAT - UTIME_TO_TIMESPEC; - return utimensat(DEFAULT_DIR_FD, path, time, 0); -#elif defined(HAVE_UTIMES) + if (HAVE_UTIMENSAT_RUNTIME) { + UTIME_TO_TIMESPEC; + return utimensat(DEFAULT_DIR_FD, path, time, 0); + } +#endif +#if defined(HAVE_UTIMES) UTIME_TO_TIMEVAL; return utimes(path, time); #elif defined(HAVE_UTIME_H) @@ -5513,7 +5558,12 @@ parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpg if (setsid) { #ifdef POSIX_SPAWN_SETSID - all_flags |= POSIX_SPAWN_SETSID; + if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) { + all_flags |= POSIX_SPAWN_SETSID; + } else { + argument_unavailable_error(func_name, "setsid"); + return -1; + } #elif defined(POSIX_SPAWN_SETSID_NP) all_flags |= POSIX_SPAWN_SETSID_NP; #else @@ -9255,59 +9305,64 @@ os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, int flags) /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/ { - Py_ssize_t cnt, n; - int async_err = 0; - struct iovec *iov; - Py_buffer *buf; + if (HAVE_PREADV_RUNTIME) { + Py_ssize_t cnt, n; + int async_err = 0; + struct iovec *iov; + Py_buffer *buf; - if (!PySequence_Check(buffers)) { - PyErr_SetString(PyExc_TypeError, - "preadv2() arg 2 must be a sequence"); - return -1; - } + if (!PySequence_Check(buffers)) { + PyErr_SetString(PyExc_TypeError, + "preadv2() arg 2 must be a sequence"); + return -1; + } - cnt = PySequence_Size(buffers); - if (cnt < 0) { - return -1; - } + cnt = PySequence_Size(buffers); + if (cnt < 0) { + return -1; + } -#ifndef HAVE_PREADV2 - if(flags != 0) { - argument_unavailable_error("preadv2", "flags"); - return -1; - } -#endif + #ifndef HAVE_PREADV2 + if(flags != 0) { + argument_unavailable_error("preadv2", "flags"); + return -1; + } + #endif - if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) { - return -1; - } -#ifdef HAVE_PREADV2 - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - n = preadv2(fd, iov, cnt, offset, flags); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); -#else - do { - 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())); -#endif + if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) { + return -1; + } + #ifdef HAVE_PREADV2 + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + n = preadv2(fd, iov, cnt, offset, flags); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + #else + do { + 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())); + #endif - iov_cleanup(iov, buf, cnt); - if (n < 0) { - if (!async_err) { - posix_error(); + iov_cleanup(iov, buf, cnt); + if (n < 0) { + if (!async_err) { + posix_error(); + } + return -1; } + + return n; + } else { + PyErr_SetString(PyExc_NotImplementedError, "preadv is not available"); return -1; } - - return n; } #endif /* HAVE_PREADV */ @@ -9850,60 +9905,65 @@ os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, int flags) /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/ { - Py_ssize_t cnt; - Py_ssize_t result; - int async_err = 0; - struct iovec *iov; - Py_buffer *buf; + if (HAVE_PWRITEV_RUNTIME) { + Py_ssize_t cnt; + Py_ssize_t result; + int async_err = 0; + struct iovec *iov; + Py_buffer *buf; - if (!PySequence_Check(buffers)) { - PyErr_SetString(PyExc_TypeError, - "pwritev() arg 2 must be a sequence"); - return -1; - } + if (!PySequence_Check(buffers)) { + PyErr_SetString(PyExc_TypeError, + "pwritev() arg 2 must be a sequence"); + return -1; + } - cnt = PySequence_Size(buffers); - if (cnt < 0) { - return -1; - } + cnt = PySequence_Size(buffers); + if (cnt < 0) { + return -1; + } -#ifndef HAVE_PWRITEV2 - if(flags != 0) { - argument_unavailable_error("pwritev2", "flags"); - return -1; - } -#endif + #ifndef HAVE_PWRITEV2 + if(flags != 0) { + argument_unavailable_error("pwritev2", "flags"); + return -1; + } + #endif - if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { - return -1; - } -#ifdef HAVE_PWRITEV2 - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - result = pwritev2(fd, iov, cnt, offset, flags); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); -#else - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - result = pwritev(fd, iov, cnt, offset); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); -#endif + if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { + return -1; + } + #ifdef HAVE_PWRITEV2 + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + result = pwritev2(fd, iov, cnt, offset, flags); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + #else + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + result = pwritev(fd, iov, cnt, offset); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + #endif - iov_cleanup(iov, buf, cnt); - if (result < 0) { - if (!async_err) { - posix_error(); + iov_cleanup(iov, buf, cnt); + if (result < 0) { + if (!async_err) { + posix_error(); + } + return -1; } + + return result; + } else { + PyErr_SetString(PyExc_NotImplementedError, "preadv is not available"); return -1; } - - return result; } #endif /* HAVE_PWRITEV */ @@ -14156,9 +14216,7 @@ static PyMethodDef posix_methods[] = { OS_READ_METHODDEF OS_READV_METHODDEF OS_PREAD_METHODDEF - OS_PREADV_METHODDEF OS_WRITE_METHODDEF - OS_WRITEV_METHODDEF OS_PWRITE_METHODDEF OS_PWRITEV_METHODDEF OS_SENDFILE_METHODDEF @@ -14228,6 +14286,9 @@ static PyMethodDef posix_methods[] = { OS__ADD_DLL_DIRECTORY_METHODDEF OS__REMOVE_DLL_DIRECTORY_METHODDEF OS_WAITSTATUS_TO_EXITCODE_METHODDEF + + OS_PREADV_METHODDEF + OS_WRITEV_METHODDEF {NULL, NULL} /* Sentinel */ }; @@ -15070,6 +15131,10 @@ posixmodule_exec(PyObject *m) return -1; } for (const char * const *trace = have_functions; *trace; trace++) { + if (HAVE_UTIMENSAT_RUNTIME) {} else if (0==strcmp(*trace, "HAVE_UTIMENSAT")) continue; + if (HAVE_FUTIMENS_RUNTIME) {} else if (0==strcmp(*trace, "HAVE_FUTIMENS")) continue; + if (HAVE_PREADV_RUNTIME) {} else if (0==strcmp(*trace, "HAVE_PREADV")) continue; + if (HAVE_PWRITEV_RUNTIME) {} else if (0==strcmp(*trace, "HAVE_PWRITEV")) continue; PyObject *unicode = PyUnicode_DecodeASCII(*trace, strlen(*trace), NULL); if (!unicode) return -1; @@ -15100,9 +15165,30 @@ static struct PyModuleDef posixmodule = { .m_free = _posix_free, }; +static void +delete_method(const char *name) +{ + int last_method_index = (sizeof(posix_methods) / sizeof(posix_methods[0])) - 1; + for (int i = last_method_index; i >= 0; i--) { + if ( posix_methods[i].ml_name && 0==strcmp(posix_methods[i].ml_name, name)) { + for (int j = i; posix_methods[j].ml_name != NULL; j++) { + posix_methods[j] = posix_methods[j+1]; + } + break; + } + } +} + + PyMODINIT_FUNC INITFUNC(void) { + #ifdef HAVE_PREADV + if (HAVE_PREADV_RUNTIME) {} else { delete_method("preadv"); } + #endif + #ifdef HAVE_PWRITEV + if (HAVE_PWRITEV_RUNTIME) {} else { delete_method("pwritev"); } + #endif return PyModuleDef_Init(&posixmodule); } diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 8a4d149befb52a..96e2486f27da27 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -51,6 +51,20 @@ #define _Py_tzname tzname #endif +#if defined(__APPLE__) +#include <TargetConditionals.h> +#endif + +#if defined(__APPLE__) && HAVE_BUILTIN_AVAILABLE && !(TARGET_OS_OSX && __arm64__) +#define HAVE_CLOCK_GETTIME_RUNTIME __builtin_available(macos 10.12, ios 10, tvos 10, watchos 3, *) +#define HAVE_CLOCK_SETTIME_RUNTIME __builtin_available(macos 10.12, ios 10, tvos 10, watchos 3, *) +#define HAVE_CLOCK_GETRES_RUNTIME __builtin_available(macos 10.12, ios 10, tvos 10, watchos 3, *) +#else +#define HAVE_CLOCK_GETTIME_RUNTIME 1 +#define HAVE_CLOCK_SETTIME_RUNTIME 1 +#define HAVE_CLOCK_GETRES_RUNTIME 1 +#endif + #define SEC_TO_NS (1000 * 1000 * 1000) /* Forward declarations */ @@ -152,25 +166,30 @@ perf_counter(_Py_clock_info_t *info) static PyObject * time_clock_gettime(PyObject *self, PyObject *args) { - int ret; - struct timespec tp; - -#if defined(_AIX) && (SIZEOF_LONG == 8) - long clk_id; - if (!PyArg_ParseTuple(args, "l:clock_gettime", &clk_id)) { -#else - int clk_id; - if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id)) { -#endif - return NULL; - } + if (HAVE_CLOCK_GETTIME_RUNTIME) { + int ret; + struct timespec tp; + + #if defined(_AIX) && (SIZEOF_LONG == 8) + long clk_id; + if (!PyArg_ParseTuple(args, "l:clock_gettime", &clk_id)) { + #else + int clk_id; + if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id)) { + #endif + return NULL; + } - ret = clock_gettime((clockid_t)clk_id, &tp); - if (ret != 0) { - PyErr_SetFromErrno(PyExc_OSError); + ret = clock_gettime((clockid_t)clk_id, &tp); + if (ret != 0) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); + } else { + PyErr_SetString(PyExc_NotImplementedError, "clock_gettime is not available"); return NULL; } - return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); } PyDoc_STRVAR(clock_gettime_doc, @@ -181,24 +200,29 @@ Return the time of the specified clock clk_id."); static PyObject * time_clock_gettime_ns(PyObject *self, PyObject *args) { - int ret; - int clk_id; - struct timespec ts; - _PyTime_t t; + if (HAVE_CLOCK_GETTIME_RUNTIME) { + int ret; + int clk_id; + struct timespec ts; + _PyTime_t t; - if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id)) { + return NULL; + } - ret = clock_gettime((clockid_t)clk_id, &ts); - if (ret != 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - if (_PyTime_FromTimespec(&t, &ts) < 0) { + ret = clock_gettime((clockid_t)clk_id, &ts); + if (ret != 0) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + if (_PyTime_FromTimespec(&t, &ts) < 0) { + return NULL; + } + return _PyTime_AsNanosecondsObject(t); + } else { + PyErr_SetString(PyExc_NotImplementedError, "clock_gettime is not available"); return NULL; } - return _PyTime_AsNanosecondsObject(t); } PyDoc_STRVAR(clock_gettime_ns_doc, @@ -211,27 +235,32 @@ Return the time of the specified clock clk_id as nanoseconds."); static PyObject * time_clock_settime(PyObject *self, PyObject *args) { - int clk_id; - PyObject *obj; - _PyTime_t t; - struct timespec tp; - int ret; - - if (!PyArg_ParseTuple(args, "iO:clock_settime", &clk_id, &obj)) - return NULL; + if (HAVE_CLOCK_SETTIME_RUNTIME) { + int clk_id; + PyObject *obj; + _PyTime_t t; + struct timespec tp; + int ret; + + if (!PyArg_ParseTuple(args, "iO:clock_settime", &clk_id, &obj)) + return NULL; - if (_PyTime_FromSecondsObject(&t, obj, _PyTime_ROUND_FLOOR) < 0) - return NULL; + if (_PyTime_FromSecondsObject(&t, obj, _PyTime_ROUND_FLOOR) < 0) + return NULL; - if (_PyTime_AsTimespec(t, &tp) == -1) - return NULL; + if (_PyTime_AsTimespec(t, &tp) == -1) + return NULL; - ret = clock_settime((clockid_t)clk_id, &tp); - if (ret != 0) { - PyErr_SetFromErrno(PyExc_OSError); + ret = clock_settime((clockid_t)clk_id, &tp); + if (ret != 0) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + Py_RETURN_NONE; + } else { + PyErr_SetString(PyExc_NotImplementedError, "clock_settime is not available"); return NULL; } - Py_RETURN_NONE; } PyDoc_STRVAR(clock_settime_doc, @@ -242,29 +271,34 @@ Set the time of the specified clock clk_id."); static PyObject * time_clock_settime_ns(PyObject *self, PyObject *args) { - int clk_id; - PyObject *obj; - _PyTime_t t; - struct timespec ts; - int ret; - - if (!PyArg_ParseTuple(args, "iO:clock_settime", &clk_id, &obj)) { - return NULL; - } + if (HAVE_CLOCK_SETTIME_RUNTIME) { + int clk_id; + PyObject *obj; + _PyTime_t t; + struct timespec ts; + int ret; + + if (!PyArg_ParseTuple(args, "iO:clock_settime", &clk_id, &obj)) { + return NULL; + } - if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { - return NULL; - } - if (_PyTime_AsTimespec(t, &ts) == -1) { - return NULL; - } + if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { + return NULL; + } + if (_PyTime_AsTimespec(t, &ts) == -1) { + return NULL; + } - ret = clock_settime((clockid_t)clk_id, &ts); - if (ret != 0) { - PyErr_SetFromErrno(PyExc_OSError); + ret = clock_settime((clockid_t)clk_id, &ts); + if (ret != 0) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + Py_RETURN_NONE; + } else { + PyErr_SetString(PyExc_NotImplementedError, "clock_settime is not available"); return NULL; } - Py_RETURN_NONE; } PyDoc_STRVAR(clock_settime_ns_doc, @@ -277,20 +311,25 @@ Set the time of the specified clock clk_id with nanoseconds."); static PyObject * time_clock_getres(PyObject *self, PyObject *args) { - int ret; - int clk_id; - struct timespec tp; + if (HAVE_CLOCK_GETRES_RUNTIME) { + int ret; + int clk_id; + struct timespec tp; - if (!PyArg_ParseTuple(args, "i:clock_getres", &clk_id)) - return NULL; + if (!PyArg_ParseTuple(args, "i:clock_getres", &clk_id)) + return NULL; - ret = clock_getres((clockid_t)clk_id, &tp); - if (ret != 0) { - PyErr_SetFromErrno(PyExc_OSError); + ret = clock_getres((clockid_t)clk_id, &tp); + if (ret != 0) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); + } else { + PyErr_SetString(PyExc_NotImplementedError, "clock_getres is not available"); return NULL; } - - return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); } PyDoc_STRVAR(clock_getres_doc, @@ -1170,23 +1209,25 @@ _PyTime_GetProcessTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) 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 (HAVE_CLOCK_GETTIME_RUNTIME) { + 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 @@ -1309,6 +1350,7 @@ sum of the kernel and user-space CPU time."); #if defined(MS_WINDOWS) #define HAVE_THREAD_TIME +#define HAVE_THREAD_TIME_RUNTIME 1 static int _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) { @@ -1349,6 +1391,7 @@ _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) #elif defined(_AIX) #define HAVE_THREAD_TIME +#define HAVE_THREAD_TIME_RUNTIME 1 static int _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) { @@ -1373,6 +1416,7 @@ _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) #elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID) #define HAVE_THREAD_TIME +#define HAVE_THREAD_TIME_RUNTIME HAVE_CLOCK_GETTIME_RUNTIME static int _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) { @@ -1380,10 +1424,16 @@ _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) const clockid_t clk_id = CLOCK_THREAD_CPUTIME_ID; const char *function = "clock_gettime(CLOCK_THREAD_CPUTIME_ID)"; - if (clock_gettime(clk_id, &ts)) { - PyErr_SetFromErrno(PyExc_OSError); + if (HAVE_CLOCK_GETTIME_RUNTIME) { + if (clock_gettime(clk_id, &ts)) { + PyErr_SetFromErrno(PyExc_OSError); + return -1; + } + } else { + PyErr_SetString(PyExc_NotImplementedError, "clock_gettime is not available"); return -1; } + if (info) { struct timespec res; info->implementation = function; @@ -1694,17 +1744,6 @@ init_timezone(PyObject *m) static PyMethodDef time_methods[] = { {"time", time_time, METH_NOARGS, time_doc}, {"time_ns", time_time_ns, METH_NOARGS, time_ns_doc}, -#ifdef HAVE_CLOCK_GETTIME - {"clock_gettime", time_clock_gettime, METH_VARARGS, clock_gettime_doc}, - {"clock_gettime_ns",time_clock_gettime_ns, METH_VARARGS, clock_gettime_ns_doc}, -#endif -#ifdef HAVE_CLOCK_SETTIME - {"clock_settime", time_clock_settime, METH_VARARGS, clock_settime_doc}, - {"clock_settime_ns",time_clock_settime_ns, METH_VARARGS, clock_settime_ns_doc}, -#endif -#ifdef HAVE_CLOCK_GETRES - {"clock_getres", time_clock_getres, METH_VARARGS, clock_getres_doc}, -#endif #ifdef HAVE_PTHREAD_GETCPUCLOCKID {"pthread_getcpuclockid", time_pthread_getcpuclockid, METH_VARARGS, pthread_getcpuclockid_doc}, #endif @@ -1727,13 +1766,24 @@ static PyMethodDef time_methods[] = { {"monotonic_ns", time_monotonic_ns, METH_NOARGS, monotonic_ns_doc}, {"process_time", time_process_time, METH_NOARGS, process_time_doc}, {"process_time_ns", time_process_time_ns, METH_NOARGS, process_time_ns_doc}, + {"perf_counter", time_perf_counter, METH_NOARGS, perf_counter_doc}, + {"perf_counter_ns", time_perf_counter_ns, METH_NOARGS, perf_counter_ns_doc}, + {"get_clock_info", time_get_clock_info, METH_VARARGS, get_clock_info_doc}, +#ifdef HAVE_CLOCK_GETTIME + {"clock_gettime", time_clock_gettime, METH_VARARGS, clock_gettime_doc}, + {"clock_gettime_ns",time_clock_gettime_ns, METH_VARARGS, clock_gettime_ns_doc}, +#endif +#ifdef HAVE_CLOCK_SETTIME + {"clock_settime", time_clock_settime, METH_VARARGS, clock_settime_doc}, + {"clock_settime_ns",time_clock_settime_ns, METH_VARARGS, clock_settime_ns_doc}, +#endif #ifdef HAVE_THREAD_TIME {"thread_time", time_thread_time, METH_NOARGS, thread_time_doc}, {"thread_time_ns", time_thread_time_ns, METH_NOARGS, thread_time_ns_doc}, #endif - {"perf_counter", time_perf_counter, METH_NOARGS, perf_counter_doc}, - {"perf_counter_ns", time_perf_counter_ns, METH_NOARGS, perf_counter_ns_doc}, - {"get_clock_info", time_get_clock_info, METH_VARARGS, get_clock_info_doc}, +#ifdef HAVE_CLOCK_GETRES + {"clock_getres", time_clock_getres, METH_VARARGS, clock_getres_doc}, +#endif {NULL, NULL} /* sentinel */ }; @@ -1874,9 +1924,49 @@ static struct PyModuleDef timemodule = { NULL }; +static void +delete_method(const char *name) +{ + for (int i = 0; time_methods[i].ml_name != NULL; i++) { + if ( 0==strcmp(time_methods[i].ml_name, name)) { + for (int j = i; time_methods[j].ml_name != NULL; j++) { + time_methods[j] = time_methods[j+1]; + } + break; + } + } +} + PyMODINIT_FUNC PyInit_time(void) { + #ifdef HAVE_CLOCK_GETTIME + if (HAVE_CLOCK_GETTIME_RUNTIME) {} else { + delete_method("clock_gettime"); + delete_method("clock_gettime_ns"); + } + #endif + + #ifdef HAVE_CLOCK_SETTIME + if (HAVE_CLOCK_SETTIME_RUNTIME) {} else { + delete_method("clock_settime"); + delete_method("clock_settime_ns"); + } + #endif + + #ifdef HAVE_CLOCK_GETRES + if (HAVE_CLOCK_GETRES_RUNTIME) {} else { + delete_method("clock_getres"); + } + #endif + + #ifdef HAVE_THREAD_TIME + if (HAVE_THREAD_TIME_RUNTIME) {} else { + delete_method("thread_time"); + delete_method("thread_time_ns"); + } + #endif + return PyModuleDef_Init(&timemodule); } diff --git a/Python/bootstrap_hash.c b/Python/bootstrap_hash.c index 47369305ee88e9..0dc86e2cf9f5f4 100644 --- a/Python/bootstrap_hash.c +++ b/Python/bootstrap_hash.c @@ -31,6 +31,16 @@ int _Py_HashSecret_Initialized = 0; static int _Py_HashSecret_Initialized = 0; #endif +#if defined(__APPLE__) +#include <TargetConditionals.h> +#endif + +#if defined(__APPLE__) && HAVE_BUILTIN_AVAILABLE && !(TARGET_OS_OSX && __arm64__) +#define HAVE_GETENTROPY_RUNTIME __builtin_available(macos 10.12, ios 10, tvos 10, watchos 3, *) +#else +#define HAVE_GETENTROPY_RUNTIME 1 +#endif + #ifdef MS_WINDOWS static HCRYPTPROV hCryptProv = 0; @@ -225,13 +235,19 @@ py_getentropy(char *buffer, Py_ssize_t size, int raise) Py_ssize_t len = Py_MIN(size, 256); int res; - if (raise) { - Py_BEGIN_ALLOW_THREADS - res = getentropy(buffer, len); - Py_END_ALLOW_THREADS - } - else { - res = getentropy(buffer, len); + + if (HAVE_GETENTROPY_RUNTIME) { + if (raise) { + Py_BEGIN_ALLOW_THREADS + res = getentropy(buffer, len); + Py_END_ALLOW_THREADS + } + else { + res = getentropy(buffer, len); + } + } else { + getentropy_works = 0; + return 0; } if (res < 0) { diff --git a/Python/pytime.c b/Python/pytime.c index b121b432f428d7..9757e5abc8e8a1 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -7,6 +7,12 @@ #include <mach/mach_time.h> /* mach_absolute_time(), mach_timebase_info() */ #endif +#if defined(__APPLE__) && HAVE_BUILTIN_AVAILABLE && !defined(__arm64__) +#define HAVE_CLOCK_GETTIME_RUNTIME __builtin_available(macos 10.12, ios 10, tvos 10, watchos 3, *) +#else +#define HAVE_CLOCK_GETTIME_RUNTIME 1 +#endif + #define _PyTime_check_mul_overflow(a, b) \ (assert(b > 0), \ (_PyTime_t)(a) < _PyTime_MIN / (_PyTime_t)(b) \ @@ -683,59 +689,58 @@ pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise) #else /* MS_WINDOWS */ int err; -#ifdef HAVE_CLOCK_GETTIME - struct timespec ts; -#else - struct timeval tv; -#endif assert(info == NULL || raise); #ifdef HAVE_CLOCK_GETTIME - err = clock_gettime(CLOCK_REALTIME, &ts); - if (err) { - if (raise) { - PyErr_SetFromErrno(PyExc_OSError); + if (HAVE_CLOCK_GETTIME_RUNTIME) { + struct timespec ts; + err = clock_gettime(CLOCK_REALTIME, &ts); + if (err) { + if (raise) { + PyErr_SetFromErrno(PyExc_OSError); + } + return -1; + } + if (pytime_fromtimespec(tp, &ts, raise) < 0) { + return -1; } - return -1; - } - if (pytime_fromtimespec(tp, &ts, raise) < 0) { - return -1; - } - if (info) { - struct timespec res; - info->implementation = "clock_gettime(CLOCK_REALTIME)"; - info->monotonic = 0; - info->adjustable = 1; - if (clock_getres(CLOCK_REALTIME, &res) == 0) { - info->resolution = res.tv_sec + res.tv_nsec * 1e-9; + if (info) { + struct timespec res; + info->implementation = "clock_gettime(CLOCK_REALTIME)"; + info->monotonic = 0; + info->adjustable = 1; + if (clock_getres(CLOCK_REALTIME, &res) == 0) { + info->resolution = res.tv_sec + res.tv_nsec * 1e-9; + } + else { + info->resolution = 1e-9; + } } - else { - info->resolution = 1e-9; + } else +#endif /* HAVE_CLOCK_GETTIME */ + { + struct timeval tv; + /* test gettimeofday() */ + err = gettimeofday(&tv, (struct timezone *)NULL); + if (err) { + if (raise) { + PyErr_SetFromErrno(PyExc_OSError); + } + return -1; } - } -#else /* HAVE_CLOCK_GETTIME */ - - /* test gettimeofday() */ - err = gettimeofday(&tv, (struct timezone *)NULL); - if (err) { - if (raise) { - PyErr_SetFromErrno(PyExc_OSError); + if (pytime_fromtimeval(tp, &tv, raise) < 0) { + return -1; } - return -1; - } - if (pytime_fromtimeval(tp, &tv, raise) < 0) { - return -1; - } - if (info) { - info->implementation = "gettimeofday()"; - info->resolution = 1e-6; - info->monotonic = 0; - info->adjustable = 1; + if (info) { + info->implementation = "gettimeofday()"; + info->resolution = 1e-6; + info->monotonic = 0; + info->adjustable = 1; + } } -#endif /* !HAVE_CLOCK_GETTIME */ #endif /* !MS_WINDOWS */ return 0; } diff --git a/configure b/configure index 5024860ca4395a..ebdd1cfeed261d 100755 --- a/configure +++ b/configure @@ -12190,6 +12190,41 @@ $as_echo "yes" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if the compiler supports __builtin_available" >&5 +$as_echo_n "checking to see if the compiler supports __builtin_available... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ + + if (__builtin_available(macOS 10.8, iOS 5.0, *)) {} + + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +cat >>confdefs.h <<_ACEOF +#define HAVE_BUILTIN_AVAILABLE 1 +_ACEOF + + +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 + for ac_prog in true do # Extract the first word of "$ac_prog", so it can be a program name with args. diff --git a/configure.ac b/configure.ac index 5a3e340aa3e72b..6df35971dec8d3 100644 --- a/configure.ac +++ b/configure.ac @@ -3825,6 +3825,19 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ AC_MSG_RESULT(yes) ]) +AC_MSG_CHECKING([to see if the compiler supports __builtin_available]) +AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([[]],[[ + if (__builtin_available(macOS 10.8, iOS 5.0, *)) {} + ]]) + ],[ + AC_MSG_RESULT([yes]) + AC_DEFINE_UNQUOTED(HAVE_BUILTIN_AVAILABLE, 1, + [Define to 1 if the compiler supports __builtin_available]) + ],[ + AC_MSG_RESULT([no]) +]) + dnl check for true AC_CHECK_PROGS(TRUE, true, /bin/true) diff --git a/pyconfig.h.in b/pyconfig.h.in index bc906a869b623e..e602a4a9f4bdc1 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -115,6 +115,9 @@ /* Define if `unsetenv` does not return an int. */ #undef HAVE_BROKEN_UNSETENV +#undef HAVE_BUILTIN_AVAILABLE +/* Define to 1 if the compiler supports __builtin_available */ + /* Has builtin atomics */ #undef HAVE_BUILTIN_ATOMIC From 5fdd1b93c8dae8931c646f05b4058b75cb56ed28 Mon Sep 17 00:00:00 2001 From: Lawrence D'Anna <lawrence_danna@apple.com> Date: Mon, 20 Jul 2020 22:54:14 -0700 Subject: [PATCH 2/7] fix test_getgroups() on Mac OS for users with large numbers of groups --- Modules/posixmodule.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 20238ddef10145..674b47e3a1a601 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -7218,7 +7218,8 @@ os_getgroups_impl(PyObject *module) * always first call getgroups with length 0 to get the actual number * of groups. */ - n = getgroups(0, NULL); + /* getgroups will not fill the last slot with a gid, so we need +1 */ + n = getgroups(0, NULL) + 1; if (n < 0) { return posix_error(); } else if (n <= MAX_GROUPS) { From fcf4b172dfbbd24eaf46724be9286bc8e223b6d2 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Tue, 21 Jul 2020 06:03:20 +0000 Subject: [PATCH 3/7] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Misc/NEWS.d/next/macOS/2020-07-21-06-03-19.bpo-41100.6Et7be.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/macOS/2020-07-21-06-03-19.bpo-41100.6Et7be.rst diff --git a/Misc/NEWS.d/next/macOS/2020-07-21-06-03-19.bpo-41100.6Et7be.rst b/Misc/NEWS.d/next/macOS/2020-07-21-06-03-19.bpo-41100.6Et7be.rst new file mode 100644 index 00000000000000..b03a6febac362f --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2020-07-21-06-03-19.bpo-41100.6Et7be.rst @@ -0,0 +1 @@ +Add runtime checks so python can be built for Mac OS 10.10 using the latest Xcode \ No newline at end of file From 57c7b6e9bebc8ef41497bed17345484878aa98f0 Mon Sep 17 00:00:00 2001 From: Lawrence D'Anna <lawrence_danna@apple.com> Date: Tue, 21 Jul 2020 14:45:33 -0700 Subject: [PATCH 4/7] fixup --- Include/py_available.h | 53 +++++++++++++++++++++++++++++++++++++++++ Modules/posixmodule.c | 32 +++---------------------- Modules/timemodule.c | 24 ++----------------- Python/bootstrap_hash.c | 11 +-------- Python/pytime.c | 7 +----- configure | 35 --------------------------- configure.ac | 13 ---------- pyconfig.h.in | 3 --- 8 files changed, 60 insertions(+), 118 deletions(-) create mode 100644 Include/py_available.h diff --git a/Include/py_available.h b/Include/py_available.h new file mode 100644 index 00000000000000..32a6c1c0ea6567 --- /dev/null +++ b/Include/py_available.h @@ -0,0 +1,53 @@ +#ifndef Py_AVAILABLE_H +#define Py_AVAILABLE_H + +#include "Python.h" + +#ifdef __has_builtin +#if __has_builtin(__builtin_available) +#define HAVE_BUILTIN_AVAILABLE 1 +#endif +#endif + +#if __APPLE__ +#include <TargetConditionals.h> +#endif + +#if __APPLE__ && HAVE_BUILTIN_AVAILABLE && !(TARGET_OS_OSX && __arm64__) +#define HAVE_UTIMENSAT_RUNTIME __builtin_available(macos 10.13, ios 11, tvos 11, watchos 4, *) +#define HAVE_FUTIMENS_RUNTIME __builtin_available(macos 10.13, ios 11, tvos 11, watchos 4, *) +#define HAVE_PREADV_RUNTIME __builtin_available(macos 11.0, ios 14, tvos 14, watchos 7, *) +#define HAVE_PWRITEV_RUNTIME __builtin_available(macos 11.0, ios 14, tvos 14, watchos 7, *) +#define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macos 10.15, ios 13, tvos 13, watchos 6, *) +#define HAVE_CLOCK_GETTIME_RUNTIME __builtin_available(macos 10.12, ios 10, tvos 10, watchos 3, *) +#define HAVE_CLOCK_SETTIME_RUNTIME __builtin_available(macos 10.12, ios 10, tvos 10, watchos 3, *) +#define HAVE_CLOCK_GETRES_RUNTIME __builtin_available(macos 10.12, ios 10, tvos 10, watchos 3, *) +#define HAVE_GETENTROPY_RUNTIME __builtin_available(macos 10.12, ios 10, tvos 10, watchos 3, *) +#else +#define HAVE_UTIMENSAT_RUNTIME 1 +#define HAVE_FUTIMENS_RUNTIME 1 +#define HAVE_PREADV_RUNTIME 1 +#define HAVE_PWRITEV_RUNTIME 1 +#define HAVE_POSIX_SPAWN_SETSID_RUNTIME 1 +#define HAVE_CLOCK_GETTIME_RUNTIME 1 +#define HAVE_CLOCK_SETTIME_RUNTIME 1 +#define HAVE_CLOCK_GETRES_RUNTIME 1 +#define HAVE_GETENTROPY_RUNTIME 1 +#endif + +static inline void +Py_delete_method(PyMethodDef *methods, size_t size, const char *name) +{ + int last_method_index = (size /sizeof(PyMethodDef)) - 1; + for (int i = last_method_index; i >= 0; i--) { + if ( methods[i].ml_name && 0==strcmp(methods[i].ml_name, name)) { + for (int j = i; methods[j].ml_name != NULL; j++) { + methods[j] = methods[j+1]; + } + break; + } + } +} + +#endif + diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 674b47e3a1a601..2a7eb26488b9fd 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -42,6 +42,7 @@ #else # include "winreparse.h" #endif +#include "py_available.h" /* On android API level 21, 'AT_EACCESS' is not declared although * HAVE_FACCESSAT is defined. */ @@ -79,25 +80,7 @@ corresponding Unix manual entries for more information on calls."); # include <sys/stat.h> #endif /* HAVE_SYS_STAT_H */ -#if defined(__APPLE__) -#include <TargetConditionals.h> -#endif - -#if defined(__APPLE__) && HAVE_BUILTIN_AVAILABLE && !(TARGET_OS_OSX && __arm64__) -#define HAVE_UTIMENSAT_RUNTIME __builtin_available(macos 10.13, ios 11, tvos 11, watchos 4, *) -#define HAVE_FUTIMENS_RUNTIME __builtin_available(macos 10.13, ios 11, tvos 11, watchos 4, *) -#define HAVE_PREADV_RUNTIME __builtin_available(macos 10.16, ios 14, tvos 14, watchos 7, *) -#define HAVE_PWRITEV_RUNTIME __builtin_available(macos 10.16, ios 14, tvos 14, watchos 7, *) -#define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macos 10.15, ios 13, tvos 13, watchos 6, *) -#else -#define HAVE_UTIMENSAT_RUNTIME 1 -#define HAVE_FUTIMENS_RUNTIME 1 -#define HAVE_PREADV_RUNTIME 1 -#define HAVE_PWRITEV_RUNTIME 1 -#define HAVE_POSIX_SPAWN_SETSID_RUNTIME 1 -#endif - -#if defined(__APPLE__) && TARGET_OS_OSX && __arm64__ && __clang__ +#if __APPLE__ && TARGET_OS_OSX && __arm64__ && __clang__ #pragma clang diagnostic ignored "-Wunguarded-availability-new" #endif @@ -15169,18 +15152,9 @@ static struct PyModuleDef posixmodule = { static void delete_method(const char *name) { - int last_method_index = (sizeof(posix_methods) / sizeof(posix_methods[0])) - 1; - for (int i = last_method_index; i >= 0; i--) { - if ( posix_methods[i].ml_name && 0==strcmp(posix_methods[i].ml_name, name)) { - for (int j = i; posix_methods[j].ml_name != NULL; j++) { - posix_methods[j] = posix_methods[j+1]; - } - break; - } - } + Py_delete_method(posix_methods, sizeof(posix_methods), name); } - PyMODINIT_FUNC INITFUNC(void) { diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 96e2486f27da27..b1a2625879903c 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -1,6 +1,7 @@ /* Time module */ #include "Python.h" +#include "py_available.h" #include <ctype.h> @@ -51,20 +52,6 @@ #define _Py_tzname tzname #endif -#if defined(__APPLE__) -#include <TargetConditionals.h> -#endif - -#if defined(__APPLE__) && HAVE_BUILTIN_AVAILABLE && !(TARGET_OS_OSX && __arm64__) -#define HAVE_CLOCK_GETTIME_RUNTIME __builtin_available(macos 10.12, ios 10, tvos 10, watchos 3, *) -#define HAVE_CLOCK_SETTIME_RUNTIME __builtin_available(macos 10.12, ios 10, tvos 10, watchos 3, *) -#define HAVE_CLOCK_GETRES_RUNTIME __builtin_available(macos 10.12, ios 10, tvos 10, watchos 3, *) -#else -#define HAVE_CLOCK_GETTIME_RUNTIME 1 -#define HAVE_CLOCK_SETTIME_RUNTIME 1 -#define HAVE_CLOCK_GETRES_RUNTIME 1 -#endif - #define SEC_TO_NS (1000 * 1000 * 1000) /* Forward declarations */ @@ -1927,14 +1914,7 @@ static struct PyModuleDef timemodule = { static void delete_method(const char *name) { - for (int i = 0; time_methods[i].ml_name != NULL; i++) { - if ( 0==strcmp(time_methods[i].ml_name, name)) { - for (int j = i; time_methods[j].ml_name != NULL; j++) { - time_methods[j] = time_methods[j+1]; - } - break; - } - } + Py_delete_method(time_methods, sizeof(time_methods), name); } PyMODINIT_FUNC diff --git a/Python/bootstrap_hash.c b/Python/bootstrap_hash.c index 0dc86e2cf9f5f4..69e1b1dcf22197 100644 --- a/Python/bootstrap_hash.c +++ b/Python/bootstrap_hash.c @@ -1,5 +1,6 @@ #include "Python.h" #include "pycore_initconfig.h" +#include "py_available.h" #ifdef MS_WINDOWS # include <windows.h> /* All sample MSDN wincrypt programs include the header below. It is at least @@ -31,16 +32,6 @@ int _Py_HashSecret_Initialized = 0; static int _Py_HashSecret_Initialized = 0; #endif -#if defined(__APPLE__) -#include <TargetConditionals.h> -#endif - -#if defined(__APPLE__) && HAVE_BUILTIN_AVAILABLE && !(TARGET_OS_OSX && __arm64__) -#define HAVE_GETENTROPY_RUNTIME __builtin_available(macos 10.12, ios 10, tvos 10, watchos 3, *) -#else -#define HAVE_GETENTROPY_RUNTIME 1 -#endif - #ifdef MS_WINDOWS static HCRYPTPROV hCryptProv = 0; diff --git a/Python/pytime.c b/Python/pytime.c index 9757e5abc8e8a1..7978e4b41206cc 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -1,4 +1,5 @@ #include "Python.h" +#include "py_available.h" #ifdef MS_WINDOWS #include <winsock2.h> /* struct timeval */ #endif @@ -7,12 +8,6 @@ #include <mach/mach_time.h> /* mach_absolute_time(), mach_timebase_info() */ #endif -#if defined(__APPLE__) && HAVE_BUILTIN_AVAILABLE && !defined(__arm64__) -#define HAVE_CLOCK_GETTIME_RUNTIME __builtin_available(macos 10.12, ios 10, tvos 10, watchos 3, *) -#else -#define HAVE_CLOCK_GETTIME_RUNTIME 1 -#endif - #define _PyTime_check_mul_overflow(a, b) \ (assert(b > 0), \ (_PyTime_t)(a) < _PyTime_MIN / (_PyTime_t)(b) \ diff --git a/configure b/configure index ebdd1cfeed261d..5024860ca4395a 100755 --- a/configure +++ b/configure @@ -12190,41 +12190,6 @@ $as_echo "yes" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if the compiler supports __builtin_available" >&5 -$as_echo_n "checking to see if the compiler supports __builtin_available... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - -int -main () -{ - - if (__builtin_available(macOS 10.8, iOS 5.0, *)) {} - - ; - return 0; -} - -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - -cat >>confdefs.h <<_ACEOF -#define HAVE_BUILTIN_AVAILABLE 1 -_ACEOF - - -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 - for ac_prog in true do # Extract the first word of "$ac_prog", so it can be a program name with args. diff --git a/configure.ac b/configure.ac index 6df35971dec8d3..5a3e340aa3e72b 100644 --- a/configure.ac +++ b/configure.ac @@ -3825,19 +3825,6 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ AC_MSG_RESULT(yes) ]) -AC_MSG_CHECKING([to see if the compiler supports __builtin_available]) -AC_COMPILE_IFELSE([ - AC_LANG_PROGRAM([[]],[[ - if (__builtin_available(macOS 10.8, iOS 5.0, *)) {} - ]]) - ],[ - AC_MSG_RESULT([yes]) - AC_DEFINE_UNQUOTED(HAVE_BUILTIN_AVAILABLE, 1, - [Define to 1 if the compiler supports __builtin_available]) - ],[ - AC_MSG_RESULT([no]) -]) - dnl check for true AC_CHECK_PROGS(TRUE, true, /bin/true) diff --git a/pyconfig.h.in b/pyconfig.h.in index e602a4a9f4bdc1..bc906a869b623e 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -115,9 +115,6 @@ /* Define if `unsetenv` does not return an int. */ #undef HAVE_BROKEN_UNSETENV -#undef HAVE_BUILTIN_AVAILABLE -/* Define to 1 if the compiler supports __builtin_available */ - /* Has builtin atomics */ #undef HAVE_BUILTIN_ATOMIC From 03dd9af5a45188d77169f07f595f01b3331ad4b3 Mon Sep 17 00:00:00 2001 From: Lawrence D'Anna <lawrence_danna@apple.com> Date: Tue, 21 Jul 2020 15:09:10 -0700 Subject: [PATCH 5/7] fixup --- Modules/posixmodule.c | 212 ++++++++++++++++++++++-------------------- 1 file changed, 111 insertions(+), 101 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 2a7eb26488b9fd..6bd6a05fa56115 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -9289,64 +9289,69 @@ os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, int flags) /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/ { - if (HAVE_PREADV_RUNTIME) { - Py_ssize_t cnt, n; - int async_err = 0; - struct iovec *iov; - Py_buffer *buf; + /* preadv method will be deleted if preadv is not available */ + #if __clang__ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + #endif - if (!PySequence_Check(buffers)) { - PyErr_SetString(PyExc_TypeError, - "preadv2() arg 2 must be a sequence"); - return -1; - } + Py_ssize_t cnt, n; + int async_err = 0; + struct iovec *iov; + Py_buffer *buf; - cnt = PySequence_Size(buffers); - if (cnt < 0) { - return -1; - } + if (!PySequence_Check(buffers)) { + PyErr_SetString(PyExc_TypeError, + "preadv2() arg 2 must be a sequence"); + return -1; + } - #ifndef HAVE_PREADV2 - if(flags != 0) { - argument_unavailable_error("preadv2", "flags"); - return -1; - } - #endif + cnt = PySequence_Size(buffers); + if (cnt < 0) { + return -1; + } - if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) { - return -1; - } - #ifdef HAVE_PREADV2 - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - n = preadv2(fd, iov, cnt, offset, flags); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - #else - do { - 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())); - #endif +#ifndef HAVE_PREADV2 + if(flags != 0) { + argument_unavailable_error("preadv2", "flags"); + return -1; + } +#endif - iov_cleanup(iov, buf, cnt); - if (n < 0) { - if (!async_err) { - posix_error(); - } - return -1; - } + if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) { + return -1; + } +#ifdef HAVE_PREADV2 + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + n = preadv2(fd, iov, cnt, offset, flags); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); +#else + do { + 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())); +#endif - return n; - } else { - PyErr_SetString(PyExc_NotImplementedError, "preadv is not available"); + iov_cleanup(iov, buf, cnt); + if (n < 0) { + if (!async_err) { + posix_error(); + } return -1; } + + return n; + + #if __clang__ + #pragma clang diagnostic pop + #endif } #endif /* HAVE_PREADV */ @@ -9889,65 +9894,70 @@ os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, int flags) /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/ { - if (HAVE_PWRITEV_RUNTIME) { - Py_ssize_t cnt; - Py_ssize_t result; - int async_err = 0; - struct iovec *iov; - Py_buffer *buf; + /* pwritev method will be deleted if preadv is not available */ + #if __clang__ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + #endif - if (!PySequence_Check(buffers)) { - PyErr_SetString(PyExc_TypeError, - "pwritev() arg 2 must be a sequence"); - return -1; - } + Py_ssize_t cnt; + Py_ssize_t result; + int async_err = 0; + struct iovec *iov; + Py_buffer *buf; - cnt = PySequence_Size(buffers); - if (cnt < 0) { - return -1; - } + if (!PySequence_Check(buffers)) { + PyErr_SetString(PyExc_TypeError, + "pwritev() arg 2 must be a sequence"); + return -1; + } - #ifndef HAVE_PWRITEV2 - if(flags != 0) { - argument_unavailable_error("pwritev2", "flags"); - return -1; - } - #endif + cnt = PySequence_Size(buffers); + if (cnt < 0) { + return -1; + } - if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { - return -1; - } - #ifdef HAVE_PWRITEV2 - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - result = pwritev2(fd, iov, cnt, offset, flags); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - #else - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - result = pwritev(fd, iov, cnt, offset); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - #endif +#ifndef HAVE_PWRITEV2 + if(flags != 0) { + argument_unavailable_error("pwritev2", "flags"); + return -1; + } +#endif - iov_cleanup(iov, buf, cnt); - if (result < 0) { - if (!async_err) { - posix_error(); - } - return -1; - } + if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { + return -1; + } +#ifdef HAVE_PWRITEV2 + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + result = pwritev2(fd, iov, cnt, offset, flags); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); +#else + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + result = pwritev(fd, iov, cnt, offset); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); +#endif - return result; - } else { - PyErr_SetString(PyExc_NotImplementedError, "preadv is not available"); + iov_cleanup(iov, buf, cnt); + if (result < 0) { + if (!async_err) { + posix_error(); + } return -1; } + + return result; + + #if __clang__ + #pragma clang diagnostic pop + #endif } #endif /* HAVE_PWRITEV */ From 164a9f318999a58df00e006c69f8b667420727a1 Mon Sep 17 00:00:00 2001 From: Lawrence D'Anna <lawrence_danna@apple.com> Date: Tue, 21 Jul 2020 15:24:49 -0700 Subject: [PATCH 6/7] fixup runtime checks --- Modules/posixmodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 6bd6a05fa56115..8fdf14c6b4ddfd 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -9292,7 +9292,7 @@ os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, /* preadv method will be deleted if preadv is not available */ #if __clang__ #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wdeprecated-declarations" + #pragma clang diagnostic ignored "-Wunguarded-availability-new" #endif Py_ssize_t cnt, n; @@ -9897,7 +9897,7 @@ os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, /* pwritev method will be deleted if preadv is not available */ #if __clang__ #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wdeprecated-declarations" + #pragma clang diagnostic ignored "-Wunguarded-availability-new" #endif Py_ssize_t cnt; From 05866b6bf3518305c908f26ee043843746379f72 Mon Sep 17 00:00:00 2001 From: Lawrence D'Anna <lawrence_danna@apple.com> Date: Fri, 24 Jul 2020 13:15:24 -0700 Subject: [PATCH 7/7] simplify These complications were needed on a previous build of Xcode but as of XCode 12 beta 3 it works without them. --- Include/py_available.h | 6 +----- Modules/posixmodule.c | 4 ---- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/Include/py_available.h b/Include/py_available.h index 32a6c1c0ea6567..7933d3a6246c8b 100644 --- a/Include/py_available.h +++ b/Include/py_available.h @@ -9,11 +9,7 @@ #endif #endif -#if __APPLE__ -#include <TargetConditionals.h> -#endif - -#if __APPLE__ && HAVE_BUILTIN_AVAILABLE && !(TARGET_OS_OSX && __arm64__) +#if __APPLE__ && HAVE_BUILTIN_AVAILABLE #define HAVE_UTIMENSAT_RUNTIME __builtin_available(macos 10.13, ios 11, tvos 11, watchos 4, *) #define HAVE_FUTIMENS_RUNTIME __builtin_available(macos 10.13, ios 11, tvos 11, watchos 4, *) #define HAVE_PREADV_RUNTIME __builtin_available(macos 11.0, ios 14, tvos 14, watchos 7, *) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 8fdf14c6b4ddfd..e659d20bf5734e 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -80,10 +80,6 @@ corresponding Unix manual entries for more information on calls."); # include <sys/stat.h> #endif /* HAVE_SYS_STAT_H */ -#if __APPLE__ && TARGET_OS_OSX && __arm64__ && __clang__ -#pragma clang diagnostic ignored "-Wunguarded-availability-new" -#endif - #ifdef HAVE_SYS_WAIT_H # include <sys/wait.h> // WNOHANG #endif