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
Cross compiling aarch64 wheel #598
Comments
Hi @odidev. I think we definitely would be interested! (it's been mentioned multiple times as a possibility, before, when adding QEMU support) The main concern to be resolved is how to ensure that the produced wheels are fully conforming to the
What exactly do you mean? How are the produced wheels different? Apart from that, I assume we of course need to consider how to integrate this into |
I've been hoping this would be worked on; compiles are painfully slow in emulation. Scikit-learn barely squeaks by in the 6 hour time window, I think. It needs to be optional, though, as it can take a little work in the package to set up. Mildly related point: This feature would be just fine in a 2.x series release, because there are no Python 2.7 alternate arch manylinuxes.
Yes, at least tests should run in emulation, just like Apple on a AS runner. :) |
It does? So we can't just shove in a cross-compiler and have things work seemlessly? :-/ |
Please find my response below-
PEP-599 says- If the wheel contains binary executables or shared objects linked against any allowed libraries that also export versioned symbols, they may only depend on the following maximum versions: We can prepare the cross compilation toolchain to honor the above requirements. However manylinux2014 containers provides gcc9 and we can go with the same.
Here I am talking about the time taken to cross compile the wheels. The time taken to cross compile the aarch64 wheel is almost similar as native compilation on x86_64 machine.
Yes we can use qemu to repair and test the wheel.
I will work on it and will share my findings on this. |
@YannickJadoul, the code change in the package requires to change the name of the cross compiled artifacts. The code change in cibuildwheel is not going to help us because cibuildwheel calls What we can do here is, instead of asking user to modify their setup.py file, we can internally patch the setup.py file within cibuildwheel during cross compilation of the wheels. Please let me know your thought here? |
Will it?
If that's what needs to happen, then yes, it would be the goal for |
Basically we need to, override below method to change the naming convention during the cross compilation.
I don't see any other way rather than patching setup.py file. Do you have any suggestions on this?
The methods which we need to override is related to below module/packages
|
wrap |
Unfortunately the other two don't seem to have easy ways to override. However I do note that |
FYI, I have built manylinux compliant(I think?) docker images for cross compiling to aarch64 and armv7l recently: https://github.com/messense/manylinux-cross It should be easy to use with crossenv since it has both host and target Python builtin, for exampe: https://github.com/messense/fasttext-wheel/blob/master/manylinux-cross.sh |
That's really cool @messense ! Props for figuring out all the fiddly details. I'm curious how generalisable this approach is. |
Sorry for the late reply, I was caught up in few other activities. @joerick, thanks for the suggesting to override sysconfig.get_platform, sysconfig.get_config_vars and distutils.sysconfig.get_config_vars methods. I applied the similar logic in the cross compilation image itself and it is working as expected. Now we can apply this approach in two ways: Below are the demerits of both the approaches: Script approach: Please provide your feedback regarding both the approaches. |
Hi odidev! This is quite a complex question, as I'm not yet sure how this would factor in to our existing feature set yet. Of the above 2 options, I'm not sure that either really fits into the model of how cibuildwheel works currently. So I'm actually more curious if we could leverage crossenv rather than doing this ourselves, as @messence mentioned? From crossenv's readme:
On a side note, I suppose UI-wise, it would be nice to just set |
Hi @joerick, to cross compile the Linux AArch64 wheels, I have done the below changes(using crossenv)- Enable cross compilation flag: Docker image: Cibuildwheel: Testing the patches: Limitations: @joerick, Please let me know if you have any questions? Thank You. |
Hi @joerick, can you please let me know if above approach/patches looks ok to you? |
I do know we can't add packages to pypa without a vote, and I don't think a fork is a valid thing to put there. But you could try to see if something could be upstreamed, and until then, just require that users manually specify an image if they want to cross-compile. Setting "odidev/manylinux2014_aarch64:2021-07-29-39729cd" isn't that bad. Also, since most of the forking is related to setting up simlinks (IIRC when I checked before), maybe cibuildwheel could do this before building. I'm busy with a few other things (and today's release of Python 3.10rc1 will likely take quite a bit of time in several of my projects), so can't fully review for now. |
@henryiii, thanks for your response. User don't need to to set an image for cross compilation and just setting |
Hi odidev. Apologies for the slow response. There's a lot to go through here and I didn't want to rush a response without taking the time to review it properly. I'd like to discuss a few things before we get to PRs - this is an enormous jump in complexity of cibuildwheel so it really needs to justify that complexity. cibuildwheel isn't really a "build system" exactly, it's more of a framework that stitches together preexisting tools in the Python packaging ecosystem. cibuildwheel has enough complexity to worry about in presenting a unified API to build wheels! So if it's possible, I'd like this to fit the same approach, to keep the mechanisms of a cross-compile separate to the cibuildwheel project, so that cibuildwheel can interact with that system with a documented and stable API. Perhaps it would help if you could explain how the pieces of your current solution fit together currently? I see large modifications to linux.py, but also a cross_compile.py, different docker images used in building and testing, a direct use of qemu, use of the (Just to be clear, I think the current state of the cibuildwheel patch is too large to be merged. I wouldn't want to waste any of your time working on this if the problem is fundamentally this complex and we can't reduce it further.) |
Hi @joerick, On a high level, in this scenario, cibuildwheel determines the architectures to cross compile and then setup the environment for them. For this, cibuildwheel creates a docker instance with the image used for cross compilation. Before building the wheel, we would need to install few dependencies (executing before_all) into toolchian for example libffi-devel while building cffi wheels. We can't directly install such dependencies in docker instance because it is x86_64 based and will pull the binaries for same architecture only. To overcome this problem, cibuildwheel runs such commands in a native container and copy back the installed artifacts into the toolchain. coming to python related commands, crossenv uses two versions of python- When all the prerequisites are done, cibuildwheel builds the wheel with Modifications are explained here- I will explore to minimize the changes, but steps can't be eliminated. What if I add a file like linux_cross_compile.py and define a build api in that and put all the things there only? Will that be ok for you? Please let me know if you have any questions? |
Thanks @odidev for this response. It's very helpful. And also massive props getting this system working! I'd like to hear what other maintainers are thinking in regards to this before moving forward. My current feeling is that this might be outside the scope of cibuildwheel, because as the jump in complexity is going to contribute a lot of extra work when maintaining the existing feature set and adding new features. I wonder therefore, if there would be merit in publishing this build system as a complementary tool e.g. 'crossbuildwheel' tool that's compatible with some of cibuildwheel options1 and called by users separately, or perhaps, eventually, invoked by cibuildwheel itself to perform a cross-compile. 1 I note that the semantics of CIBW_BEFORE_* options are changed in this system, CIBW_BUILD_FRONTEND isn't used, and the semantics of others are subtly changed by the use of different execution environments. |
@joerick, I don't see any response from other maintainers on this thread. Can you please suggest how to proceed on this? |
Hmm. This is a tricky one. I can see that cross-compilation of aarch64 would be a valuable feature for users, but I also see lots of complexity here that I don't currently have time to integrate and I'm not sure I want to commit to maintain long-term. I think perhaps the best route forward would be that your build system could be stood up as a standalone tool ( |
@joerick, Thanks for your response and suggestions. If I create tool like |
Sorry for the delay from my side (and it's not over), but I'd like to jot down a few thoughts. First, the best thing would have been a simple, first-party addition to just make it possible to cross compile with some user configuration. I still have to look over it more carefully, but that's likely not feasible if too much has to be changed and the cost of maintenance grows too much. If done very carefully, there still might be a chance - I'll look over what you've done in the near future. It would have to be general to not be tied to a specific fork, etc. Assuming that's not possible, then I think the second best option would be to develop an extension API. We could provide specific, documented hooks so that users could write a "plugin" for cibuildwheel that would extend it, in this case, to add cross compilation. Then you could avoid forking (with would be a disaster, you'd have to sync the constant maintenance changes, etc). If we had a "minimal" set of changes that would make it "possible" (not "pretty") to cross-compile, that might be a good starting point. Also, to get a repository into the PyPA, a vote has to be taken of all active members, first on the forum, then in a mailing list if it has a current member willing to start the vote. It's not something we can just add. The process is outlined in PEP 609. |
Thanks for weighing in, @henryiii !
The thought also occurred to me. But TBH I wasn't sure what advantage an plugin API would offer over a separate, decoupled standalone tool. I suppose there's options parsing, and perhaps our DockerContainer helper..? The downside of an extension API are of course the burden of maintaining it - ensuing that internal (now external) APIs don't break backwards compatibility is a big one. Also I'd want to be convinced that we might see another few consumers of this API to make that maintenance burden worth it.
Apologies, I didn't intend to propose @odidev's new tool would be a fork of cibuildwheel, although I can see why you assumed that. I would recommend that odidev's crossbuildwheel tool doesn't do any of the mac/windows/conventional manylinux building, leave that to cibuildwheel, but just tackle this one issue of cross compiling manylinux. So users might do their build something like: - name: Build wheels
run: |
pipx run cibuildwheel==2.1.1 --output-dir wheelhouse .
pipx run crossbuildwheel==0.1.0 --output-dir wheelhouse . ...which would invoke cibuildwheel to do the conventional builds, and then crossbuildwheel to do the aarch64 cross-compilation. |
The benefit is we'd only have to maintain that, not the cross-compiling extension too, though. Specifically, I don't want to be tied to a fork of dockcross, that would be more maintenance than I'd like to commit to.
Pretty much everything? All the options / configurations / pinning / etc? Basically you'd have to rewrite cibuildwheel except you could skip macOS and Windows. You'd still need the "traditional" emulated linux support as well to run the tests, which would be extra important when cross compiling. Also, would all configuration need to be duplicated under a new prefix for users? Honestly, the overall size of the patch (odidev@2c8c109) isn't that bad - most of the worry really comes because of the extra requirements of the forked docker image (odidev/dockcross@39729cd). I really want to look through this in the near future and see if we could support just the cibuildwheel patch without taking on the dockcross image. |
Could this be cleanly implemented as a new platform? "crosslinux" as the platform, perhaps? then crosslinux.py would sit beside linux.py, windows.py, and macos.py. This would get rid of a lot of the if statements, etc. above. You would have to specify |
(this is also what I was thinking about as a "plugin" system - if an unrecognized platform was looked up through an entrypoint, then most of the logic would sit there, and we'd just have to have a few functions we expect to call and a way to load identifiers, I think). |
Yes, I do think this would be the neatest way to do it, if we wanted to pull that functionality into cibuildwheel.
Maybe I'm missing something, but I don't see huge amounts of code... the cross-build wouldn't need pip constraint pins, as it uses the docker container. It uses a different docker container from the manylinux ones, so those pins aren't needed. And any bits of code that are useful, crossbuildwheel could copy from cibuildwheel to get started.
Yes, this could work. I'd still be concerned about the resulting API stability requirements, though.
I'd be interested in what you find out! I know that cross compiling aarch64 is becoming more of a priority for the community, so I would like to support it. So if there's a lower-maintenance way forward, I'm all ears. Btw, another thing in the back of my mind is - how long until aarch64 CI runners are available? We are starting to see more and ARM servers be deployed in cloud environments, I kinda expect that within 2-3 years ARM will be a more mainstream cloud platform. If so, cross-building is more of a stop-gap than a long-term solution. At the very least we should see Mac ARM64 runners within the next 1-2 years, these machines can run aarch64 Docker images natively. So that is slightly reducing my appetite for big cibuildwheel changes to support this feature. |
@henryiii and @joerick, I have implemented a new platform Please let me know if this looks OK. Also, I have pushed changes in dockcross to support cross compiling the wheels. The images has been released on PyPI: dockcross/manylinux2014-aarch64:20210823-db51f29 |
This is starting to look very good, especially since official dockcross gained support and we can just build on that. A few questions (you do not need to implement them right now):
|
@henryiii, I will add cross compilation support for |
@ax3l, cross compiler is not following manylinux compliance which is a blocker. So, this activity is on hold as of now. |
Oh I see, that's too bad for now. Thanks for the update. |
Just curious, how would one test and/or achieve manylinux compliance? |
@nikolaik, please check this: #804 (comment) |
@henryiii It turns out that @thewtex and I are maintaining the dockcross organization, we can definitely discuss approaches to consolidate the manylinux images are reduce overall maintenance effort. |
Building wheels using emulation through qemu is much slower and the cross compilation wheel is almost similar as on x86_64.
Here is the comparison for the time taken in different ways of building wheels
X86_64 (Native build)
Start: Tue Feb 16 15:46:46 UTC 2021
End: Tue Feb 16 15:47:40 UTC 2021
Build Time: 0:54
Qemu (Emulation)
Start: Tue Feb 16 15:50:11 UTC 2021
End: Tue Feb 16 15:54:53 UTC 2021
Build Time: 4:42
Cross compilation
Start: Tue Feb 16 16:03:53 UTC 2021
End: Tue Feb 16 16:04:32 UTC 2021
Build Time: 0:39
Here are the modified/added files:
Modified files in cibuildwheel-
cibuildwheel.patch.txt
Used dockcross docker images with slight modification-
dockcross.patch.txt
Added files in dockcross (manylinux2014-aarch64 directory) -
install_deps.sh.txt
repair_wheel.sh.txt
Users need to modify their setup files to cross compile the wheel(cffi as an example)-
cffi.patch.txt
Please let me know your interest in adding cross compilation support. Thanks in advance.
The text was updated successfully, but these errors were encountered: