Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
ctypes: check _dyld_shared_cache_contains_path in find_library
System libraries in Mac OS 11 may be present only in the shared cache,
with the actual mach-o file not present in the corresponding location
on the filesystem.   ctypes.util.find_library should check the
shared cache in order to behave consistently across Mac OS 10.15
and earlier and Mac OS 11.0 and later.
  • Loading branch information
lawrence-danna-apple committed Jun 30, 2020
commit 311f8c301d8b6d3aef7156631f487eccc73c6ef7
12 changes: 12 additions & 0 deletions Lib/ctypes/macholib/dyld.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
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',
'framework_info', 'dylib_info',
Expand Down Expand Up @@ -124,6 +130,12 @@ def dyld_find(name, executable_path=None, env=None):
), 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):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ctypes: Mac OS 11: check for system libraries in the shared cache
38 changes: 38 additions & 0 deletions Modules/_ctypes/callproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@
#include "ctypes_dlfcn.h"
#endif

#ifdef __APPLE__
extern bool _dyld_shared_cache_contains_path(const char* path) __attribute__((weak_import));

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.

This can be replaced with #include <mach-o/dyld.h> after Seed 3

@jeremyhu jeremyhu Jul 7, 2020 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Can we please wait for official API here? or at least have another PR to clean this up which we can merge later?

@kainjow kainjow Jul 23, 2020 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Seed 3 is out today 🎉

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.

looks like it got pushed out to seed 4

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It is in Xcode 12 beta 4, only enough with the same name but with documentation in a header file.

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.

yup, updated the pull request to include mach-o/dyld.h instead of declaring a weak import

#endif

#ifdef MS_WIN32
#include <malloc.h>
#endif
Expand Down Expand Up @@ -1398,6 +1402,37 @@ copy_com_pointer(PyObject *self, PyObject *args)
}
#else

#ifdef __APPLE__
static PyObject *py_dyld_shared_cache_contains_path(PyObject *self, PyObject *args)
{
PyObject *name, *name2;
char *name_str;

if (_dyld_shared_cache_contains_path == NULL) {
PyErr_SetString(PyExc_NotImplementedError, "_dyld_shared_cache_contains_path symbol is missing");
return NULL;
}

if (!PyArg_ParseTuple(args, "O", &name))
return NULL;

if (name == Py_None)
Py_RETURN_FALSE;

if (PyUnicode_FSConverter(name, &name2) == 0)
return NULL;
if (PyBytes_Check(name2))
name_str = PyBytes_AS_STRING(name2);
else
name_str = PyByteArray_AS_STRING(name2);

if(_dyld_shared_cache_contains_path(name_str))
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
#endif

static PyObject *py_dl_open(PyObject *self, PyObject *args)
{
PyObject *name, *name2;
Expand Down Expand Up @@ -1908,6 +1943,9 @@ PyMethodDef _ctypes_module_methods[] = {
"dlopen(name, flag={RTLD_GLOBAL|RTLD_LOCAL}) open a shared library"},
{"dlclose", py_dl_close, METH_VARARGS, "dlclose a library"},
{"dlsym", py_dl_sym, METH_VARARGS, "find symbol in shared library"},
#endif
#ifdef __APPLE__
{"_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},
Expand Down