Bug report
Bug description:
Lib/_ios_support.py raises ImportError at module import if ctypes.util.find_library("objc") returns None:
lib = util.find_library("objc")
if lib is None:
# Failed to load the objc library
raise ImportError("ObjC runtime library couldn't be loaded")
On Apple platforms the ObjC runtime exists only in the dyld shared cache, not as a file on disk, so find_library() cannot resolve it by a filesystem check. ctypes.macholib.dyld.dyld_find() handles that by falling back to _dyld_shared_cache_contains_path():
if os.path.isfile(path):
return path
try:
if _dyld_shared_cache_contains_path(path):
return path
except NotImplementedError:
pass
That symbol is availability-guarded at runtime in Modules/_ctypes/callproc.c:
#define HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH_RUNTIME \
__builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
so on iOS 13 the probe raises NotImplementedError, dyld_find() gives up, find_library("objc") returns None, and importing _ios_support fails outright. IPHONEOS_DEPLOYMENT_TARGET defaults to 13.0 in configure.ac, so this is inside the range iOS support targets, and it takes platform.platform(), platform.ios_ver() and anything else built on _ios_support down with it.
dyld resolves a bare library name against the shared cache by itself, so the runtime is loadable even when find_library() cannot name a path for it. On macOS, where the same cache mechanism applies:
>>> from ctypes import cdll, util; import os
>>> util.find_library("objc")
'/usr/lib/libobjc.dylib'
>>> os.path.isfile("/usr/lib/libobjc.dylib")
False
>>> cdll.LoadLibrary("libobjc.dylib")
<CDLL 'libobjc.dylib', handle ... at ...>
The suggested fix is to fall back to the bare name when find_library() comes up empty, and to keep reporting a genuine load failure as ImportError. With find_library patched to return None, the module then loads the runtime and objc_getClass(b"NSProcessInfo") works.
A caveat on the evidence: I do not have an iOS 13 device or simulator runtime, so I have not reproduced the import failure on-device — the chain above is read from the source. The fallback itself is verified, as shown.
CPython versions tested on:
CPython main
Operating systems tested on:
macOS
Linked PRs
Bug report
Bug description:
Lib/_ios_support.pyraisesImportErrorat module import ifctypes.util.find_library("objc")returnsNone:On Apple platforms the ObjC runtime exists only in the dyld shared cache, not as a file on disk, so
find_library()cannot resolve it by a filesystem check.ctypes.macholib.dyld.dyld_find()handles that by falling back to_dyld_shared_cache_contains_path():That symbol is availability-guarded at runtime in
Modules/_ctypes/callproc.c:so on iOS 13 the probe raises
NotImplementedError,dyld_find()gives up,find_library("objc")returnsNone, and importing_ios_supportfails outright.IPHONEOS_DEPLOYMENT_TARGETdefaults to13.0inconfigure.ac, so this is inside the range iOS support targets, and it takesplatform.platform(),platform.ios_ver()and anything else built on_ios_supportdown with it.dyld resolves a bare library name against the shared cache by itself, so the runtime is loadable even when
find_library()cannot name a path for it. On macOS, where the same cache mechanism applies:The suggested fix is to fall back to the bare name when
find_library()comes up empty, and to keep reporting a genuine load failure asImportError. Withfind_librarypatched to returnNone, the module then loads the runtime andobjc_getClass(b"NSProcessInfo")works.A caveat on the evidence: I do not have an iOS 13 device or simulator runtime, so I have not reproduced the import failure on-device — the chain above is read from the source. The fallback itself is verified, as shown.
CPython versions tested on:
CPython main
Operating systems tested on:
macOS
Linked PRs