rust-embedded / cargo-binutils

Cargo subcommands to invoke the LLVM tools shipped with the Rust toolchain
Apache License 2.0
474 stars 41 forks source link

When given a --config argument, cargo-objcopy fails with non-error error #143

Open mcclure opened 3 months ago

mcclure commented 3 months ago

I have a project, in which when I run cargo objcopy I get this error:

image

The error says "could not compile due to 2 previous errors", but there are zero previous errors. This is unhelpful.

Repro

This is a simple "brick breaking game" targeting an unusual platform. It runs on a RISC-V softcore uploaded to a FPGA-based handheld game system. The brick break game is intended as Rust sample code for this RISC-V platform. The platform is using 32-bit RISC-V with double-precision floating point, a RISC-V variant which is "tier 3" support in Rust, which means when we build the Rust app we must (1) use a .cargo/config.toml to specify a custom platform json (2) build in nightly so we can use "build-std". This (the source linked at the top of this paragraph) builds and runs perfectly (see run.txt). Relying on the implicitly-loading .config/cargo.toml is causing multiple practical problems for us, so I am investigating other options.

Here are five versions of the program— I link them all to show you which ones work and which ones don't. In all cases the compile instructions are in run.txt but consist of installing some prerequisites then running make. The Makefile is simple and basically calls cargo build followed by cargo objcopy.

  1. Branch minibreak-agg here . Works. Config in .cargo/config.toml.
  2. Branch z_experimental_minibreak-agg-cargo-toml here . Works. Config in subdirectory riscv-build/.cargo, and the makefile cds into riscv-build before building.
  3. Branch z_experimental_minibreak-agg-cargo-toml-2 here . Breaks with above error. Config is in the root directory and specified with --config. Because files specified in a --config look one level up from the config.toml, you will have to move riscv32imafdc-unknown-none-elf.json outside the project directory before running make, one level up.
  4. Branch z_experimental_minibreak-agg-cargo-toml-3 here . Breaks with above error. Config is in a riscv32imafdc-unknown-none-elf subdirectory and specified with --config. Config specifies json at its full path.
  5. Branch z_experimental_minibreak-agg-cargo-toml-4 here . Breaks with above error. Config is in a platform directory and specified with --config. Config specifies json at its full path.

Based on these repro cases, I believe the problem occurs anytime cargo objcopy is specified with a --config argument. Because test case 5 works, I believe the problem is not caused by the platform json specified in the config having a name other than riscv32imafdc-unknown-none-elf. Because test case 3 works, I believe the problem is not caused by the platform json specified in the config having a / in the name.

Expected behavior

I expect all three of 3,4,5 above should work, since the same config file worked when loaded as .cargo/config.toml. If there is some flaw in my project which is causing it to not work, that should be printed as an error message.

Configuration

$ cargo +nightly --version
cargo 1.79.0-nightly (a59aba136 2024-03-28)
$ cargo objcopy --version
cargo-objcopy 0.3.6

In my screenshots above, I invoke the program through make, but this does not make a difference. I get the same results just running cargo from the command line.

adamgreig commented 3 months ago

Thanks for the bug report! I think the issue is that cargo-objcopy doesn't know about the --config flag for Cargo (it didn't exist at the time cargo-objcopy was written and I guess no one has noticed its absence since Cargo added it). Consequently, --config is not getting passed to Cargo, which then fails to build (since it doesn't have your config) and reports "failed due to 2 previous errors". Unfortunately cargo-objcopy has swallowed those errors and doesn't report them, leading to the confusing error message.

A fix is probably to add a new config argument here and then pass it to Cargo here, following the same pattern as the various other flags. If you're interested in giving a fix a go you'd be very welcome!

mcclure commented 3 months ago

I can't make any promises on attempting a patch, but can you clarify— if I simply invoke cargo objcopy without the --config, would you expect it to just work and not print an error, or would you expect it to do the wrong thing because it will be working with an incorrect idea about what platform it's targeting?