Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cargo in WSL prefers windows user config #11677

Open
weltensturm opened this issue Feb 3, 2023 · 8 comments
Open

Cargo in WSL prefers windows user config #11677

weltensturm opened this issue Feb 3, 2023 · 8 comments
Labels
C-bug Category: bug E-medium Experience: Medium O-windows OS: Windows S-needs-mentor Status: Issue or feature is accepted, but needs a team member to commit to helping and reviewing.

Comments

@weltensturm
Copy link

weltensturm commented Feb 3, 2023

Problem

Cargo in WSL uses the windows host cargo config in %UserProfile%/.cargo/config.toml, and it looks like values there are preferred over the WSL ~/.cargo/config.toml.
When there is either rustc-wrapper or target-dir configured, cargo in WSL fails because it does not have access to those paths.

edit: The project I am trying to compile is in a folder symlinked to /c/Users/<user>/projects. It looks like cargo unwraps the symlink, then it's pretty clear why it finds the windows config first. But I am not sure this behavior is preferrable.
/edit

I have a ~/.cargo/config.toml in WSL with the following content:

[build]
rustc-wrapper = "/home/<user>/.cargo/bin/sccache"
target-dir = "/home/<user>/.cargo/targets"

But cargo prefers the host values.
Error when rustc-wrapper is set on windows:

error: failed to run `rustc` to learn about target-specific information

Caused by:
  could not execute process `/mnt/c/Users/<user>/C:/Users/<user>/.cargo/bin/sccache.exe rustc - --crate-name ___ --print=file-names --crate-type bin --crate-type rlib --crate-type dylib --crate-type cdylib --crate-type staticlib --crate-type proc-macro --print=sysroot --print=cfg` (never executed)

Caused by:
  No such file or directory (os error 2)

Error when target-dir is set on windows:

error: failed to join paths from `$LD_LIBRARY_PATH` together

Check if any of path segments listed below contain an unterminated quote character or path separator:
    "/mnt/c/Users/<user>/C:/Users/<user>/.cargo/targets/debug/deps"
    "/home/<user>/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib"
    "/home/<user>/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib"

Caused by:
  path segment contains separator `:`

which { rustup cargo rustc } shows WSL binaries, so there is no issue with accidentally invoking host binaries.

When I delete the contents of the windows cargo.toml, the WSL config is applied correctly.

Steps

  1. Set up WSL
  2. Install cargo/rust in windows host and in WSL
  3. Set up a cargo project in %UserProfile%/projects/<name>
  4. Create a config.toml in %UserProfile%/.cargo with either rustc-wrapper or target-dir
  5. In WSL: Create a symlink in ~/ to /mnt/c/Users/<user>/projects
  6. In WSL: cargo run in ~/projects/<name>

Possible Solution(s)

Change cargo so it doesn't "unwrap" symlinks when looking for configs.
If pwd prints ~/projects/, cargo should not behave like it's in /mnt/c/Users/<user>/projects.

Notes

wsl -v -l

WSL version: 1.0.3.0
Kernel version: 5.15.79.1
WSLg version: 1.0.47
MSRDC version: 1.2.3575
Direct3D version: 1.606.4
DXCore version: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
Windows version: 10.0.22621.1105

Version

cargo 1.67.0 (8ecd4f20a 2023-01-10)
release: 1.67.0
commit-hash: 8ecd4f20a9efb626975ac18a016d480dc7183d9b
commit-date: 2023-01-10
host: x86_64-unknown-linux-gnu
libgit2: 1.5.0 (sys:0.16.0 vendored)
libcurl: 7.86.0-DEV (sys:0.4.59+curl-7.86.0 vendored ssl:OpenSSL/1.1.1q)
os: Ubuntu 22.04 (jammy) [64-bit]
@weltensturm weltensturm added the C-bug Category: bug label Feb 3, 2023
@weihanglo
Copy link
Member

My guess is that home crate only respects USERPROFILE even on WSL.

pub fn home_dir_inner() -> Option<PathBuf> {
env::var_os("USERPROFILE")
.filter(|s| !s.is_empty())
.map(PathBuf::from)
.or_else(home_dir_crt)
}
#[cfg(not(target_vendor = "uwp"))]
fn home_dir_crt() -> Option<PathBuf> {
unsafe {
let mut path: Vec<u16> = Vec::with_capacity(MAX_PATH as usize);
match SHGetFolderPathW(0, CSIDL_PROFILE as i32, 0, 0, path.as_mut_ptr()) {
S_OK => {
let len = wcslen(path.as_ptr());
path.set_len(len);
let s = OsString::from_wide(&path);
Some(PathBuf::from(s))
}
_ => None,
}
}
}

I don't really have my Windows close by though. I believe @epage is more helpful. @epage, do you have any experience in WSL with home directory setup?

@weihanglo weihanglo added the O-windows OS: Windows label Feb 7, 2023
@weltensturm
Copy link
Author

weltensturm commented Feb 7, 2023

It works when copying the project to a "native" WSL directory, it's only when the project is in some way under a symlink to /mnt/c/Users/<user>/ or any child directory where the problem occurs. I assume it happens because rust unwraps the symlink path and uses the real/physical path to search all parent directories for configs.
USERPROFILE is empty in WSL.
I only checked that case after I created this issue, so apart from the edit block I left the description largely as it is, to show how confusing it is from the user side. But it's not as bad as it sounds, should I add a "when project is in a symlink to the windows user directory` to the title?

@arlosi
Copy link
Contributor

arlosi commented Feb 8, 2023

I assume it happens because rust unwraps the symlink path and uses the real/physical path to search all parent directories for configs

Yes, this is correct (it's unrelated to WSL). std::env::current_dir() calls getcwd on Linux, which resolves symlinks. Cargo never sees the version of the path that contains the symlinks.

@weihanglo weihanglo added S-needs-mentor Status: Issue or feature is accepted, but needs a team member to commit to helping and reviewing. E-medium Experience: Medium labels Jun 29, 2023
@n-tropy247
Copy link

My guess is that home crate only respects USERPROFILE even on WSL.

pub fn home_dir_inner() -> Option<PathBuf> {
env::var_os("USERPROFILE")
.filter(|s| !s.is_empty())
.map(PathBuf::from)
.or_else(home_dir_crt)
}
#[cfg(not(target_vendor = "uwp"))]
fn home_dir_crt() -> Option<PathBuf> {
unsafe {
let mut path: Vec<u16> = Vec::with_capacity(MAX_PATH as usize);
match SHGetFolderPathW(0, CSIDL_PROFILE as i32, 0, 0, path.as_mut_ptr()) {
S_OK => {
let len = wcslen(path.as_ptr());
path.set_len(len);
let s = OsString::from_wide(&path);
Some(PathBuf::from(s))
}
_ => None,
}
}
}

I don't really have my Windows close by though. I believe @epage is more helpful. @epage, do you have any experience in WSL with home directory setup?

Can confirm, this resolved for me after creating a USERPROFILE environment variable in WSL that pointed to the right location.

@bingzhux
Copy link

bingzhux commented Dec 18, 2023

this issue makes me struggled for a very very long time.

Actually, all I wanted is just very simple:
As long as I enter WSL2 environment to build my rust project, cargo should always use WSL2's cargo configuration file, which is located at WSL2:/home/wsl2user/.cargo/config.toml

but currently in WSL2:

  • If my current rust project folder is under non-mnt (not /mnt/). directories, e.g. /home/wsl2user/rustdev/., cargo will always or only use WSL2's cargo configuration file, which is WSL2: /home/wsl2user/.cargo/config.toml

  • If my current rust project folder is under mnt directories /mnt/c/Users/winuser/..., cargo will combine to use host Windows configuration file, which is located at Windows: C:\Users\winuser\.cargo\config.toml, as well as WSL2's configuration file mentioned above.

@weihanglo
Copy link
Member

Forgot to say, home was migrated into rust-lang/cargo repo #11359 last year, so cargo maintainers here do have permissions to update it.

@CGMossa
Copy link

CGMossa commented Feb 12, 2024

What's the status of this? I tried to add .cargo/config.toml with an [env], but it won't detect those variables either. I'm detecting them via env::var_os. I'm on WSL2.

Update: If I use env::var then this works. Somehow there is a difference between env::var and env::var_os on WSL.

@arlosi
Copy link
Contributor

arlosi commented Feb 12, 2024

@CGMossa what your encountering sounds like a different problem. If you can create a minimal reproduceable example, please create a new issue with details.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: bug E-medium Experience: Medium O-windows OS: Windows S-needs-mentor Status: Issue or feature is accepted, but needs a team member to commit to helping and reviewing.
Projects
None yet
Development

No branches or pull requests

6 participants