Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
919efcc
Add support for ARM64 to the pythonw tool
ronaldoussoren Jul 20, 2020
69c39f3
Add support for "universal2" as a fat binary target on macOS
ronaldoussoren Jul 20, 2020
3940c86
Tweak ctypes.macholib.dyld to work with the shared library cache.
ronaldoussoren Jul 20, 2020
deda5f0
Silence compile time warning
ronaldoussoren Jul 20, 2020
ea3c200
macOS/arm64 support, based on GH-21249
ronaldoussoren Jul 20, 2020
552bca8
Fix test for macOS before 10.10
ronaldoussoren Jul 20, 2020
e0c23a1
ARM64 is a valid platform for macOS
ronaldoussoren Jul 20, 2020
e637a77
Unconditionally use uint32_t here.
ronaldoussoren Jul 20, 2020
02fb660
First stab at deploying to an earlier version of macOS than the build…
ronaldoussoren Jul 21, 2020
ba2f5a3
Update build-installer.py for universal2 builds
ronaldoussoren Jul 26, 2020
8e3b454
Merge ctypes changes from Apple (PR 21241)
ronaldoussoren Jul 26, 2020
87c942b
The archive-deps.py script isn't really useful
ronaldoussoren Jul 26, 2020
515fbe6
Merge branch 'macos-deploy-to-earlier' into macos11-deploy-earlier-br…
ronaldoussoren Oct 20, 2020
eee5437
Cleanup the code to check at runtime for a couple of APIs.
ronaldoussoren Oct 20, 2020
3a1d4f2
Dynamicly fill posix._have_functions as well
ronaldoussoren Oct 20, 2020
2f019f4
Changes after testing with Xcode 6.2 on macOS 10.9
ronaldoussoren Oct 21, 2020
cec3da7
Code formatting
ronaldoussoren Oct 21, 2020
86b5cf3
Fix a number of errors in weaklinking support
ronaldoussoren Oct 21, 2020
d604cef
Merge branch 'macos11-deploy-earlier-branch' of github.com:ronaldouss…
ronaldoussoren Oct 21, 2020
dde0ba4
Implement tests for weak linked symbols.
ronaldoussoren Oct 21, 2020
7ac26c4
Finish the test for os.link behaviour
ronaldoussoren Oct 21, 2020
191a2d7
posixmodule.c uses multi-phase initialization
ronaldoussoren Oct 21, 2020
e6d195b
Make sure some form of prep_cif is called, even if the variadic versi…
ronaldoussoren Oct 21, 2020
cfb02ba
Move the removal of unavailable functions to the module exec
ronaldoussoren Oct 21, 2020
003dae8
Improved error handling
ronaldoussoren Oct 21, 2020
004ba4e
Remove '-arch arm64' from the compiler arguments when necessary
ronaldoussoren Oct 21, 2020
6019346
check that weak linking works for the time module
ronaldoussoren Oct 22, 2020
54576ab
Drop the DEPS_ONLY changes
ronaldoussoren Oct 22, 2020
6af77ab
Undo change to default PATH
ronaldoussoren Oct 22, 2020
b653df9
Use configure to detect the presence of _dyld_shared_cache_contains_path
ronaldoussoren Oct 22, 2020
98af7b3
Revert unnecessary change
ronaldoussoren Oct 22, 2020
817d9bf
Updates to timemodule.c
ronaldoussoren Oct 22, 2020
8684d9d
Stricter checking of __builtin_available
ronaldoussoren Oct 22, 2020
0b44610
Clean up setup.py
ronaldoussoren Oct 22, 2020
36deb92
Fix build failures on Linux
ronaldoussoren Oct 22, 2020
33d5710
Fix typo
ronaldoussoren Oct 22, 2020
c3113eb
Remove reference to non-existing probe function
ronaldoussoren Oct 22, 2020
587e53e
One more attempt at building on Linux...
ronaldoussoren Oct 22, 2020
24ef276
A bit of clean up of the setup.py logic.
ronaldoussoren Oct 22, 2020
e0614bc
Fix patchcheck issues
ronaldoussoren Oct 22, 2020
e6478fa
add prefix to f-strings
ronaldoussoren Oct 22, 2020
3f72949
Add missing preprocessor guards
ronaldoussoren Oct 22, 2020
5daff99
Use the correct cut-off for the availability of clock_gettime and
ronaldoussoren Oct 22, 2020
6681261
Fix error in preprocessor logic for os.chmod implementation
ronaldoussoren Oct 22, 2020
b17a3d5
Merge branch 'master' into macos11-deploy-earlier-branch
ronaldoussoren Oct 22, 2020
7e64e95
the sid attribute for posix_spawn is only available on recent version…
ronaldoussoren Oct 31, 2020
fef2e93
Changes due to review by Victor Stinner
ronaldoussoren Oct 31, 2020
24eb0d0
Merge branch 'macos11-deploy-earlier-branch' of github.com:ronaldouss…
ronaldoussoren Oct 31, 2020
296666b
inor changes
ronaldoussoren Nov 1, 2020
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
Prev Previous commit
Next Next commit
macOS/arm64 support, based on GH-21249
This is support for ctypes on macOS/arm64 based
on PR 21249 by Lawrence D'Anna (Apple).

Changes:
- changed __builtin_available tests from 11.0 to 10.15
- added test to setup.py for ffi_closure_alloc and use
  that in malloc_closure.c
- Minor change in the code path for ffi_prep_closure_var
  (coding style change)
  • Loading branch information
ronaldoussoren committed Jul 20, 2020
commit ea3c200890e1dc606745f6a5308725018595d001
1 change: 1 addition & 0 deletions Lib/test/test_bytes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1035,6 +1035,7 @@ def test_from_format(self):
c_char_p)

PyBytes_FromFormat = pythonapi.PyBytes_FromFormat
PyBytes_FromFormat.argtypes = (c_char_p,)
PyBytes_FromFormat.restype = py_object

# basic tests
Expand Down
2 changes: 2 additions & 0 deletions Lib/test/test_unicode.py
Original file line number Diff line number Diff line change
Expand Up @@ -2513,11 +2513,13 @@ class CAPITest(unittest.TestCase):
def test_from_format(self):
import_helper.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):
Expand Down
39 changes: 31 additions & 8 deletions Modules/_ctypes/callbacks.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "Python.h"
#include "frameobject.h"

#include <stdbool.h>

#include <ffi.h>
#ifdef MS_WIN32
#include <windows.h>
Expand All @@ -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);
}

Expand Down Expand Up @@ -361,8 +363,7 @@ CThunkObject *_ctypes_alloc_callback(PyObject *callable,

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;
Expand Down Expand Up @@ -408,13 +409,35 @@ CThunkObject *_ctypes_alloc_callback(PyObject *callable,
"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 true

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use "1" instead of "true"?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need #include <stdbool.h> for true.

# 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);
Expand Down
72 changes: 60 additions & 12 deletions Modules/_ctypes/callproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@
#include "Python.h"
#include "structmember.h" // PyMemberDef

#include <stdbool.h>

#ifdef MS_WIN32
#include <windows.h>
#include <tchar.h>
Expand Down Expand Up @@ -812,7 +814,8 @@ static int _call_function_pointer(int flags,
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;
Expand All @@ -835,14 +838,60 @@ static int _call_function_pointer(int flags,
if ((flags & FUNCFLAG_CDECL) == 0)
cc = FFI_STDCALL;
#endif
if (FFI_OK != ffi_prep_cif(&cif,
cc,
argcount,
restype,
atypes)) {
PyErr_SetString(PyExc_RuntimeError,
"ffi_prep_cif failed");
return -1;

# if 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
#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)) {
Expand Down Expand Up @@ -1212,9 +1261,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
Expand Down
8 changes: 8 additions & 0 deletions Modules/_ctypes/ctypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,14 @@ PyObject *_ctypes_get_errobj(int **pspace);
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 ~"
Expand Down
15 changes: 13 additions & 2 deletions Modules/_ctypes/malloc_closure.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
102 changes: 53 additions & 49 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,13 @@ def macosx_sdk_specified():
macosx_sdk_root()
return MACOS_SDK_SPECIFIED

def is_macosx_at_least(vers):
if MACOS:
dep_target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
if dep_target:
return tuple(map(int, dep_target.split('.'))) >= vers
return False


def is_macosx_sdk_path(path):
"""
Expand All @@ -239,6 +246,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
Expand Down Expand Up @@ -2100,43 +2114,18 @@ def detect_tkinter(self):
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 and
(is_macosx_at_least((10,15)) or '-arch arm64' in sysconfig.get_config_var("CFLAGS"))):
Comment thread
ronaldoussoren marked this conversation as resolved.
Outdated
self.use_system_libffi = True
else:
self.use_system_libffi = '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS")

include_dirs = []
extra_compile_args = ['-DPy_BUILD_CORE_MODULE']
extra_link_args = []
Expand All @@ -2149,11 +2138,10 @@ def detect_ctypes(self):

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')
#sources.append('_ctypes/darwin/dlfcn_simple.c')
Comment thread
ronaldoussoren marked this conversation as resolved.
Outdated
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
Expand Down Expand Up @@ -2183,31 +2171,47 @@ def detect_ctypes(self):
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'
# XXX: The define should only be added when actually using the system
Comment thread
ronaldoussoren marked this conversation as resolved.
Outdated
# version (and not a locally compiled one)
ext.extra_compile_args.append("-DUSING_APPLE_OS_LIBFFI=1")
ffi_in_sdk = os.path.join(macosx_sdk_root(), "usr/include/ffi")
if os.path.exists(ffi_in_sdk):
ffi_inc = ffi_in_sdk
ffi_lib = 'ffi'
else:
# OS X 10.5 comes with libffi.dylib; the include files are
# in /usr/include/ffi
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

Expand Down