Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit408e127

Browse files
freakboy3742mhsmithericsnowcurrently
authored
gh-114099 - Add iOS framework loading machinery. (GH-116454)
Co-authored-by: Malcolm Smith <smith@chaquo.com>Co-authored-by: Eric Snow <ericsnowcurrently@gmail.com>
1 parenta557478 commit408e127

File tree

22 files changed

+302
-62
lines changed

22 files changed

+302
-62
lines changed

‎.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ Lib/test/data/*
6969
/_bootstrap_python
7070
/Makefile
7171
/Makefile.pre
72-
iOSTestbed.*
72+
/iOSTestbed.*
7373
iOS/Frameworks/
7474
iOS/Resources/Info.plist
7575
iOS/testbed/build

‎Doc/library/importlib.rst

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,6 +1241,69 @@ find and load modules.
12411241
and how the module's:attr:`__file__` is populated.
12421242

12431243

1244+
..class::AppleFrameworkLoader(name, path)
1245+
1246+
A specialization of:class:`importlib.machinery.ExtensionFileLoader` that
1247+
is able to load extension modules in Framework format.
1248+
1249+
For compatibility with the iOS App Store, *all* binary modules in an iOS app
1250+
must be dynamic libraries, contained in a framework with appropriate
1251+
metadata, stored in the ``Frameworks`` folder of the packaged app. There can
1252+
be only a single binary per framework, and there can be no executable binary
1253+
material outside the Frameworks folder.
1254+
1255+
To accomodate this requirement, when running on iOS, extension module
1256+
binaries are *not* packaged as ``.so`` files on ``sys.path``, but as
1257+
individual standalone frameworks. To discover those frameworks, this loader
1258+
is be registered against the ``.fwork`` file extension, with a ``.fwork``
1259+
file acting as a placeholder in the original location of the binary on
1260+
``sys.path``. The ``.fwork`` file contains the path of the actual binary in
1261+
the ``Frameworks`` folder, relative to the app bundle. To allow for
1262+
resolving a framework-packaged binary back to the original location, the
1263+
framework is expected to contain a ``.origin`` file that contains the
1264+
location of the ``.fwork`` file, relative to the app bundle.
1265+
1266+
For example, consider the case of an import ``from foo.bar import _whiz``,
1267+
where ``_whiz`` is implemented with the binary module
1268+
``sources/foo/bar/_whiz.abi3.so``, with ``sources`` being the location
1269+
registered on ``sys.path``, relative to the application bundle. This module
1270+
*must* be distributed as
1271+
``Frameworks/foo.bar._whiz.framework/foo.bar._whiz`` (creating the framework
1272+
name from the full import path of the module), with an ``Info.plist`` file
1273+
in the ``.framework`` directory identifying the binary as a framework. The
1274+
``foo.bar._whiz`` module would be represented in the original location with
1275+
a ``sources/foo/bar/_whiz.abi3.fwork`` marker file, containing the path
1276+
``Frameworks/foo.bar._whiz/foo.bar._whiz``. The framework would also contain
1277+
``Frameworks/foo.bar._whiz.framework/foo.bar._whiz.origin``, containing the
1278+
path to the ``.fwork`` file.
1279+
1280+
When a module is loaded with this loader, the ``__file__`` for the module
1281+
will report as the location of the ``.fwork`` file. This allows code to use
1282+
the ``__file__`` of a module as an anchor for file system traveral.
1283+
However, the spec origin will reference the location of the *actual* binary
1284+
in the ``.framework`` folder.
1285+
1286+
The Xcode project building the app is responsible for converting any ``.so``
1287+
files from wherever they exist in the ``PYTHONPATH`` into frameworks in the
1288+
``Frameworks`` folder (including stripping extensions from the module file,
1289+
the addition of framework metadata, and signing the resulting framework),
1290+
and creating the ``.fwork`` and ``.origin`` files. This will usually be done
1291+
with a build step in the Xcode project; see the iOS documentation for
1292+
details on how to construct this build step.
1293+
1294+
..versionadded::3.13
1295+
1296+
..availability::iOS.
1297+
1298+
..attribute::name
1299+
1300+
Name of the module the loader supports.
1301+
1302+
..attribute::path
1303+
1304+
Path to the ``.fwork`` file for the extension module.
1305+
1306+
12441307
:mod:`importlib.util` -- Utility code for importers
12451308
---------------------------------------------------
12461309

‎Doc/tools/extensions/pyspecific.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ class Availability(SphinxDirective):
133133
known_platforms=frozenset({
134134
"AIX","Android","BSD","DragonFlyBSD","Emscripten","FreeBSD",
135135
"GNU/kFreeBSD","Linux","NetBSD","OpenBSD","POSIX","Solaris",
136-
"Unix","VxWorks","WASI","Windows","macOS",
136+
"Unix","VxWorks","WASI","Windows","macOS","iOS",
137137
# libc
138138
"BSD libc","glibc","musl",
139139
# POSIX platforms with pthreads

‎Lib/ctypes/__init__.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,17 @@ def __init__(self, name, mode=DEFAULT_MODE, handle=None,
348348
winmode=None):
349349
ifname:
350350
name=_os.fspath(name)
351+
352+
# If the filename that has been provided is an iOS/tvOS/watchOS
353+
# .fwork file, dereference the location to the true origin of the
354+
# binary.
355+
ifname.endswith(".fwork"):
356+
withopen(name)asf:
357+
name=_os.path.join(
358+
_os.path.dirname(_sys.executable),
359+
f.read().strip()
360+
)
361+
351362
self._name=name
352363
flags=self._func_flags_
353364
ifuse_errno:

‎Lib/ctypes/util.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def find_library(name):
6767
returnfname
6868
returnNone
6969

70-
elifos.name=="posix"andsys.platform=="darwin":
70+
elifos.name=="posix"andsys.platformin {"darwin","ios","tvos","watchos"}:
7171
fromctypes.macholib.dyldimportdyld_findas_dyld_find
7272
deffind_library(name):
7373
possible= ['lib%s.dylib'%name,

‎Lib/importlib/_bootstrap_external.py

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252

5353
# Bootstrap-related code ######################################################
5454
_CASE_INSENSITIVE_PLATFORMS_STR_KEY='win',
55-
_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY='cygwin','darwin'
55+
_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY='cygwin','darwin','ios','tvos','watchos'
5656
_CASE_INSENSITIVE_PLATFORMS= (_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY
5757
+_CASE_INSENSITIVE_PLATFORMS_STR_KEY)
5858

@@ -1714,6 +1714,46 @@ def __repr__(self):
17141714
returnf'FileFinder({self.path!r})'
17151715

17161716

1717+
classAppleFrameworkLoader(ExtensionFileLoader):
1718+
"""A loader for modules that have been packaged as frameworks for
1719+
compatibility with Apple's iOS App Store policies.
1720+
"""
1721+
defcreate_module(self,spec):
1722+
# If the ModuleSpec has been created by the FileFinder, it will have
1723+
# been created with an origin pointing to the .fwork file. We need to
1724+
# redirect this to the location in the Frameworks folder, using the
1725+
# content of the .fwork file.
1726+
ifspec.origin.endswith(".fwork"):
1727+
with_io.FileIO(spec.origin,'r')asfile:
1728+
framework_binary=file.read().decode().strip()
1729+
bundle_path=_path_split(sys.executable)[0]
1730+
spec.origin=_path_join(bundle_path,framework_binary)
1731+
1732+
# If the loader is created based on the spec for a loaded module, the
1733+
# path will be pointing at the Framework location. If this occurs,
1734+
# get the original .fwork location to use as the module's __file__.
1735+
ifself.path.endswith(".fwork"):
1736+
path=self.path
1737+
else:
1738+
with_io.FileIO(self.path+".origin",'r')asfile:
1739+
origin=file.read().decode().strip()
1740+
bundle_path=_path_split(sys.executable)[0]
1741+
path=_path_join(bundle_path,origin)
1742+
1743+
module=_bootstrap._call_with_frames_removed(_imp.create_dynamic,spec)
1744+
1745+
_bootstrap._verbose_message(
1746+
"Apple framework extension module {!r} loaded from {!r} (path {!r})",
1747+
spec.name,
1748+
spec.origin,
1749+
path,
1750+
)
1751+
1752+
# Ensure that the __file__ points at the .fwork location
1753+
module.__file__=path
1754+
1755+
returnmodule
1756+
17171757
# Import setup ###############################################################
17181758

17191759
def_fix_up_module(ns,name,pathname,cpathname=None):
@@ -1746,10 +1786,17 @@ def _get_supported_file_loaders():
17461786
17471787
Each item is a tuple (loader, suffixes).
17481788
"""
1749-
extensions=ExtensionFileLoader,_imp.extension_suffixes()
1789+
ifsys.platformin {"ios","tvos","watchos"}:
1790+
extension_loaders= [(AppleFrameworkLoader, [
1791+
suffix.replace(".so",".fwork")
1792+
forsuffixin_imp.extension_suffixes()
1793+
])]
1794+
else:
1795+
extension_loaders= []
1796+
extension_loaders.append((ExtensionFileLoader,_imp.extension_suffixes()))
17501797
source=SourceFileLoader,SOURCE_SUFFIXES
17511798
bytecode=SourcelessFileLoader,BYTECODE_SUFFIXES
1752-
return[extensions,source,bytecode]
1799+
returnextension_loaders+ [source,bytecode]
17531800

17541801

17551802
def_set_bootstrap_module(_bootstrap_module):

‎Lib/importlib/abc.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,11 @@ def get_code(self, fullname):
180180
else:
181181
returnself.source_to_code(source,path)
182182

183-
_register(ExecutionLoader,machinery.ExtensionFileLoader)
183+
_register(
184+
ExecutionLoader,
185+
machinery.ExtensionFileLoader,
186+
machinery.AppleFrameworkLoader,
187+
)
184188

185189

186190
classFileLoader(_bootstrap_external.FileLoader,ResourceLoader,ExecutionLoader):

‎Lib/importlib/machinery.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from ._bootstrap_externalimportSourceFileLoader
1313
from ._bootstrap_externalimportSourcelessFileLoader
1414
from ._bootstrap_externalimportExtensionFileLoader
15+
from ._bootstrap_externalimportAppleFrameworkLoader
1516
from ._bootstrap_externalimportNamespaceLoader
1617

1718

‎Lib/inspect.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,10 @@ def getsourcefile(object):
954954
elifany(filename.endswith(s)forsin
955955
importlib.machinery.EXTENSION_SUFFIXES):
956956
returnNone
957+
eliffilename.endswith(".fwork"):
958+
# Apple mobile framework markers are another type of non-source file
959+
returnNone
960+
957961
# return a filename found in the linecache even if it doesn't exist on disk
958962
iffilenameinlinecache.cache:
959963
returnfilename
@@ -984,6 +988,7 @@ def getmodule(object, _filename=None):
984988
returnobject
985989
ifhasattr(object,'__module__'):
986990
returnsys.modules.get(object.__module__)
991+
987992
# Try the filename to modulename cache
988993
if_filenameisnotNoneand_filenameinmodulesbyfile:
989994
returnsys.modules.get(modulesbyfile[_filename])
@@ -1119,7 +1124,7 @@ def findsource(object):
11191124
# Allow filenames in form of "<something>" to pass through.
11201125
# `doctest` monkeypatches `linecache` module to enable
11211126
# inspection, so let `linecache.getlines` to be called.
1122-
ifnot (file.startswith('<')andfile.endswith('>')):
1127+
if(not (file.startswith('<')andfile.endswith('>')))orfile.endswith('.fwork'):
11231128
raiseOSError('source code not available')
11241129

11251130
module=getmodule(object,file)

‎Lib/modulefinder.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,12 @@ def _find_module(name, path=None):
7272
ifisinstance(spec.loader,importlib.machinery.SourceFileLoader):
7373
kind=_PY_SOURCE
7474

75-
elifisinstance(spec.loader,importlib.machinery.ExtensionFileLoader):
75+
elifisinstance(
76+
spec.loader, (
77+
importlib.machinery.ExtensionFileLoader,
78+
importlib.machinery.AppleFrameworkLoader,
79+
)
80+
):
7681
kind=_C_EXTENSION
7782

7883
elifisinstance(spec.loader,importlib.machinery.SourcelessFileLoader):

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp