crossenv icon indicating copy to clipboard operation
crossenv copied to clipboard

Add support for cross-compiling on iOS

Open freakboy3742 opened this issue 1 year ago • 7 comments

PEP 730 adds iOS as a Tier 3 supported platform for CPython 3.13. This PR adds the modifications to crossenv to support cross-compiling for iOS devices (ARM64) and iOS Simulators (ARM64 and x86_64). It also includes support for tvOS and watchOS, since the changes are effectively identical.

It also migrates the setup.py file to PEP 621 pyproject.toml format. A pyproject.toml file with a PEP517 configuration is required to avoid warnings (and, in the very near future installation errors); migrating the rest of the configuration was relatively trivial.

These changes have been empirically tested through use in Mobile Forge, which compiles a range of binary packages, for Python 3.9 through 3.13.

There's no additional programmatic tests, because it's not clear if the existing test suite is currently in a working state. I couldn't find any documentation for how to run the test suite; when I take the naïve approach and use pytest to run the test suite locally (on macOS), I get a 100% failure rate; and there's no CI results (that I can find) to compare against. I'm happy to add runtime tests for any of these changes if requested - I just need some guidance on how the test suite is meant to run.

freakboy3742 avatar Sep 06 '24 07:09 freakboy3742

Wow, this is really neat, thank you. I will start taking a look at it right away.

The existing test suite is unfortunately, as you noticed, partially broken. Some of the tests ended up depending on a combination of Python/setuptools/3rd party modules, which has ended up being far too much of a moving target to maintain. This is something I need to rework.

benfogle avatar Sep 08 '24 00:09 benfogle

If you've got any general notes/ideas on how the test suite should work (or it's a case of "just get it working, however you do it), I might be able to find some time to work on fixing those issues. However, if you'd prefer to tackle that kind of "core infrastructure" yourself, I'd completely understand.

freakboy3742 avatar Sep 08 '24 22:09 freakboy3742

Re: the test suite. It's not terribly broken and can be run manually. I do actually have a local branch to fix things up. Basically it needs:

  • Migrate to GitHub actions
  • Instead of maintaining a toolchain for testing, run the tests in pre-built docker images. There are docker images that would work that either didn't exist when I started the project, or I wasn't aware of them.
  • Don't rely on building 3rd party modules for test purposes. Like bcrypt started using Rust and numpy started using cmake. And setuptools changes too. This is tricky, because testing with setuptools is still a good idea even though it's a moving target.

benfogle avatar Sep 10 '24 01:09 benfogle

Re: the test suite. It's not terribly broken and can be run manually.

I've had no luck running pytest on the current master branch. I get 100% failures, with every test failing with either:

shutil.ReadError: /Users/rkm/projects/crossenv/tests/prebuilt/prebuilt_musl_arm_aarch64.tar.xz is not a compressed or uncompressed tar file

or

UnboundLocalError: cannot access local variable 'archives' where it is not associated with a value

Looking at the xz file - if I try to unpack it manually, I get an error that it isn't a valid archive "Unrecognised archive format".

freakboy3742 avatar Sep 10 '24 01:09 freakboy3742

I see now from reverse engineering the Azure config that my testing problem is likely the git lfs handling. I'll see if that fixes things...

freakboy3742 avatar Sep 10 '24 03:09 freakboy3742

Ok - it's clearly not just lfs; I get binary format errors if I run on an ARM64 macOS laptop. From what I can work out, that's not surprising - the test (and lfs content) seems to involve packaged binaries. My x86_64 Ubuntu 22.04 test machine also fails - there's a handful of test successes (mostly in test_usage), but also a bunch of executable format errors, and a lot of "AssertionError: Could not make crossenv!".

Are you able to provide any high level context for what the test suite is actually doing, and where it should run?

freakboy3742 avatar Sep 10 '24 05:09 freakboy3742

The test suites expect to run on Linux (crossenv has been Linux-only up to now), with qemu-user available via binfmt. On ubuntu, you can install qemu-user-binfmt or qemu-user-static. I run it on Ubuntu 22.04 currently.

Most of these tests will create a temporary crossenv environment (you can poke around in /tmp/pytest-of-$USER to see them) and then run commands in that environment. To make sure that the cross-compiled modules can execute, we use qemu-user to emulate the host-python and load the module. For debugging, I often find it helpful to debug a single test at a time: pytest -k <name_of_test> --pdb. You can also use --trace instead of --pdb to break at the start instead of on failure.

benfogle avatar Sep 11 '24 00:09 benfogle

The test suites expect to run on Linux (crossenv has been Linux-only up to now), with qemu-user available via binfmt. On ubuntu, you can install qemu-user-binfmt or qemu-user-static. I run it on Ubuntu 22.04 currently.

Most of these tests will create a temporary crossenv environment (you can poke around in /tmp/pytest-of-$USER to see them) and then run commands in that environment. To make sure that the cross-compiled modules can execute, we use qemu-user to emulate the host-python and load the module. For debugging, I often find it helpful to debug a single test at a time: pytest -k <name_of_test> --pdb. You can also use --trace instead of --pdb to break at the start instead of on failure.

Ah - that probably explains it. My Ubuntu 22.04 test box is already being emulated, so QEMU won't work (I can't run the Android emulator on my Ubuntu or Windows test boxes for essentially the same reason).

Using a Docker container to run the tests suite container might avoid those problems - but it might hit the same "emulation inside an emulator" limits. I'll try and see if that's any more successful.

freakboy3742 avatar Sep 12 '24 00:09 freakboy3742

@benfogle I've done some more investigation; it looks like the issue isn't QEMU as I thought, but the libraries dynamically linked by the prebuilt environments. Details in #118 where I've got a GitHub Actions CI configuration definition.

freakboy3742 avatar Oct 01 '24 06:10 freakboy3742

I'm not seeing any breakage manually. What I'm going to do is cut a release off of another PR that just went in and then merge this one. If there is breakage we're not catching, it'll be on the unreleased master branch and hopefully we can fix up CI and then release.

benfogle avatar Oct 06 '24 00:10 benfogle