Cargo in WSL prefers windows user config
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
- Set up WSL
- Install cargo/rust in windows host and in WSL
- Set up a cargo project in
%UserProfile%/projects/<name> - Create a
config.tomlin%UserProfile%/.cargowith eitherrustc-wrapperortarget-dir - In WSL: Create a symlink in
~/to/mnt/c/Users/<user>/projects - In WSL:
cargo runin~/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]
My guess is that home crate only respects USERPROFILE even on WSL.
https://github.com/rust-lang/cargo/blob/82c3bb79e3a19a5164e33819ef81bfc2c984bc56/crates/home/src/windows.rs#L9-L30
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?
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?
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.
My guess is that
homecrate only respectsUSERPROFILEeven on WSL.https://github.com/rust-lang/cargo/blob/82c3bb79e3a19a5164e33819ef81bfc2c984bc56/crates/home/src/windows.rs#L9-L30
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.
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.
Forgot to say, home was migrated into rust-lang/cargo repo https://github.com/rust-lang/cargo/pull/11359 last year, so cargo maintainers here do have permissions to update it.
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.
@CGMossa what your encountering sounds like a different problem. If you can create a minimal reproduceable example, please create a new issue with details.