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

bug: VS Code fails to initialize workspace with Cargo (Rust Alanyzer) #1178

Open
spikespaz opened this issue Mar 6, 2022 · 25 comments
Open
Labels
bug priority asdf core intend to resolve soon

Comments

@spikespaz
Copy link

Describe the Bug

I am using the rust-analyzer extension for Visual Studio Code and when I open a Cargo project I see:

rust-analyzer failed to load workspace: "cargo" "--version" failed: No such file or directory (os error 2)

I have had nothing but problems trying to get other similar tools to find the shims from asdf. There has to be a method, as it is everything that I try to use with asdf-managed tools is simply inoperable.

I cannot find a setting in Code that allows me to change the path to the toolchain.

Steps to Reproduce

  1. asdf plugin add rust
  2. asdf install rust latest
  3. asdf global rust latest
  4. Test VS Code, see it can't find Cargo.
  5. asdf reshim
  6. Test again, error again.
  7. rm -rf ~/.asdf/shims
  8. asdf reshim
  9. Test again, error again.
  10. ???

Expected Behaviour

The IDEs and other tools should be able to find software managed by asdf. I have tried adding the initialization script to both .zshrc and .profile (ZSH is my login shell).

# Source the asdf version manager
[ -f '/opt/asdf-vm/asdf.sh' ] &&
  source '/opt/asdf-vm/asdf.sh'

Everything works fine from the command line.

Actual Behaviour

No tooling I try (specifically VS code in this case) can ever find binaries from ~/.asdf.

Environment

OS:
Linux jacob-thinkpad 5.17.0-2-MANJARO #1 SMP PREEMPT Fri Feb 25 11:28:23 UTC 2022 x86_64 GNU/Linux

SHELL:
zsh 5.8.1 (x86_64-pc-linux-gnu)

ASDF VERSION:
v0.9.0

ASDF ENVIRONMENT VARIABLES:
ASDF_DIR=/opt/asdf-vm

ASDF INSTALLED PLUGINS:
flutter                      https://github.com/oae/asdf-flutter.git master 1f5b9e2
java                         https://github.com/halcyon/asdf-java.git master b0341fd
nodejs                       https://github.com/asdf-vm/asdf-nodejs.git master 364c078
python                       https://github.com/danhper/asdf-python.git master 57a4d72
ruby                         https://github.com/asdf-vm/asdf-ruby.git master de49662
rust                         https://github.com/code-lever/asdf-rust.git master 0c88f99

asdf plugins affected (if relevant)

rust

@spikespaz spikespaz added the bug label Mar 6, 2022
@bitterteriyaki
Copy link

I'm experiencing the same bug, but I'm not sure if this is the fault of asdf or rust-analyzer.

@bitterteriyaki
Copy link

Hey, @spikespaz. I found a quick fix for this problem. Add the shims folder to the env vars of your .bash_profile (or .zprofile, if you are using Zsh):

# Import the default profile
if [ -f "/etc/profile" ]; then
  source "/etc/profile"
fi

# Set the list of directories that Bash/Zsh searches for programs
path=(
  $HOME/.asdf/shims
  $path
)

I want to mention my gratitude to @baliestri, who helped me solve this problem.

@baliestri
Copy link

path only works with zsh, if you are using bash do it like this: export PATH=$HOME/.asdf/shims:$PATH

@chaosharmonic
Copy link

chaosharmonic commented May 11, 2022

So in an Arch derivative, which zprofile file am I looking for -- /etc/zsh/zprofile, the /etc/profile file it's importing via its single default line, or $ZDOTDIR/.zprofile? (And if the latter doesn't exist for whatever reason, should I touch that?)

@soukyomi also it's definitely asdf -- I'm experiencing an identical issue, but with deno.

@baliestri
Copy link

Only if you want you can write to the .zshrc file.

I use it as follows:

path=(
  $HOME/.asdf/shims
  $HOME/.local/{bin,sbin}
  /usr/{bin,sbin}
  /usr/local/{bin,sbin}
  $path
)

@jthegedus
Copy link
Contributor

jthegedus commented Jun 20, 2022

This issue happens to me with some tools and not others. I have experienced this with Rust Analyzer myself, but didn't stick with Rust long enough to resolve or investigate in any meaningful way.

Given the unpredictable nature of this, I expect that this depends on how the plugin itself tries to find tools and what it does in the background to resolve missing tools. For instance, I use the shellcheck VSCode plugin, but it can't find my asdf installed Shellcheck version (I am unsure how it searches for it) and then proceeds to download and install a version to somewhere on my machine. Again, since this happens with some plugins and not others I expect it is because of the way the tool is located by the plugin. Happy to be corrected, because if this is an easy fix for us, then great.

The asdf.sh script which is sourced in your shell (as part of step 3 of the setup guide) should source .asdf/shims, so it should already be in your PATH and not needed to be added manually.

Is sourcing it in the "profile" file different to VSCode? Why would this be?

@spikespaz
Copy link
Author

Because the extension isn't looking at your PATH, it's looking through files in /usr/bin, /usr/sbin, and /bin. It never sees that the executables are in ~/.asdf/shims. I would say it's a problem with the extensions that share this behavior, but considering that they are looking in standardized locations... ASDF is not Nix.

@jthegedus
Copy link
Contributor

jthegedus commented Jun 23, 2022

@spikespaz As you say in the initial issue:

The IDEs and other tools should be able to find software managed by asdf

They can if they look in the right place.

I would say it's a problem with the extensions that share this behavior, but considering that they are looking in standardized locations

Standardized locations for tools installed at the system level, non-version managed.

ASDF is not Nix.

Yes, it is not Nix. Our comments on that are here https://asdf-vm.com/guide/introduction.html

Can someone speak as to why @bitterteriyaki method supposedly works?

I am inclined to mark this as unfixable by asdf core and close the Issue.

@Rotwang
Copy link

Rotwang commented Jul 6, 2022

@jthegedus it's such a fundamental issue for users of asdf, like it's one of the first things I stumbled on. Right now the best solution for me is to run code from the terminal session. It would be good if there was at least some kind of infrormation/doc pointing to the solution.

edit: I know it's not asdf issue per se but people think it is, for example look here: https://elixirforum.com/t/failed-to-run-elixir-command-error-in-vs-code/31047/6

edit2: so in my case when I have been sourcing $HOME/.asdf/asdf.sh in ~/.bashrc then it broke but when I added that source to ~/.bash_profile then it worked. So my conclusion is that vscode will abide by the ~/.bash_profile or .zprofile (confirming what @bitterteriyaki have said already)

edit3: I've straced vscode and it doesn't look to me like it's directly sourcing the files, my assumption is that something launching it has already done that.

@jthegedus
Copy link
Contributor

it's such a fundamental issue for users of asdf, like it's one of the first things I stumbled on

I am not sure what we can do about it though.

Copying shims to /usr/bin or /usr/sbin type locations might work, but we can't guess which location each VSCode plugin would decide to use, so we would have to copy to ALL of the possible locations, which does not feel like the right thing to do.

@Rotwang
Copy link

Rotwang commented Jul 7, 2022

I was following this https://asdf-vm.com/guide/getting-started.html#_3-install-asdf and if there was a mention like "if you're facing issues with your code editor/3rd party tooling being unable to find binaries then add this to your ~/.bash_profile or whatever ..." then it would save a ton of my time (and others as well).

@jthegedus
Copy link
Contributor

So my conclusion is that vscode will abide by the ~/.bash_profile or .zprofile

Is this captured in VSCode documentation anywhere? Before we recommend to all users in the docs I want to understand the issue completely. Is VSCode strictly tied to your Shell? A specific Shell, or the default Shell? If I use Fish will VSCode run that Shell's equivalent of profile?

Lots of questions to understand what is actually happening before we can recommend any solution. You have done some great digging, thanks @Rotwang If you have more time to further investigate that would be appreciated.

@Stratus3D
Copy link
Member

Is this captured in VSCode documentation anywhere?

Lots of questions to understand what is actually happening before we can recommend any solution.

This is key. If the behavior of VSCode is not documented anywhere, we cannot document a proper solution to this problem in the asdf docs. If VSCode doesn't clearly explain how it finds commands we can provide any official suggestions on how to work around the issue. Based on the conversation here there is nothing indicating any issues with asdf itself. If there aren't official docs on how VSCode handles this we should close this issue.

@keithlayne
Copy link

I have been wrestling with this for quite a while. I always launch vscode from the shell, which is generally helpful, vscode inherits the path and everything seems good.

My workflow for working on multiple projects is to open multiple vscode windows, and (no evidence for this) it seems like the directory that you open the initial window from is the environment that works. Actually, I just did a test locally - I exited vscode, loaded a project with an asdf config, and then opened another project. As I expected, I saw the bad behavior from a specific extension. My takeaway here is that having the shims dir on the path is not sufficient in all cases.

I completely agree that it's unclear how to really address this - it probably depends on extension implementations to some extent. My intuition says that a vscode extension would be the right answer, but I have no clue if vscode exposes an API that would a) be useful and b) work universally.

I had a thought a few minutes ago, that direnv works in a vaguely similar way, so it might provide some clues. There are some direnv extensions for vscode, but it looks like they have limitations.

Not sure if any of this is helpful 🤷‍♂️

@keithlayne
Copy link

This feels relevant: microsoft/vscode#130493

But, I don't really know how asdf works. I need to do some reading, But, feels like if the node extension host (which runs per-workspace) were launched with the right environment and/or ran the asdf hook (?) first then everything would be happy.

@Rotwang
Copy link

Rotwang commented Jul 9, 2022

Lots of questions to understand what is actually happening before we can recommend any solution. You have done some great digging, thanks @Rotwang If you have more time to further investigate that would be appreciated.

@jthegedus

There are two questions to be answered in my mind:
Question "A" why does the ~/.bash_profile make vscode work while ~/.bashrc doesn't (analogous to zshell's rc files).
Question "B" what environment do the graphical applications run with (ones that don't go near shell when being executed)

A) Actually vscode tends to launch it's children through a login shell, here is strace output (my initial findings were not quite correct):

[pid  6886] execve("/bin/bash", ["/bin/bash", "-ilc", "'/usr/share/code/code' --ms-enable-electron-run-as-node -p '\"dc5562613985\" + JSON.stringify(process.env) + \"dc5562613985\"'"],  ...

What you can see here is vscode starting a login shell. Excerpt from bash manpage:

When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable.
[...]
When an interactive shell that is not a login shell is started, bash reads and executes commands from /etc/bash.bashrc and ~/.bashrc, if these files exist.

So here is the reason, I had my . $HOME/.asdf/asdf.sh in .bashrc and the .bash_profile was separate from it (i.e. it was empty) so vscode couldn't get the right path since it starts the login shell.

When I changed my user's shell (chsh -s /bin/sh myuser) to sh then the vscode would exec /bin/sh -ilc instead (which would in turn source its own login files (/etc/profile and .profile if they exist).

B) It's difficult to tell on linux because there are so many different ways you can set up your graphical environment. There are many desktop managers (login things that make you enter password and they spin up your gnome/kde/fluxbox/etc. for you) that can be set up in a different way. I'm using ubuntu 20.04 with lightdm and what it does once it authenticates you and runs your session is it runs a wrapper script (located in /usr/sbin/lightdm-session) that sources ~/.profile and ~/.xprofile, GDM seems to be following suit with its /etc/gdm3/Xsession.
You end up with variables from /etc/profile and $HOME/.{profile,xsession}

A note on PAM we shouldn't forget that on linux the authentication is done by PAM which is going to provide its own variables from /etc/environment and ~/.pam_environment by default but it depends on PAM's configuration.

Having said all that what I did in the end was:

  • Put the . $HOME/.asdf/asdf.sh into the ~/.bashrc
  • Source .bashrc in the ~/.profile (courtesy of ubuntu's defaults):
if [ -n "$BASH_VERSION" ]; then
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then
	. "$HOME/.bashrc"
    fi
fi
  • Got rid of ~/.bash_profile since the ~/.profile seems to be the common denominator here (both for graphical and shell sessions).

I hope that helps.

edit: typo and minor semantic mistake

@keithlayne
Copy link

AFAIK, .bash_profile is always loaded, .bashrc is only loaded for interactive sessions. Analagous for zsh.

@Rotwang
Copy link

Rotwang commented Jul 10, 2022

AFAIK, .bash_profile is always loaded, .bashrc is only loaded for interactive sessions. Analagous for zsh.

Not quite, if you look up the INVOCATION section of the bash 5 manual you can find that for a login shell (login shell can be interactive but doesn't have to be) following files are being sourced: /etc/profile, ~/.bash_profile, ~/.bash_login, and ~/.profile (in that order). For an interactive bash session that is not a login shell /etc/bash.bashrc and ~/.bashrc, are being read.

Conclusion is that ~/.bash_profile and ~/.bashrc are independent of each other and being read at different times. A lot of people will source their ~/.bashrc inside ~/.bash_profile or ~/.profile and that's why it looks like ~/.bashrc is being always read (but it doesn't have to be true).

@jthegedus
Copy link
Contributor

@keithlayne That VSCode Issue is interesting, thanks. You may be interested in https://github.com/asdf-community/asdf-direnv

@Rotwang That is a lot of very useful information, thanks for your time & effort!

So what I have learned is this:

  • VSCode starts via a login shell
  • ~/.profile is the most common config file loaded by login shells, but it really depends
  • the dir that VSCode opens in the explorer tab determines the location for asdf resolution when commands are executed by VSCode Extensions (I tested this one myself)

What we need to do:

  • make list of ~/.profile-like files loaded by each of the Shells asdf explicitly supports (Bash, ZSH, Fish, Elvish)
  • write docs to guide users to source $HOME/.asdf/asdf.sh in file determined above or just .*rc within that file
  • write docs/FAQ entry for this mess

Does this sound reasonable to everyone? @Stratus3D ?


I wonder how *Nix and Docker-based version-managed projects handle these issues, or is their workflow that the IDE Extensions just not use the version managed tooling?

@jthegedus jthegedus added the priority asdf core intend to resolve soon label Jul 12, 2022
@keithlayne
Copy link

the dir that VSCode opens in the explorer tab determines the location for asdf resolution when commands are executed by VSCode Extensions (I tested this one myself)

This is interesting, because it seems to conflict with my experience with multiple workspaces open. This isn't super easy to test, but I have an extension that only works when I load from the console (avoiding the .profile question for now) and it's the first vscode window opened. If you already tested that specifically, then maybe an answer is closer for me than I thought.

@jthegedus
Copy link
Contributor

Perhaps I got lucky. I had the below behaviour:

~/.tool-versions         < empty
~/somedir/.tool-versions < deno version here
  • Open VSCode, select directory to open from landing page UI, open in ~/somedir. Correctly resolves Deno version
  • Open integrated terminal in ~/somedir & run code ~
  • VSCode(window 2) opens in ~ and correctly errors trying to resolve Deno version. The Output tab shows the asdf error when the Extension tried to start the Deno Language Server:
No version is set for command deno
Consider adding one of the following versions in your config file at ~/.tool-versions
deno 1.22.1

So it is correctly trying to resolve the tool from the directory it was opened in and not from. At least for me, and with this particular Extension. The Deno extension might just be super resilient. As for my setup while testing this:

  • Windows11 with WSL2 Ubuntu 20.22
  • default shell is Nushell with asdf configured
  • but no nushell was output in strace, it seemed to resolve /usr/bin/sh, and the default Ubuntu ~/.profile does source ~/.bashrc however I do not have asdf configured with in any config other than Nushell.

Extension variance is definitely a factor in this, but not a predictable one and certainly not solvable by us.

User shell setup is also a nightmare, hence why we didn't want to get into the game of automatically modifying configs.


Additionally, I just got VSCode@1.69 which has unrelated, but further Shell integrations

This release we improved integration with bash-preexec

So VSCode are actively working in this area and can potentially introduce changes which would affect our advice. We must remain aware.


I would like to not get stuck in the weeds of comparing each others Shell setups if we agree on the "what we need to do" items I outlined above.

@richardhp
Copy link

sudo ln -s ~/.asdf/shims/cargo /usr/bin/cargo

worked for me

@roele
Copy link

roele commented Feb 15, 2023

Problem is also being discussed in rust-analyzer/issues/3154

@yozachar

This comment was marked as outdated.

@yozachar
Copy link

This seems like a VSCode issue rather than asdf. Ref: microsoft/vscode#187955

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug priority asdf core intend to resolve soon
Projects
None yet
Development

No branches or pull requests