Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
PyPy
cffi
Commits
89bbed80be4d
Commit
f166536c
authored
Oct 02, 2020
by
Max Bélanger
1
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix building `cffi` for macOS with Apple Silicon support + backwards compatibility
parent
144ac54d9bff
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
88 additions
and
73 deletions
+88
-73
c/_cffi_backend.c
c/_cffi_backend.c
+83
-47
setup.py
setup.py
+5
-26
No files found.
c/_cffi_backend.c
View file @
89bbed80
...
...
@@ -80,18 +80,36 @@
* That sounds like a horribly bad idea to me, and is the reason for why
* I prefer CFFI crashing cleanly.
*
* Currently, we use libffi's ffi_closure_alloc()
only
on NetBSD. It is
* Currently, we use libffi's ffi_closure_alloc() on NetBSD. It is
* known that on the NetBSD kernel, a different strategy is used which
* should not be open to the fork() bug.
*
* This is also used on macOS, provided we are executing on macOS 10.15 or
* above.
*/
#ifdef __NetBSD__
# define CFFI_TRUST_LIBFFI
#endif
#ifndef CFFI_TRUST_LIBFFI
# define CFFI_CHECK_FFI_CLOSURE_ALLOC 1
# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC 1
# define CFFI_CHECK_FFI_PREP_CIF_VAR 0
#elif defined(__APPLE__) && defined(FFI_AVAILABLE_APPLE)
# define CFFI_CHECK_FFI_CLOSURE_ALLOC __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
# define CFFI_CHECK_FFI_PREP_CIF_VAR __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
# include "malloc_closure.h"
#endif
#else
# define CFFI_CHECK_FFI_CLOSURE_ALLOC 0
# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC 0
# define CFFI_CHECK_FFI_PREP_CIF_VAR 0
# include "malloc_closure.h"
#endif
#if PY_MAJOR_VERSION >= 3
# define STR_OR_BYTES "bytes"
...
...
@@ -1890,11 +1908,11 @@ static void cdataowninggc_dealloc(CDataObject *cd)
ffi_closure
*
closure
=
((
CDataObject_closure
*
)
cd
)
->
closure
;
PyObject
*
args
=
(
PyObject
*
)(
closure
->
user_data
);
Py_XDECREF
(
args
);
#ifdef CFFI_TRUST_LIBFFI
ffi_closure_free
(
closure
);
#
else
cffi_closure_free
(
closure
);
#endif
if
(
CFFI_CHECK_FFI_CLOSURE_ALLOC
)
{
ffi_closure_free
(
closure
);
}
else
{
cffi_closure_free
(
closure
);
}
}
else
{
Py_FatalError
(
"cdata CDataOwningGC_Type with unexpected type flags"
);
...
...
@@ -5821,6 +5839,7 @@ static cif_description_t *fb_prepare_cif(PyObject *fargs,
cif_description_t
*
cif_descr
;
struct
funcbuilder_s
funcbuffer
;
ffi_status
status
;
char
did_prep_cif_var
=
0
;
funcbuffer
.
nb_bytes
=
0
;
funcbuffer
.
bufferp
=
NULL
;
...
...
@@ -5843,20 +5862,22 @@ static cif_description_t *fb_prepare_cif(PyObject *fargs,
assert
(
funcbuffer
.
bufferp
==
buffer
+
funcbuffer
.
nb_bytes
);
cif_descr
=
(
cif_description_t
*
)
buffer
;
#if HAVE_FFI_PREP_CIF_VAR
/* use `ffi_prep_cif_var` if necessary and available */
if
(
variadic_nargs_declared
>=
0
)
{
status
=
ffi_prep_cif_var
(
&
cif_descr
->
cif
,
fabi
,
variadic_nargs_declared
,
funcbuffer
.
nargs
,
funcbuffer
.
rtype
,
funcbuffer
.
atypes
);
}
else
#endif
#if !HAVE_FFI_PREP_CIF_VAR && defined(__arm64__) && defined(__APPLE__)
#error Apple Arm64 ABI requires ffi_prep_cif_var
#endif
{
if
(
CFFI_CHECK_FFI_PREP_CIF_VAR
)
{
status
=
ffi_prep_cif_var
(
&
cif_descr
->
cif
,
fabi
,
variadic_nargs_declared
,
funcbuffer
.
nargs
,
funcbuffer
.
rtype
,
funcbuffer
.
atypes
);
did_prep_cif_var
=
1
;
}
}
if
(
!
did_prep_cif_var
)
{
status
=
ffi_prep_cif
(
&
cif_descr
->
cif
,
fabi
,
funcbuffer
.
nargs
,
funcbuffer
.
rtype
,
funcbuffer
.
atypes
);
}
if
(
status
!=
FFI_OK
)
{
PyErr_SetString
(
PyExc_SystemError
,
"libffi failed to build this function type"
);
...
...
@@ -6244,6 +6265,7 @@ static PyObject *b_callback(PyObject *self, PyObject *args)
PyObject
*
infotuple
;
cif_description_t
*
cif_descr
;
ffi_closure
*
closure
;
ffi_status
status
;
void
*
closure_exec
;
if
(
!
PyArg_ParseTuple
(
args
,
"O!O|OO:callback"
,
&
CTypeDescr_Type
,
&
ct
,
&
ob
,
...
...
@@ -6254,12 +6276,13 @@ static PyObject *b_callback(PyObject *self, PyObject *args)
if
(
infotuple
==
NULL
)
return
NULL
;
#ifdef CFFI_TRUST_LIBFFI
closure
=
ffi_closure_alloc
(
sizeof
(
ffi_closure
),
&
closure_exec
);
#else
closure
=
cffi_closure_alloc
();
closure_exec
=
closure
;
#endif
if
(
CFFI_CHECK_FFI_CLOSURE_ALLOC
)
{
closure
=
ffi_closure_alloc
(
sizeof
(
ffi_closure
),
&
closure_exec
);
}
else
{
closure
=
cffi_closure_alloc
();
closure_exec
=
closure
;
}
if
(
closure
==
NULL
)
{
Py_DECREF
(
infotuple
);
PyErr_SetString
(
PyExc_MemoryError
,
...
...
@@ -6286,28 +6309,40 @@ static PyObject *b_callback(PyObject *self, PyObject *args)
"return type or with '...'"
,
ct
->
ct_name
);
goto
error
;
}
/* NOTE: ffi_prep_closure() is marked as deprecated. We could just
* call ffi_prep_closure_loc() instead, which is what ffi_prep_closure()
* does. However, cffi also runs on older systems with a libffi that
* doesn't have ffi_prep_closure_loc() at all---notably, the OS X
* machines on Azure are like that (June 2020). I didn't find a way to
* version-check the included ffi.h. So you will have to live with the
* deprecation warning for now. (We could try to check for an unrelated
* macro like FFI_API which happens to be defined in libffi 3.3 and not
* before, but that sounds very obscure. And I prefer a compile-time
* warning rather than a cross-version binary compatibility problem.)
*/
#ifdef CFFI_TRUST_LIBFFI
if
(
ffi_prep_closure_loc
(
closure
,
&
cif_descr
->
cif
,
invoke_callback
,
infotuple
,
closure_exec
)
!=
FFI_OK
)
{
if
(
CFFI_CHECK_FFI_PREP_CLOSURE_LOC
)
{
status
=
ffi_prep_closure_loc
(
closure
,
&
cif_descr
->
cif
,
invoke_callback
,
infotuple
,
closure_exec
);
}
else
{
#if defined(__APPLE__) && defined(FFI_AVAILABLE_APPLE) && !FFI_LEGACY_CLOSURE_API
PyErr_Format
(
PyExc_SystemError
,
"ffi_prep_closure_loc() is missing"
);
goto
error
;
#else
if
(
ffi_prep_closure
(
closure
,
&
cif_descr
->
cif
,
invoke_callback
,
infotuple
)
!=
FFI_OK
)
{
/* messily try to silence a gcc/clang deprecation warning here */
# if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
# elif defined(__GNUC__)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
# endif
status
=
ffi_prep_closure
(
closure
,
&
cif_descr
->
cif
,
invoke_callback
,
infotuple
);
# if defined(__clang__)
# pragma clang diagnostic pop
# elif defined(__GNUC__)
# pragma GCC diagnostic pop
# endif
#endif
}
if
(
status
!=
FFI_OK
)
{
PyErr_SetString
(
PyExc_SystemError
,
"libffi failed to build this callback"
);
goto
error
;
}
if
(
closure
->
user_data
!=
infotuple
)
{
/* Issue #266. Should not occur, but could, if we are using
at runtime a version of libffi compiled with a different
...
...
@@ -6327,11 +6362,12 @@ static PyObject *b_callback(PyObject *self, PyObject *args)
error:
closure
->
user_data
=
NULL
;
if
(
cd
==
NULL
)
{
#ifdef CFFI_TRUST_LIBFFI
ffi_closure_free
(
closure
);
#else
cffi_closure_free
(
closure
);
#endif
if
(
CFFI_CHECK_FFI_CLOSURE_ALLOC
)
{
ffi_closure_free
(
closure
);
}
else
{
cffi_closure_free
(
closure
);
}
}
else
Py_DECREF
(
cd
);
...
...
setup.py
View file @
89bbed80
...
...
@@ -149,39 +149,18 @@ if COMPILE_LIBFFI:
sources
.
extend
(
os
.
path
.
join
(
COMPILE_LIBFFI
,
filename
)
for
filename
in
_filenames
)
else
:
if
'darwin'
in
sys
.
platform
and
macosx_deployment_target
()
>=
(
10
,
15
):
# use libffi from Mac OS SDK if we're targetting 10.15 (including
# on arm64). This libffi is safe against the crash-after-fork
# issue described in _cffi_backend.c. Also, arm64 uses a different
# ABI for calls to vararg functions as opposed to regular functions.
extra_compile_args
+=
[
'-iwithsysroot/usr/include/ffi'
]
define_macros
+=
[(
'CFFI_TRUST_LIBFFI'
,
'1'
),
(
'HAVE_FFI_PREP_CIF_VAR'
,
'1'
)]
libraries
+=
[
'ffi'
]
else
:
use_pkg_config
()
use_pkg_config
()
ask_supports_thread
()
ask_supports_sync_synchronize
()
if
'darwin'
in
sys
.
platform
:
# priority is given to `pkg_config`, but always fall back on SDK's libffi.
extra_compile_args
+=
[
'-iwithsysroot/usr/include/ffi'
]
if
'freebsd'
in
sys
.
platform
:
include_dirs
.
append
(
'/usr/local/include'
)
library_dirs
.
append
(
'/usr/local/lib'
)
if
'darwin'
in
sys
.
platform
:
try
:
p
=
subprocess
.
Popen
([
'xcrun'
,
'--show-sdk-path'
],
stdout
=
subprocess
.
PIPE
)
except
OSError
as
e
:
if
e
.
errno
not
in
[
errno
.
ENOENT
,
errno
.
EACCES
]:
raise
else
:
t
=
p
.
stdout
.
read
().
decode
().
strip
()
p
.
stdout
.
close
()
if
p
.
wait
()
==
0
:
include_dirs
.
append
(
t
+
'/usr/include/ffi'
)
if
__name__
==
'__main__'
:
from
setuptools
import
setup
,
Distribution
,
Extension
...
...
Martin
@StykMartin
mentioned in issue
#480 (closed)
·
Nov 27, 2020
mentioned in issue
#480 (closed)
mentioned in issue #480
Toggle commit list
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment