axodotdev / cargo-dist

📦 shippable application packaging
https://axodotdev.github.io/cargo-dist/
Apache License 2.0
1.33k stars 56 forks source link

cross-compilation support #74

Open Gankra opened 1 year ago

Gankra commented 1 year ago

This is punted on in the current version, pending some evaluation of the options. There are three four options I know:

This is a blocker for musl and aarch64 (arm64) support.

Note that taiki-e/upload-rust-binary-action does handle this and in my experiments whatever it does Just Works (great work from taiki-e as always).

Gankra commented 1 year ago

One of my big concerns about cross-compilation is to what extent certain Fancy Things cannot be cross-compiled.

Apple certainly does not want you cross-compiling from linux to macos. I'm not sure if support for code signing (#21) or certain installers is necessarily non-crossable. Certainly some are harder to cross. Certainly there are... Ways Around The Rules. But I don't want to get people in trouble or have them ship busted things!

reubenmiller commented 1 year ago

Just some of my recent experience/pain regarding cross compiling for Linux arm* and x86_64 targets for an open source project that I'm involved with.

Basically we have to build for linux environments on arm >= v6, arm64 and x86_64, for both gnu and musl releases. We were using cargo-cross however still had some issues to build for all the targets and the output was dependant on your build machine.

Then I saw a great blog post about cargo-zigbuild and was amazed with how effort it was to cross compile for all of our targets, especially since the other developers have a mix between Windows (using WSL2) and MacOS (M1/arm64 and amd64) setups.

Below details some of the details with the projects:

Experience cargo-cross

Experience with cargo-zigbuild

Overall I was finally able to get the following targets built using cargo-zigbuild running both natively on MacOS M1 and inside a linux (dev) container.

Though like you said, I don't think it will work for absolutely everything, so it might be worthwhile allowing some "composability" when it comes to building for different targets. And the targets are above are not so exotic compared to the other more lower level embedded targets, e.g. risc etc.

I created a gist to detail my experience, including the references to sources etc.

I hope my experience can at least help someone else, as this had caused me countless hours fluffy around with various dependencies/build machines.

messense commented 1 year ago
  • armv7-unknown-linux-gnueabihf (yes, this does actually work...I think notice in the project's README.md is out of date)

To clarify, I have implemented some workarounds for these caveats in cargo-zigbuild and updated the readme: https://github.com/rust-cross/cargo-zigbuild#caveats

VorpalBlade commented 1 year ago

Is there any work being done on this and/or is there any way to help on this? Cross compiling to Linux ARM and Linux Aarch64 is an absolute must for me.

VorpalBlade commented 1 year ago

@reubenmiller I found the opposite. Zigbuild is great when it works, but:

  1. It fails when trying to for example cross compile and link OpenSSL (openssl-sys crate). You can either enabled the vendored feature of openssl-sys to build OpenSSL from source or with cross install the relevant -dev package for cross compiling in a pre-build step in the docker container.
    Installing OpenSSL as a pre-build step is much faster than building it from scratch every time, easily negating the general speed improvement of zigbuild over cross. (And no, rustls/ring is not an option for several of the platforms I'm targeting.)
  2. Cross supports running the tests using user mode qemu, zigbuild doesn't as far as I have been able to find. While this is not important for release, it is important for CI in general. And I'd rather not have to maintain two separate cross compilation systems.
  3. Cross compiling to Windows (x86_64-pc-windows-gnu) from Linux just doesn't seem to work at at all with zigbuild, works out of the box with cross.

Thus I think cross is the better and more mature option to go with.

cryingpotat0 commented 1 year ago

👋 Hey! I also wanted to chime in and see if cross compilation for cost reduction purposes was on the roadmap? Spinning up separate machines (especially expensive Mac machines, almost 10x an equivalent Linux machine) for every release seems like it could blow past the free tier on Github actions. While it's still cheap in the grand scheme of things, it would be cool to use the cheapest Github actions instance to compile for all platforms where possible.

ssokolow commented 1 year ago

Unfortunately, mac machines are probably the most difficult to replace because, unlike with MinGW, there's no libre equivalent to some of the parts of Apple's toolchain. (I believe the binary-signing tool is one such example, but that may be outdated information.)

The solutions I've run into which work without mac hardware have involved using parts of Apple's toolchain on top of non-mac hardware in violation of its license.

frol commented 5 months ago

I hope this issue can be prioritized. It seems that a number of projects would love to see it happen:

Toasterson commented 4 months ago

For MacOS there are decent hosted runner options available in gitlab and github it's only windows that due to DRM is hard to get. But there cross compiling works very well with ubuntu runners and native packages and the gnome msitools. I opened #821 for integration of the later.

VorpalBlade commented 4 months ago

For MacOS there are decent hosted runner options available in gitlab and github it's only windows that due to DRM is hard to get. But there cross compiling works very well with ubuntu runners and native packages and the gnome msitools. I opened #821 for integration of the later.

No I don't believe this is true. Github Actions offers free (for open source) Ubuntu, Windows and MacOS x86-64 runners. There are no free MacOS ARM64 runners. Thus you need cross compilation if you want to create native MacOS-ARM64 binaries (cross testing seems impossible, rosetta only goes the other direction as far as I understand).

As far as I know most non-github options cost money, which is not an option for small open source hobby projects.

Windows can also be trivially cross compiled from Linux with the -gnu toolchain. The -msvc one cannot. There are no license-abiding ways to cross compile to MacOS at all as far as I know.

Toasterson commented 4 months ago

Hi, @VorpalBlade I was talking about Gitlab exclusively as we cannot use GitHub due to corporate requirements. GitLab has ARM64 runners. https://docs.gitlab.com/ee/ci/runners/saas/macos_saas_runner.html#machine-types-available-for-macos

VorpalBlade commented 4 months ago

Hi, @VorpalBlade I was talking about Gitlab exclusively as we cannot use GitHub due to corporate requirements. GitLab has ARM64 runners. https://docs.gitlab.com/ee/ci/runners/saas/macos_saas_runner.html#machine-types-available-for-macos

You said "gitlab and github" in your original text so that is what I responded to. However it seems that the MacOS runners on gitlab are only available on "Tier: Premium, Ultimate", so that is irrelevant for open source projects. At least the windows runners there are available on the free tier.

Toasterson commented 4 months ago

Oh, sorry. I noticed that now. Anyway, in the text I was looking at it said

SaaS runners on macOS are in Beta for open-source programs and customers in Premium and Ultimate plans.

So I took it for a spin on my free account. https://gitlab.com/Toasterson/rust-cross-testing/-/pipelines but it looks like this feature does indeed need a Subscription...

connec commented 2 months ago

I've been able to cross compile aarch64 from standard x86 GitHub Actions runners with a fairly small amount of configuration:

YMMV – I have minimal system dependencies in the projects where I've used this and I'm sure it would require more fiddling if you depend on additional system libraries (openssl etc). I've also not thoroughly tested the results (though I've tested that they execute, at least).

frol commented 2 months ago

@connec Thanks for sharing! I tried to follow your steps, but system dependencies are blocking me (openssl and libudev): https://github.com/near/near-cli-rs/pull/319

image
Toasterson commented 2 months ago

Then you will need a sysroot with copies of those libs and headers and use the --sysroot flag when compiling. Adding that flag to the .cargo/config.toml CC lines worked for me when I needed to cross compile. Checkout the cross project for sysroot tarballs and OCI images in the wild.

frol commented 2 months ago

Well, I used cross before and it worked great, so I would love to see cargo-dist support it or any other solution.

I am getting more and more reports these days from people trying to use my CLIs on:

  1. Docker on macOS ARM64 (M1/M2/...) which runs Linux ARM64 images
  2. Raspberry Pi

@Gankra What is your vision/priority regarding cross-compilation? As a temporary solution, I am thinking about creating a separate workflow to build extra binary releases (I'll play with https://github.com/taiki-e/upload-rust-binary-action or build completely from scratch), and I expect that the installer will see those binary-release archives