ipetkov / crane

A Nix library for building cargo projects. Never build twice thanks to incremental artifact caching.
https://crane.dev
MIT License
871 stars 82 forks source link

Fails to find library artifacts when cross compiling #223

Closed dpc closed 1 year ago

dpc commented 1 year ago

At https://github.com/fedimint/fedimint as per commit 61a4c2571108c7f25ee6edf88ae043cf8dfd462f (for reference), if I run nix build .#cross.aarch64-linux.mint-client (or any other pair of cross-compilation targets and package we built), the ./result/ is empty.

Build is successful but produces nothing, which we did not notice. I'm quite sure it used to work in the past, and I don't think we've changed anything. Seems to me like finding/filtering of artifacts silently broke. I'm quite sure we used to get an .so files just fine.

ipetkov commented 1 year ago

Thanks for the report @dpc!

Could you do a git bisect of your project to narrow down the change which introduced the failure? Assuming this leads you to a flake update we can then do a git bisect on the crane revision to narrow down what changed

dpc commented 1 year ago

I stand corrected. It looks like it never worked. :D

Is there any way I can help you debug it? Or could it be something I'm doing incorrectly?

dpc commented 1 year ago

The relevant code is https://github.com/fedimint/fedimint/blob/7299e5e6ff22991975164654e321e1477fd18754/flake.nix#L448

It's kind of the same as we use for normal "package inside workspace" build, except we inject bunch of environment variables to make C-deps compile OK, and also the $CARGO_PROFILE.

One difference that I can think of is that the binaries go into ./target/<target>/release etc. and not just ./target/release

ipetkov commented 1 year ago

Interesting, so buildPackage tries to capture cargo's build log and then install binaries based on that. Maybe it needs to be crawled better?

I'll try to take a look later, but you can also try to cat $cargoBuildLog in a post install hook to see what it contains

dpc commented 1 year ago

I think this is the one.

{"reason":"compiler-artifact","package_id":"mint-client 0.1.0 (path+file:///build/source/client/client-lib)","manifest_path":"/build/source/client/client-lib/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"mint_client","src_path":"/build/source/client/client-lib/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":null,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/source/target/aarch64-linux-android/release/libmint_client.rlib","/build/source/target/aarch64-linux-android/release/deps/libmint_client-12a62e6b92607bb2.rmeta"],"executable":null,"fresh":false}
dpc commented 1 year ago

Seems like it's looking for:

contains(["staticlib"]) or contains(["cdylib"])

but I get:

  "target": {
    "kind": [
      "lib"
    ],
dpc commented 1 year ago

OK, so the issue might be that we should set the type of the library for the build.

However, I'd say that if someone wants (needs) the normal/default library type they probably should get it as well?

ipetkov commented 1 year ago

Pretty printing the log gives:

{
  "reason": "compiler-artifact",
  "package_id": "mint-client 0.1.0 (path+file:///build/source/client/client-lib)",
  "manifest_path": "/build/source/client/client-lib/Cargo.toml",
  "target": {
    "kind": [
      "lib"
    ],
    "crate_types": [
      "lib"
    ],
    "name": "mint_client",
    "src_path": "/build/source/client/client-lib/src/lib.rs",
    "edition": "2021",
    "doc": true,
    "doctest": true,
    "test": true
  },
  "profile": {
    "opt_level": "3",
    "debuginfo": null,
    "debug_assertions": false,
    "overflow_checks": false,
    "test": false
  },
  "features": [],
  "filenames": [
    "/build/source/target/aarch64-linux-android/release/libmint_client.rlib",
    "/build/source/target/aarch64-linux-android/release/deps/libmint_client-12a62e6b92607bb2.rmeta"
  ],
  "executable": null,
  "fresh": false
}

Looks like this artifact is a regular rlib (i.e. what the compiler builds if you don't specify a staticlib or cdylib). buildPackage intentionally ignores these as they aren't really useful to anyone else besides cargo/rustc. Usually other toolchains would want to work with staticlib or cdylib types as they can actually be linked against.

My recommendation is:

ipetkov commented 1 year ago

I've opened https://github.com/ipetkov/crane/pull/225 to clarify the docs around this as this specific behavior is intentional