Skip to content

Commit 67e7ed6

Browse files
[3.15] gh-159998: Fix libpython.dynamic in build-details.json for framework builds (GH-160005) (#160145)
In framework builds, `libpython.dynamic` now joins `PYTHONFRAMEWORKPREFIX` with `LDLIBRARY` instead of `LIBDIR` with `LDLIBRARY`, so it points at the framework library that is actually installed. Other builds are unchanged. (cherry picked from commit 13c758d) Co-authored-by: Itamar Oren <itamarost@gmail.com>
1 parent 56c0185 commit 67e7ed6

3 files changed

Lines changed: 39 additions & 2 deletions

File tree

‎Lib/test/test_build_details.py‎

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,26 @@ def test_libpython_static(self):
191191
with open(value['static'], 'rb') as f:
192192
self.assertEqual(f.read(8), b'!<arch>\n')
193193

194+
@needs_installed_python
195+
@unittest.skipIf(
196+
is_android or is_apple_mobile,
197+
"Android and iOS run tests via a custom testbed method that doesn't ship libpython"
198+
)
199+
@unittest.skipIf(
200+
sys.platform == 'cygwin',
201+
"Cygwin installs the DLL in BINDIR and the import library in LIBPL, "
202+
"not in LIBDIR"
203+
)
204+
def test_libpython_dynamic(self):
205+
value = self.data.get('libpython', {})
206+
if 'dynamic' not in value:
207+
self.skipTest("No dynamic libpython")
208+
209+
if sysconfig._installation_is_relocated():
210+
self.skipTest("Installation is relocated")
211+
212+
self.assertTrue(os.path.isfile(value['dynamic']))
213+
194214

195215
@unittest.skipIf(
196216
generate_build_details is None,
@@ -303,8 +323,14 @@ def test_framework(self):
303323
# a libpython3.X.a symlink to the framework's shared library instead.
304324
libpython = self.generate_libpython(
305325
LDLIBRARY='Python.framework/Versions/3.X/Python',
306-
STATIC_LIBPYTHON=1, PYTHONFRAMEWORK='Python')
326+
STATIC_LIBPYTHON=1, PYTHONFRAMEWORK='Python',
327+
PYTHONFRAMEWORKPREFIX='/Library/Frameworks')
307328
self.assertNotIn('static', libpython)
329+
# The dynamic library is the framework binary, which is installed at
330+
# PYTHONFRAMEWORKPREFIX/LDLIBRARY.
331+
self.assertEqual(
332+
libpython['dynamic'],
333+
'/Library/Frameworks/Python.framework/Versions/3.X/Python')
308334

309335

310336
if __name__ == '__main__':
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix ``libpython.dynamic`` in the :pep:`739` ``build-details.json`` file for
2+
macOS and iOS framework builds. It now points at the framework's library
3+
instead of a nonexistent path under :file:`lib/`.

‎Tools/build/generate-build-details.py‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,13 @@ def generate_data(schema_version: str) -> collections.defaultdict[str, Any]:
9393
# The static library is only installed into LIBDIR when it is also
9494
# LDLIBRARY; otherwise it is only installed into LIBPL.
9595
static_library_dir = LIBPL if has_dynamic_library else LIBDIR
96+
# In framework builds, LDLIBRARY is the path of the framework library
97+
# relative to PYTHONFRAMEWORKPREFIX (e.g.
98+
# Python.framework/Versions/3.X/Python), not a file in LIBDIR.
99+
if sysconfig.get_config_var('PYTHONFRAMEWORK'):
100+
dynamic_library_dir = sysconfig.get_config_var('PYTHONFRAMEWORKPREFIX')
101+
else:
102+
dynamic_library_dir = LIBDIR
96103
elif os.name == 'nt':
97104
# Windows can only use a dynamic library or a static library.
98105
# If it's using a dynamic library, sys.dllhandle will be set.
@@ -101,6 +108,7 @@ def generate_data(schema_version: str) -> collections.defaultdict[str, Any]:
101108
has_dynamic_library = hasattr(sys, 'dllhandle')
102109
has_static_library = not has_dynamic_library
103110
static_library_dir = LIBDIR
111+
dynamic_library_dir = LIBDIR
104112
else:
105113
raise NotADirectoryError(f'Unknown platform: {os.name}')
106114

@@ -121,7 +129,7 @@ def generate_data(schema_version: str) -> collections.defaultdict[str, Any]:
121129
data['abi']['stable_abi_suffix'] = suffix
122130
break
123131

124-
data['libpython']['dynamic'] = os.path.join(LIBDIR, LDLIBRARY)
132+
data['libpython']['dynamic'] = os.path.join(dynamic_library_dir, LDLIBRARY)
125133
# FIXME: Not sure if windows has a different dll for the stable ABI, and
126134
# even if it does, currently we don't have a way to get its name.
127135
if PY3LIBRARY:

0 commit comments

Comments
 (0)