Skip to content

WIP: ENH: implement support for build-details.json (PEP 739) and cross compilation #779

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
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
25 changes: 22 additions & 3 deletions mesonpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,11 +312,15 @@ def __init__(
manifest: Dict[str, List[Tuple[pathlib.Path, str]]],
limited_api: bool,
allow_windows_shared_libs: bool,
is_cross: bool,
build_details: Optional[Dict[str, str | Dict[str, Any]]] = None,
) -> None:
self._metadata = metadata
self._manifest = manifest
self._limited_api = limited_api
self._allow_windows_shared_libs = allow_windows_shared_libs
self._is_cross = is_cross
self._build_details = build_details

@property
def _has_internal_libs(self) -> bool:
Expand Down Expand Up @@ -347,8 +351,8 @@ def tag(self) -> mesonpy._tags.Tag:
# does not contain any extension module (does not
# distribute any file in {platlib}) thus use generic
# implementation and ABI tags.
return mesonpy._tags.Tag('py3', 'none', None)
return mesonpy._tags.Tag(None, self._stable_abi, None)
return mesonpy._tags.Tag('py3', 'none', None, self._build_details)
return mesonpy._tags.Tag(None, self._stable_abi, None, self._build_details)

@property
def name(self) -> str:
Expand Down Expand Up @@ -757,6 +761,21 @@ def __init__(
''')
self._meson_native_file.write_text(native_file_data, encoding='utf-8')

# Handle cross compilation
self._is_cross = any(s.startswith('--cross-file') for s in self._meson_args['setup'])
self._build_details = None
if self._is_cross:
# Use build-details.json (PEP 739) to determine
# platform/interpreter/abi tags, if given.
for setup_arg in self._meson_args['setup']:
if setup_arg.startswith('-Dpython.build_config='):
with open(setup_arg.split('-Dpython.build_config=')[1]) as f:
self._build_details = json.load(f)
break
else:
# TODO: warn that interpreter details may be wrong. Get platform from cross file.
pass

# reconfigure if we have a valid Meson build directory. Meson
# uses the presence of the 'meson-private/coredata.dat' file
# in the build directory as indication that the build
Expand Down Expand Up @@ -1067,7 +1086,7 @@ def sdist(self, directory: Path) -> pathlib.Path:
def wheel(self, directory: Path) -> pathlib.Path:
"""Generates a wheel in the specified directory."""
self.build()
builder = _WheelBuilder(self._metadata, self._manifest, self._limited_api, self._allow_windows_shared_libs)
builder = _WheelBuilder(self._metadata, self._manifest, self._limited_api, self._allow_windows_shared_libs, self._is_cross, self._build_details)
return builder.build(directory)

def editable(self, directory: Path) -> pathlib.Path:
Expand Down
32 changes: 21 additions & 11 deletions mesonpy/_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,15 @@
_32_BIT_INTERPRETER = struct.calcsize('P') == 4


def get_interpreter_tag() -> str:
name = sys.implementation.name
def get_interpreter_tag(build_details: Optional[dict] = None) -> str:
if build_details is None:
name = sys.implementation.name
version = sys.version_info
else:
name = build_details['implementation']['name']
_v = build_details['implementation']['version']
version = (_v['major'], _v['minor'])
name = INTERPRETERS.get(name, name)
version = sys.version_info
return f'{name}{version[0]}{version[1]}'


Expand All @@ -53,7 +58,12 @@ def _get_cpython_abi() -> str:
return f'cp{version[0]}{version[1]}{debug}{pymalloc}'


def get_abi_tag() -> str:
def get_abi_tag(build_details: Optional[dict] = None) -> str:
if build_details is not None:
ext_suffix = build_details['abi']['extension_suffix']
else:
ext_suffix = sysconfig.get_config_var('EXT_SUFFIX')

# The best solution to obtain the Python ABI is to parse the
# $SOABI or $EXT_SUFFIX sysconfig variables as defined in PEP-314.

Expand All @@ -62,7 +72,7 @@ def get_abi_tag() -> str:
# See https://foss.heptapod.net/pypy/pypy/-/issues/3816 and
# https://github.com/pypa/packaging/pull/607.
try:
empty, abi, ext = str(sysconfig.get_config_var('EXT_SUFFIX')).split('.')
empty, abi, ext = str(ext_suffix).split('.')
except ValueError as exc:
# CPython <= 3.8.7 on Windows does not implement PEP3149 and
# uses '.pyd' as $EXT_SUFFIX, which does not allow to extract
Expand Down Expand Up @@ -178,8 +188,8 @@ def _get_ios_platform_tag() -> str:
return f'ios_{version[0]}_{version[1]}_{multiarch}'


def get_platform_tag() -> str:
platform = sysconfig.get_platform()
def get_platform_tag(build_details: Optional[dict] = None) -> str:
platform = build_details['platform'] if build_details is not None else sysconfig.get_platform()
if platform.startswith('macosx'):
return _get_macosx_platform_tag()
if platform.startswith('ios'):
Expand All @@ -194,10 +204,10 @@ def get_platform_tag() -> str:


class Tag:
def __init__(self, interpreter: Optional[str] = None, abi: Optional[str] = None, platform: Optional[str] = None):
self.interpreter = interpreter or get_interpreter_tag()
self.abi = abi or get_abi_tag()
self.platform = platform or get_platform_tag()
def __init__(self, interpreter: Optional[str] = None, abi: Optional[str] = None, platform: Optional[str] = None, build_details: Optional[dict] = None):
self.interpreter = interpreter or get_interpreter_tag(build_details)
self.abi = abi or get_abi_tag(build_details)
self.platform = platform or get_platform_tag(build_details)

def __str__(self) -> str:
return f'{self.interpreter}-{self.abi}-{self.platform}'
Loading