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

rustup doc does not work on Windows/WSL #2206

Closed
kobenauf opened this issue Jan 18, 2020 · 31 comments · Fixed by #2792
Closed

rustup doc does not work on Windows/WSL #2206

kobenauf opened this issue Jan 18, 2020 · 31 comments · Fixed by #2792
Labels
bug forwarded This issue as been forwarded "upstream" O-linux Linux related O-windows Windows related

Comments

@kobenauf
Copy link

Problem
On Windows, using WSL 2, rustup doc --std (or any other rustup doc command) opens firefox correctly (because I have BROWSER=firefox.exe), but the browser does not load a file; the browser is empty/blank.

I found the rustup docs here:

~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/share/doc/rust/html/index.html

I could open this manually like this:

firefox.exe file://///wsl$/Ubuntu/home/kobenauf/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/share/doc/rust/html/index.html

Or like this:

firefox.exe `wslpath -w ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/share/doc/rust/html/index.html`

Possible Solution(s)
Consider making rustup doc aware of how to open files on WSL so they open the docs as expected.

Notes

Output of rustup --version:
rustup 1.21.1 (7832b2e 2019-12-20)

Output of rustup show:
Default host: x86_64-unknown-linux-gnu
rustup home: /home/kobenauf/.rustup

installed toolchains

stable-x86_64-unknown-linux-gnu
nightly-x86_64-unknown-linux-gnu (default)

installed targets for active toolchain

wasm32-unknown-unknown
x86_64-pc-windows-gnu
x86_64-unknown-linux-gnu

active toolchain

nightly-x86_64-unknown-linux-gnu (default)
rustc 1.42.0-nightly (689fca01c 2020-01-17)

@kobenauf kobenauf added the bug label Jan 18, 2020
@kinnison
Copy link
Contributor

WSL is, as far as Rustup is concerned, Linux. As such, it's using the xdg-open embedded in the opener crate. @Seeker14491 do you have any ideas how this might be accomodated?

@kinnison kinnison added the forwarded This issue as been forwarded "upstream" label Jan 19, 2020
@rbtcollins
Copy link
Contributor

We could sniff the kernel to detect WSLv1, but that won't help on WSLv2. I am not sure how to detect WSLv2 at this point. Perhaps there will be an lsb-release metadata tag of some sort.

I think the BROWSER command here is the problem: firefox.exe isn't a wsl-aware command. I suggest making a firefox wrapper script within WSL itself that:

  • checks $1 for filesystem parameters
  • converts them as appropriate with wslpath etc
  • then calls firefox.exe

@Seeker14491
Copy link
Contributor

As kinnison said, the opener crate is currently oblivious to WSL and so just uses xdg-open like any other Linux. While the open node package (which opener took inspiration from) has checks for WSL, I'm not sure that's the right approach. Perhaps it is xdg-open which should support WSL, like what's proposed in this patch.

@kobenauf
Copy link
Author

For what it's worth, the patch @Seeker14491 linked for xdg-open was originally reported Dec 2018, so chances it is going to get fixed there seem low.

@kinnison
Copy link
Contributor

@kobenauf It seems to me that it'd be up to the WSL distributions to realise they're on WSL/WSL2 and locally patch their xdg-open if upstream won't. @Seeker14491 is there any way (for now?) that the opener crate might detect WSL/WSL2 and use an internal patched version of xfg-open short-term?

@therealkenc
Copy link

I am not sure how to detect WSLv2 at this point

This, but RIIR.

Perhaps it is xdg-open which should support WSL

Or WSL users can (and do) swap out their xdg-open for a wrapper that takes into account the path conversion.

This is unrelated to MIcrosoft/WSL#4649. There is some navel gazing in #3907, others. Another option is to have rustup serve the page on http://localhost:someport/somepath instead of file://somewhere if you want to be schmancy. Bonne chance.

@Seeker14491
Copy link
Contributor

Well currently users can't just swap out their xdg-open, because we're shipping our own xdg-open, though we could change the opener crate to try using the system xdg-open first before falling back to our own xdg-open.
Of course, it would be nice if this worked out-of-the-box, so @kinnison's suggestion seems like a viable option. Basically, we would use the wslpath command in our modified xdg-open to convert from a WSL path to a Windows path, whenever the script tries to launch an .exe.

@therealkenc
Copy link

therealkenc commented Jan 26, 2020

Well currently users can't just swap out their xdg-open

Okay got it. Users not only can swap their xdg-open(1), they do; but that won't work because xdg-open(1) it isn't actually spawned.

@kinnison's suggestion is workable.

we could change the opener crate to try using the system xdg-open first before falling back to our own xdg-open.

Yes, there's a large(ish) community using native chrome/firefox on WSL with remote X11 (VcXsrv and such). For them native system xdg-open(1) (and opener::open()) works. One way to spot those folks is check existence $DISPLAY.

whenever the script tries to launch an .exe

Counting on the .exe extension is one heuristic you can use. That approach leans hard on $BROWSER being set per the OP. Another way to go is to spawn powershell.exe start <wsl path>, which is the approach taken in the patch you cite. That's probably better (for some value of better).

Great to see out-of-the box would-be-niceness for WSL being entertained. Big 👍

@rbtcollins
Copy link
Contributor

How does invoking the non-WSL binary work? Does it show up in a recognisable path? We could do path normalisation things if (pseudo code):

which(browser)
if wsl-windows-image
   wsl-ify-path
fork-and-exec

@therealkenc
Copy link

therealkenc commented Jan 27, 2020

How does invoking the non-WSL binary work?

It's a binfmt_misc under the hood. At the execve() syscall level it looks just like anything else that has a custom interpreter. The exeve() syscall follows the $PATH resolution rules same as usual. You can mostly ignore the details.

Does it show up in a recognisable path?

That's a good question, and the answer is "not necessarily". There are options controlled by wsl.conf. (1) WSL users might not have drvfs (f.e. /mnt/c) automounted. That much can be a hard fail. (2) Even if they mount drvfs, users can opt out of importing the Windows %PATH% into WSL $PATH.

And... even if users haven't futzed the wsl.conf defaults, there isn't any guarantee firefox.exe is in their Window %PATH%. In particular chrome.exe usually isn't. MS Edge poses it's own challenges (and that's the default for anyone who hasn't gotten around to installing Firefox or Chrome).

This is one reason spawning powershell.exe start is probably a (scary quote) "better" approach than hoping that path walking firefox.exe works out. Or that $BROWSER is set in the first place. You know where powershell.exe lives, %PATH% import or not.

We could do path normalisation things if (pseudo code):

I assume implied here is trying to do a wslpath(1) equivalent yourself rather than spawning the utility. Anything can be done, but it isn't as straightforward as it sounds. In particular there is no straightforward way to get the name of the distro once you're inside WSL (and hence glean the correct \\wsl$\distroname\).

All that said there isn't anything (strictly-speaking) incorrect with the psudocode. Left undrescribed is how if wsl-windows-image should behave. You could try a file(1) equivalent, but that might not give you the sort of result you expect (because... complicated). Alternately you can glean whether the browser executable is on a "windows path", but that isn't as straightforward as it sounds either because there is no guarantee the "Windows path" lives on /mnt/c. Docker-types in particular like mounting on /c via the wsl.conf [automount] root option. You have to parse /proc/self/mounts to get it right.

All of which is doable.

Alternately something like:

if not xdg-open-equivalent-succeeded($native_url_path)
  if on-wsl()   # WSL 1 or 2 doesn't actually matter
     $win_url_path = fork_and_exec("/bin/wslpath", "-w", $native_url_path)
     fork_and_exec("powershell.exe", "start", $win_url_path)

Noting deliberate absence of $browser variable above, because not this pseudocode's responsibility.

@kinnison
Copy link
Contributor

If the system xdg-open is correctly updated on WSL, then that seems like the safest option frankly.

@therealkenc
Copy link

If the system xdg-open is correctly updated on WSL, then that seems like the safest option frankly.

That's the standard operating procedure (if there is such a thing). WSL users wrap their xdg-open. It's (probably) a stretch for xdg-open(1) proper to change their ways; it isn't xdg-util's problem, at least arguably. If opener::open() wants to act as the xplat intermediary, that's fine. WSL is "another platform". That is probably where the "if (wsl)" would go, if the crate is insistent on rolling it's own xdg-open equivalent for the Real Linux™ (meaning, freedesktop.org) case rather than spawning the real thing.

@paulirotta

This comment has been minimized.

@rbtcollins

This comment has been minimized.

@vkottler
Copy link

vkottler commented Sep 7, 2020

If the system xdg-open is correctly updated on WSL, then that seems like the safest option frankly.

That's the standard operating procedure (if there is such a thing). WSL users wrap their xdg-open. It's (probably) a stretch for xdg-open(1) proper to change their ways; it isn't xdg-util's problem, at least arguably. If opener::open() wants to act as the xplat intermediary, that's fine. WSL is "another platform". That is probably where the "if (wsl)" would go, if the crate is insistent on rolling it's own xdg-open equivalent for the Real Linux™ (meaning, freedesktop.org) case rather than spawning the real thing.

Example solution I came up with:

#!/bin/bash

if [ "$#"  -lt 1 ]; then
        echo "$0: no args"
        exit 1
fi

OPEN_PATH=`wslpath -w $1 2>/dev/null`

if [ $? -eq 0 ]; then
        wslview $OPEN_PATH
else
        wslview $1
fi

Write this bash to a script (e.g. $HOME/bin/wsl_browser.sh), then export BROWSER="$HOME/bin/wsl_browser.sh" and sudo ln -s $HOME/bin/wsl_browser.sh /usr/local/bin/xdg-open and seems to get rid of most problems I have at CLI. Haven't found a use-case to keep any form of a real xdg-open around on wsl.

@kinnison
Copy link
Contributor

That's an interesting approach, and much closer to logic that opener could plausibly think about using. It could detect the presence of wslpath and wslview and do the above, falling back to the system xdg-open and/or its internal implementation as needed. @Seeker14491 would it make sense for someone to open an issue to that effect over on your repo?

@therealkenc
Copy link

therealkenc commented Sep 11, 2020

The wslpath application is is part of WSL and always available (it is actually a symlink to WSL's /init). The wslview app is part of wslu is here. It is a short shell script which is effectively powershell.exe start <url> with some sophistication. Same as "alternately something like" from January.

@Seeker14491
Copy link
Contributor

@kinnison definitely. I think this approach could work, but I'm thinking instead we first check if there is a system xdg-open, falling back to the wslpath and wslview approach. This is to allow the use of a customized xdg-open if the user has one, and also to allow opening with native Linux applications. At least on the Ubuntu WSL, xdg-open is not installed by default, so the wslpath and wslview fallback would get used by default, which I think is the right default.

I'm additionally considering introducing a second API function to the opener crate; something like open_browser() that would explicitly use the $BROWSER environment variable before falling back to the generic opening strategy. On WSL, we could check for $BROWSER being set to an .exe, and if so, convert the path with wslpath before opening it.

@workingjubilee
Copy link
Member

@rustbot label: +O-windows +O-linux

@rustbot rustbot added O-linux Linux related O-windows Windows related labels Apr 29, 2021
@kartva
Copy link

kartva commented Jun 4, 2021

Any progress on this PR?

@kinnison
Copy link
Contributor

kinnison commented Jun 8, 2021

@DesmondWillowbrook I'm afraid we're beholden to someone providing @Seeker14491 with the help needed to get the opener crate to the point that it can better support this use-case.

Seeker14491 added a commit to Seeker14491/rustup.rs that referenced this issue Jun 13, 2021
rbtcollins pushed a commit to rbtcollins/rustup.rs that referenced this issue Jul 11, 2021
@strugglebak
Copy link

If the system xdg-open is correctly updated on WSL, then that seems like the safest option frankly.

That's the standard operating procedure (if there is such a thing). WSL users wrap their xdg-open. It's (probably) a stretch for xdg-open(1) proper to change their ways; it isn't xdg-util's problem, at least arguably. If opener::open() wants to act as the xplat intermediary, that's fine. WSL is "another platform". That is probably where the "if (wsl)" would go, if the crate is insistent on rolling it's own xdg-open equivalent for the Real Linux™ (meaning, freedesktop.org) case rather than spawning the real thing.

Example solution I came up with:

#!/bin/bash

if [ "$#"  -lt 1 ]; then
        echo "$0: no args"
        exit 1
fi

OPEN_PATH=`wslpath -w $1 2>/dev/null`

if [ $? -eq 0 ]; then
        wslview $OPEN_PATH
else
        wslview $1
fi

Write this bash to a script (e.g. $HOME/bin/wsl_browser.sh), then export BROWSER="$HOME/bin/wsl_browser.sh" and sudo ln -s $HOME/bin/wsl_browser.sh /usr/local/bin/xdg-open and seems to get rid of most problems I have at CLI. Haven't found a use-case to keep any form of a real xdg-open around on wsl.

kind of tricky, but it works well, thanks a lot !!!

@dssocool
Copy link

dssocool commented Mar 3, 2022

If you're in Windows11 with wslg, then just install firefox in your WSL Ubuntu, and run "rustup doc".

The wslg will open the firefox brower in WSL with the right content for you. Works like a charm!

@1216892614
Copy link

Why dont open rustdoc in a server like Trunk or Live Server.
That can help a lot.

@wukaijin
Copy link

Dear all,

I found an easy way to solve this question.

Adding the prompt below in .zshrc or .bashrc:

export BROWSER="/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe"

It works for me. Maybe you should alter the real executing path of browser. ❤️

@AbdulxaqDev
Copy link

Hello everyone.

I just found out to open a link in browser with WSL with following command.

cmd.exe /C start http://link/you/want/to/open

And, I just put the link of rust book to open with an alias in WSL. The book, which is in .cargo folder, in home directory.

alias open_rust_book='cmd.exe /C start file://wsl.localhost/Ubuntu-20.04/home/omni/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/share/doc/rust/html/book/ch01-00-getting-started.html'

And it worked. I am new to Rust language, learning form its book, so I ended up with this.

@rami3l
Copy link
Member

rami3l commented Apr 15, 2024

alias open_rust_book='cmd.exe /C start file://wsl.localhost/Ubuntu-20.04/home/omni/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/share/doc/rust/html/book/ch01-00-getting-started.html'

@AbdulxaqDev Thanks for sharing!

Have you thought about combining your current solution with @wukaijin's #2206 (comment)?

Maybe something like the following (I haven't tested it yet):

export BROWSER="cmd.exe /C start"

@AbdulxaqDev
Copy link

Hello @rami3l
I tried just now, I added .zshrs file. When I run rustup doc --book, is it supposed to open the book?

I got the following error:

Opening docs named `book` in your browser
error: couldn't open browser: error spawning command(s) 'cmd.exe /C start ': No such file or directory (os error 2)

Or am I using it in wrong way?

@rami3l
Copy link
Member

rami3l commented Apr 15, 2024

@AbdulxaqDev Oops, it seems to me that https://github.com/Seeker14491/opener requires $BROWSER to be an actual executable, so you must create an executable to make the trick work, and that's rather unfortunate for the moment being. Sorry for the noise! 🙇

@AbdulxaqDev
Copy link

Thank you for explanation @rami3l 👍

@Okpainmo
Copy link

Okpainmo commented Jun 7, 2024

Dear all,

I found an easy way to solve this question.

Adding the prompt below in .zshrc or .bashrc:

export BROWSER="/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe"

It works for me. Maybe you should alter the real executing path of browser. ❤️

Thanks @wukaijin this works indeed - like a charm.

Simply update the browser path in case the added command fails to fix it:

In my case, I had to update like so:

export BROWSER="/mnt/c/Program Files/Google/Chrome/Application/chrome.exe"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug forwarded This issue as been forwarded "upstream" O-linux Linux related O-windows Windows related
Projects
None yet
Development

Successfully merging a pull request may close this issue.