Skip to content

Commit 2d9019d

Browse files
committed
ENH: Add support for targeting Android
1 parent 3205db1 commit 2d9019d

2 files changed

Lines changed: 74 additions & 0 deletions

File tree

mesonpy/__init__.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,38 @@ def __init__(
744744
self._meson_cross_file.write_text(cross_file_data, encoding='utf-8')
745745
self._meson_args['setup'].extend(('--cross-file', os.fspath(self._meson_cross_file)))
746746

747+
# Android may be native-compiled (e.g. with Termux), or cross-compiled (e.g.
748+
# with cibuildwheel), in which case we should generate a cross file.
749+
# sys.cross_compiling isn't an official Python API, but it originated from
750+
# crossenv and has been followed by other cross-compiling tools.
751+
elif (
752+
sysconfig.get_platform().startswith('android-')
753+
and getattr(sys, 'cross_compiling', False)
754+
):
755+
cpu = platform.machine()
756+
cpu_family = (
757+
'arm' if cpu.startswith('arm') else 'x86' if cpu.endswith('86') else cpu
758+
)
759+
760+
cross_file_data = textwrap.dedent(f'''
761+
# Binaries are controlled by environment variables, so they don't need
762+
# to be repeated here.
763+
[host_machine]
764+
system = 'android'
765+
subsystem = 'android'
766+
kernel = 'linux'
767+
cpu_family = {cpu_family!r}
768+
cpu = {cpu!r}
769+
endian = {sys.byteorder!r}
770+
771+
[properties]
772+
# cibuildwheel's cross virtual environment will make Meson believe it's
773+
# running on Android when it's actually running on Linux or macOS.
774+
needs_exe_wrapper = true
775+
''')
776+
self._meson_cross_file.write_text(cross_file_data, encoding='utf-8')
777+
self._meson_args['setup'].extend(('--cross-file', os.fspath(self._meson_cross_file)))
778+
747779
# Support iOS targets. iOS does not have native build tools and always
748780
# requires cross compilation: synthesize the appropriate cross file.
749781
elif sysconfig.get_platform().startswith('ios-'):

tests/test_project.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,48 @@ def test_archflags_envvar_parsing_invalid(package_purelib_and_platlib, monkeypat
378378
os.environ.pop('_PYTHON_HOST_PLATFORM', None)
379379

380380

381+
@pytest.mark.parametrize(
382+
('cpu', 'cpu_family'),
383+
[
384+
('aarch64', 'aarch64'),
385+
('armv7l', 'arm'),
386+
('armv8l', 'arm'),
387+
('i686', 'x86'),
388+
('x86_64', 'x86_64'),
389+
],
390+
)
391+
@pytest.mark.parametrize('cross', [True, False])
392+
def test_android_project(package_simple, monkeypatch, tmp_path, cpu, cpu_family, cross):
393+
# Mock being on Android
394+
monkeypatch.setattr(sys, 'platform', 'android')
395+
monkeypatch.setattr(sys, 'byteorder', 'little')
396+
monkeypatch.setattr(platform, 'machine', Mock(return_value=cpu))
397+
monkeypatch.setattr(sysconfig, 'get_platform', Mock(return_value='android-24'))
398+
if cross:
399+
monkeypatch.setattr(sys, 'cross_compiling', True, raising=False)
400+
monkeypatch.setenv('STRIP', '/path/to/strip')
401+
402+
# Create a project.
403+
project = mesonpy.Project(source_dir=package_simple, build_dir=tmp_path)
404+
405+
# When cross-compiling, a cross file should be generated and used.
406+
setup_args = project._meson_args['setup']
407+
cross_path = tmp_path / 'meson-python-cross-file.ini'
408+
if cross:
409+
assert setup_args[-2:] == ['--cross-file', str(cross_path)]
410+
cross_config = cross_path.read_text().splitlines()
411+
assert "system = 'android'" in cross_config
412+
assert "subsystem = 'android'" in cross_config
413+
assert "kernel = 'linux'" in cross_config
414+
assert f"cpu_family = '{cpu_family}'" in cross_config
415+
assert f"cpu = '{cpu}'" in cross_config
416+
assert "endian = 'little'" in cross_config
417+
assert 'needs_exe_wrapper = true' in cross_config
418+
else:
419+
assert '--cross-file' not in setup_args
420+
assert not cross_path.exists()
421+
422+
381423
@pytest.mark.skipif(sys.version_info < (3, 13), reason='requires Python 3.13 or higher')
382424
@pytest.mark.parametrize('multiarch', [
383425
'arm64-iphoneos',

0 commit comments

Comments
 (0)