Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-41100: add runtime checks for MACOSX_DEPLOYMENT_TARGET=10.10 #21577

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions Include/py_available.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#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__ && 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, *)
#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

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add runtime checks so python can be built for Mac OS 10.10 using the latest Xcode
109 changes: 88 additions & 21 deletions Modules/posixmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down Expand Up @@ -4826,9 +4827,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;
/*
Expand All @@ -4841,7 +4847,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
Expand All @@ -4852,12 +4867,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
Expand All @@ -4875,12 +4893,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
Expand All @@ -4891,9 +4912,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)
Expand Down Expand Up @@ -5513,7 +5537,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
Expand Down Expand Up @@ -7168,7 +7197,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) {
Expand Down Expand Up @@ -9255,6 +9285,12 @@ os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
int flags)
/*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/
{
/* preadv method will be deleted if preadv is not available */
#if __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
#endif

Py_ssize_t cnt, n;
int async_err = 0;
struct iovec *iov;
Expand Down Expand Up @@ -9308,6 +9344,10 @@ os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
}

return n;

#if __clang__
#pragma clang diagnostic pop
#endif
}
#endif /* HAVE_PREADV */

Expand Down Expand Up @@ -9850,6 +9890,12 @@ os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
int flags)
/*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/
{
/* pwritev method will be deleted if preadv is not available */
#if __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
#endif

Py_ssize_t cnt;
Py_ssize_t result;
int async_err = 0;
Expand Down Expand Up @@ -9904,6 +9950,10 @@ os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
}

return result;

#if __clang__
#pragma clang diagnostic pop
#endif
}
#endif /* HAVE_PWRITEV */

Expand Down Expand Up @@ -14156,9 +14206,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
Expand Down Expand Up @@ -14228,6 +14276,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 */
};

Expand Down Expand Up @@ -15070,6 +15121,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;
Expand Down Expand Up @@ -15100,9 +15155,21 @@ static struct PyModuleDef posixmodule = {
.m_free = _posix_free,
};

static void
delete_method(const char *name)
{
Py_delete_method(posix_methods, sizeof(posix_methods), name);
}

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);
}

Expand Down
Loading