crate2nix icon indicating copy to clipboard operation
crate2nix copied to clipboard

Cross compilation support

Open lovesegfault opened this issue 4 years ago • 14 comments

I'm trying to use crate2nix to build my toy kernel but I'm unsure how to correctly cross compile with it. I'm following BlogOS and in chapters 1 and 2 they go over how to correctly build a freestanding Rust binary, with an important step being the writing of a custom target:

{
  "llvm-target": "x86_64-unknown-none",
  "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
  "arch": "x86_64",
  "target-endian": "little",
  "target-pointer-width": "64",
  "target-c-int-width": "32",
  "os": "none",
  "executables": true,
  "linker-flavor": "ld.lld",
  "linker": "rust-lld",
  "panic-strategy": "abort",
  "disable-redzone": true,
  "features": "-mmx,-sse,+soft-float"
}

They then proceed to use cargo-xbuild to correctly rebuild core et al for the correct target. I think this should all be doable from within Nix though, but I don't really know how tell crate2nix to use the custom target, etc.

lovesegfault avatar May 01 '20 22:05 lovesegfault

Hi @lovesegfault, sounds like an awesome project! I have not looked into this and I'd need some time to dig into this. If you can make the underlying buildRustCrate use these parameters, it should be quite easy to convince crate2nix to do the right thing. I haven't even overwritten the target to an existing one, yet.

If you or someone else figures it out, it would be awesome to report back. I'd integrate it in the docs if it isn't too convoluted. Equivalently for eventual PRs.

kolloch avatar May 02 '20 08:05 kolloch

Maybe @andir can weigh in on how flexible buildRustCrate will be to these things

lovesegfault avatar May 04 '20 18:05 lovesegfault

I have literally no idea how that will behave with a custom target. It might just work out or maybe not.

andir avatar May 04 '20 21:05 andir

I'm looking at cross-compiling with crate2nix within the context of NixOS. So far I've found that some minor changes are needed to buildRustCrate, but I'm now running into a bunch of implicit assumptions in crate2nix's generated code that all crates are built for the same platform.

This causes crates that have build-dependencies to fail with errors like the following:

error[E0461]: couldn't find crate `autocfg` with expected target triple x86_64-unknown-linux-gnu
 --> build.rs:1:1
  |
1 | extern crate autocfg;
  | ^^^^^^^^^^^^^^^^^^^^^
  |
  = note: the following crate versions were found:
          crate `autocfg`, target triple arm-unknown-linux-gnueabihf: /nix/store/jpgbq5wl1qvid5gjgc6wl15gx79mh92n-rust_autocfg-0.1.6-armv6l-unknown-linux-gnueabihf-lib/lib/libautocfg-e2329d796e.rlib

error: aborting due to previous error

build-dependencies need to be built for the build platform, but it looks like it will take some significant refactoring to make this possible.

lopsided98 avatar Sep 27 '20 20:09 lopsided98

See https://github.com/kolloch/crate2nix/pull/152

lopsided98 avatar Sep 29 '20 00:09 lopsided98

Also n.b. even more tricky than build-dependeices are proc macros, which are listed as normal dev- and build- dependencies but also run on the build platform.

Ericson2314 avatar Oct 12 '20 03:10 Ericson2314

I think this issue can be closed? There are some odds and ends but the basic support has landed since #160.

Ericson2314 avatar Jul 08 '21 01:07 Ericson2314

The documentation could still stand to be improved a bit. I tried to get cross-compilation working with a crate2nix-generated expression for a couple days and eventually gave up (fortunately I found an alternate solution). For someone who doesn't have a deep knowledge of the internals of crate2nix, I think it's a big challenge to actually get something to cross-compile successfully.

exarkun avatar Dec 10 '22 00:12 exarkun

Fair enough. The hardest part is bounding the standard library and splicing it in. I would like to make that easier too.

Ericson2314 avatar Dec 10 '22 15:12 Ericson2314

I am curious how one could use crate2nix for compiling to mustang targets. I have been trying to play around with it but have not had success. I believe it is because I need to compile core somehow. I understand that you need to do crossSystem in order for the target to be passed to rustc. So for the nixpkgs that is calling calling Cargo.nix have the following:

pkgs1 = import nixpkgs {
  localSystem = system;
  crossSystem = {
    inherit system;
    rustc = {
      config = target;
      platform = builtins.fromJSON (builtins.readFile "${mustangTargets}/${target}.json");
    };
  };
};

But I am stuck on actually compiling core. I am using oxalica's rust-overlay as follows from a non-cross compiled nixpkgs. I do not want to compile rustc itself with the custom target, just core & alloc.

rust = super.rust-bin.selectLatestNightlyWith (toolchain: toolchain.default.override {extensions = ["rust-src" "miri"];}));

But all I get in the end is the following build log error:

Running rustc --crate-name cfg_if src/lib.rs --out-dir target/lib -L dependency=target/deps --cap-lints allow -C opt-level=3 -C codegen-units=1 --remap-path-prefix=/build=/ --cfg feature="default" --target /nix/store/ivm8cb4f1sdx7dhrwvn9ls7pfaa1lr7i-x86_64-mustang-linux-gnu.json --edition 2018 -C metadata=f243553f7f -C extra-filename=-f243553f7f --crate-type lib --color always
error[E0463]: can't find crate for `core`
  |
  = note: the `ivm8cb4f1sdx7dhrwvn9ls7pfaa1lr7i-x86_64-mustang-linux-gnu` target may not be installed
  = help: consider downloading the target with `rustup target add ivm8cb4f1sdx7dhrwvn9ls7pfaa1lr7i-x86_64-mustang-linux-gnu`

error[E0463]: can't find crate for `compiler_builtins`

error: aborting due to 2 previous errors

jordanisaacs avatar Feb 07 '23 00:02 jordanisaacs

I am sorry this is not more documented let alone streamlined, but see if you can imitate what github.com/alamgu/alamgu does.

Ericson2314 avatar Feb 07 '23 02:02 Ericson2314

No worries! That repo looks to be an example of exactly what I am looking for. I'll try to write some stuff down along the way to provide some more documentation.

jordanisaacs avatar Feb 07 '23 16:02 jordanisaacs

I was able to get cross compilation working based on alamgu correctly. I wrote some notes on how it works here. Essentially has three steps:

  1. keep your rustc compiler from getting cross compiled
  2. Create a sysroot through crate2nix that compiles your core, std, etc.
  3. Conditionally pass those sysroot crates to your non-build dependenices

jordanisaacs avatar Feb 27 '23 02:02 jordanisaacs

Great! Thank you!

Ericson2314 avatar Feb 27 '23 02:02 Ericson2314