nix-community / crate2nix

rebuild only changed crates in CI with crate2nix and nix
https://nix-community.github.io/crate2nix/
Apache License 2.0
356 stars 83 forks source link

Cross compilation support #132

Open lovesegfault opened 4 years ago

lovesegfault commented 4 years ago

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.

kolloch commented 4 years ago

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.

lovesegfault commented 4 years ago

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

andir commented 4 years ago

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

lopsided98 commented 3 years ago

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 commented 3 years ago

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

Ericson2314 commented 3 years ago

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 commented 3 years ago

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

exarkun commented 1 year ago

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.

Ericson2314 commented 1 year ago

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

jordanisaacs commented 1 year ago

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
Ericson2314 commented 1 year ago

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

jordanisaacs commented 1 year ago

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 commented 1 year ago

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
Ericson2314 commented 1 year ago

Great! Thank you!