-
Notifications
You must be signed in to change notification settings - Fork 98
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
Improved support for cross compilation #786
Comments
I do support cross-compilation on top of crane in https://github.com/rustshop/flakebox , among many things (support for cargo build profiles, etc.) The cross-compilation of Rust stuff is relatively easy, but cross-compilation of C/C++ dependencies requires setting up all sorts of env variables and then in practice fixup based on combination of bugs in C/C++ toolchains, C/C++ source code, exact building system wrapping C compilation (build.rs). Flakebox had to invent some tooling to make some C/C++ building stuff universally switchable: e.g. https://github.com/rustshop/flakebox/blob/master/lib/universalLlvmConfig.nix for this to work, and it generally takes a "set up env vars for each supported target" approach One user contributed a better support for pkgsCross, but I wasn't happy about how it works under the hood and never had time to redoit: rustshop/flakebox#161 Having some more universal cross-compilation support somewhere makes sense. In Flakebox I've coupled it with bunch of other things, which maybe would make sense to have separately and then re-use. |
That's been my experience as well, however setting up the appropriate env variables for the most common C/C++ build crates (like |
Hi @Popax21 thanks for the discussion! I think at a high level my decision to include cross-compilation support that "just works" will boil down to:
So at a high level, could you describe what additional behavior/implementation you'd like to see being done by default? I've somewhat intentionally avoided baking in cross-compilation support (and left it with an example) because of all the perils it is normally associated with like:
I'm totally open to changing my mind around this, but the goal of "just works" can be a pretty tall order once you start trying to handle more and more quirks in a general purpose way without any of the context and understanding a project maintainer would have in deciding the correct way to solve things for their specific use case. Some of the problems above are things that we could influence, but others there is little we can do by the time the derivation is being evaluated. |
As |
Hey, thanks yall for taking the time to engage with this! As briefly mentioned in the original issue text I already have a (WIP) implementation of this feature I created for one of my projects (in retrospective I should have put more emphasis on this in the original issue - this issue is mostly about checking if upstream crane would be interested in adopting such a feature before I put more effort into a complete / generic implementation for a PR), and as such I think I can answer some of those questions:
It's pretty much just that - setting some environment variables to hook up the Rust build process to standard nixpkgs cross-compilation infrastructure. Namely, this involves configuring cargo's build target / linker / emulator settings, as well as setting environment variables for the
In my experience it has worked just fine for anything I have thrown at it since I first wrote it. Of course a world where it always "just works" is an unachievable utopia, so I have no doubts that some more obscure crates / build processes will break this, but even in those cases it's almost certainly an issue of some additional required configuration being missing instead of the default configuration being wrong, so setting those environment variables by default still gets you closer to a functional cross-compilation setup than not doing anything (which is guaranteed to not work no matter the crate/...).
I'm not quite sure what you are referring to with this. Currently, when attempting to build a crane derivation without having made any cross compilation adjustments one will most likely just receive an error from cargo complaining that If the user does encounter a rare circumstance where the toolchain configured by crane does indeed cause an error (because a crate, for example, needs to be built with either gcc or clang specifically), then they're free to overwrite the relevant environment variables themselves in the derivation just as they would do with the current state of things (depending on the targeted level of complexity for this feature it might also be possible for crane to allow one to e.g. configure which stdenv to use, to allow derivations to configure the toolchain in a more ergonomic manner themselves). However, I highly doubt that these crates are very common, and that they wouldn't cause issues in a regular native build as well.
There's no inherent aspect of this feature which would require it to be either opt-in or opt-out. Personally, I would prefer if it were opt-out, since this should allow most crates to cross-compile out of the box, and of the few remaining crates for which this is not the case, there will be even fewer where the settings set by crane would be a cause of additional problems. To summarize what such a feature would look like once again, it would pretty much just be a matter of setting the environment variables set in the cross compilation example automatically, in a similar manner as to how nixpkgs' Rust infrastructure does it right now. While this obviously won't create a "it just works" scenario for >all< crates, it should create such a scenario for >most< crates, and remove part of the setup required for crates where it does not work out of the box. I'm currently on vacation, so I don't have access to the source code of my current WIP implementation, but I would be happy to provide concrete example Nix code to illustrate how an implementation might look like once I'm back home. If deemed acceptable, I would be willing to polish it up further and turn it into a PR. To briefly address your second set of points: obviously all of this will be in vain if the derivations themselves aren't properly set up for cross compilation / the crates don't support it out right. However, for derivations which are written "correctly" (as in using |
Is your feature request related to a problem? Please describe.
Currently, cross compilation using crane requires that the user sets up a bunch of environment variables on their own (see the cross compilation example on crane.dev).
This is an additional setup step required by all projects which want to allow users to cross-compile, and in most cases leads to non-target-independent derivations (the above-linked example is hardcoded to compile for aarch64 for example - it will pull in an aarch64 compiler even if the user does not want to cross compile, and changing the cross compilation target requires manual adjustment of the environment variables since they hard-code the rustc target).
Additionally, upstream flakes / repos using crane which have not configured cross compilation can't easily be cross compiled without patching the upstream repo.
Describe the solution you'd like
Ideally, cross compilation should "just work", as in not require any adjustments compared to a minimal native-only build setup - all that should be required to cross-compile a project is plugging in an instance of nixpkgs which has been set up for cross compilation (like e.g. a member of
pkgsCross
) intocrane.mkLib
.Crane then automatically sets the required environment variables to make cross compilation work, based on the instance of nixpkgs it has been given (this is similar to how nixpkgs's
buildRustPackage
currently works).Describe alternatives you've considered
Keep the current system of delegating the responsibility of configuring cargo's toolchain to the user.
This gives the user more control by default, however a setup where cross compilation "just works", with the the user being able to override any default options they want to change, would still be preferable in my opinion (additionally, a "kill switch" can be added to disable any default cross compilation settings, for users who want to configure cross compilation completely on their own).
Additional context
I have already implemented this myself for one of my projects, however I've decided to open an issue first instead of opening an unsolicited PR for an potentially unwanted feature.
If this is something upstream crane is interested in I would be happy to PR said implementation. :)
The text was updated successfully, but these errors were encountered: