rust-lang / wg-cargo-std-aware

Repo for working on "std aware cargo"
133 stars 8 forks source link

Rust compiler workspace patches are being ignored when compiling with `-Zbuild-std` #78

Open raoulstrackx opened 2 years ago

raoulstrackx commented 2 years ago

Problem

When working on the stdlib, crates sometimes need to be patched. Unfortunately this isn't compatible with testing the stdlib through compilation with -Zbuild-std. The problem is that the patch section is generated on the fly by Cargo through the resolve_std function. This obviously omits any user-specified patches.

Steps

  1. Point the src directory of your toolchain to a checked-out version of the compiler
  2. Add a patch to the workspace
  3. Build a new application and specify the -Zbuild-std flag
  4. Observe that the patch isn't used.

Possible Solution(s)

No response

Notes

No response

Version

No response

ehuss commented 2 years ago

Can you say more about how you you did the first two steps? The following should work:

  1. ./x.py build library/std
  2. RUSTC=/path/to/build/triple/stage1/bin/rustc cargo build -Zbuild-std --target target

It uses the sysroot from rustc, which should have lib/rustlib/src/rust, and x.py will set up a symlink to the source directory for you.

ian-h-chamberlain commented 2 years ago

I think I have been experiencing this issue as well, I've been trying various permutations so I may not remember the exact steps that led me here, but as best I can recall:

  1. Check out https://github.com/rust-lang/rust (actually a fork in my case, but AFAICT it shouldn't matter much).

    library/std/Cargo.toml contains this:

    [dependencies]
    libc = { version = "0.2.108", default-features = false, features = ['rustc-dep-of-std'] }
  2. Add to the root /Cargo.toml and run cargo update -p libc, as recommended by rustc-dev-guide:

    [patch.crates-io]
    libc = { path = "../libc" }
  3. ./x.py build library/std

Then, in a project directory (in my case, HOST=x86_64-apple-darwin and TARGET=armv6k-nintendo-3ds):

RUSTC=build/$HOST/stage1/bin/rustc cargo build -Zbuild-std --target $TARGET

What I observe is that even though the path = "../libc" has version 0.2.108, Cargo.lock lists 0.2.108, and my crate also depends on 0.2.108, the -Zbuild-std process seems to pull in libc = "0.2.112" from crates.io (as well as 0.2.108 for my crate).

Example output:

$ cargo clean && cargo +stage1 build  --example time_rtc -Zbuild-std --target armv6k-nintendo-3ds
    Updating crates.io index
   Compiling compiler_builtins v0.1.66
   Compiling core v0.0.0 (/path/to/rust/build/x86_64-apple-darwin/stage1/lib/rustlib/src/rust/library/core)
   Compiling libc v0.2.112
   Compiling cc v1.0.69
   Compiling memchr v2.4.1
   Compiling std v0.0.0 (/path/to/rust/build/x86_64-apple-darwin/stage1/lib/rustlib/src/rust/library/std)
   Compiling libc v0.2.108 (/path/to/libc)

Since 0.2.112 does not have the local changes I have made in my local checkout of libc, the build fails for unknown symbols etc:

error[E0412]: cannot find type `sockaddr_un` in crate `libc`
  --> /path/to/rust/build/x86_64-apple-darwin/stage1/lib/rustlib/src/rust/library/std/src/os/unix/net/addr.rs:18:33
   |
18 |   fn sun_path_offset(addr: &libc::sockaddr_un) -> usize {
   |                                   ^^^^^^^^^^^ help: a struct with a similar name exists: `sockaddr_in`
   |

Something else I tried was explicitly setting libc = "=0.2.108" in library/std/Cargo.toml (keeping the [patch]), but this seems to have the same problem, but more subtle:

$ cargo clean && cargo +stage1 build  --example time_rtc -Zbuild-std --target armv6k-nintendo-3ds
    Updating crates.io index
   Compiling compiler_builtins v0.1.66
   Compiling core v0.0.0 (/path/to/rust/build/x86_64-apple-darwin/stage1/lib/rustlib/src/rust/library/core)
   Compiling libc v0.2.108
   Compiling cc v1.0.69
   Compiling memchr v2.4.1
   Compiling std v0.0.0 (/path/to/rust/build/x86_64-apple-darwin/stage1/lib/rustlib/src/rust/library/std)
   Compiling libc v0.2.108 (/path/to/libc)

In this case, it seems to just pull 0.2.108 from crates-io (note there is no ($PATH) listed next to it.

The most reliable workaround I've found so far is to actually ./x.py build --target=$TARGET library/std and use the resulting built std, instead of using -Zbuild-std, but it seems like there should be some way to leverage build-std to accomplish this.

Edit: I found I actually can use build-std if I update the [dependencies] directly, e.g.

# In library/std/Cargo.toml:
libc = { git = "https://github.com/ian-h-chamberlain/libc.git", default-features = false, features = ['rustc-dep-of-std'] }

I can also use path = "", but the path must be absolute, since a relative path that points outside the tree won't be valid anymore in the context of build/$TARGET/stage1... So a git dep is a little more flexible / reproducible, it would seem. Still, being able to use [patch] would be nicer, I think.

Let me know if I can help with providing any additional information.

raoulstrackx commented 2 years ago

Sorry I kinda forgot about this issue. I used the same workaround as @ian-h-chamberlain to resolve this for now, which obviously isn't ideal.