VS Code completion for core Elixir on Windows not working due to lack of source

Hi there,

I just recently started using VS Code to take advantage of all the lovely functionality via elixir-ls.

However, I discovered quite a significant stumbling block - much of elixir-ls functionality for core Elixir isn’t available.

The language server needs access to Elixir’s source to do a lot of useful things. The ‘solution’ appears to be to build Elixir from source with the suggestion of using asdf. Unfortunately this isn’t a valid solution on Windows.

Looking at the code for elixir-ls it appears to be trying to do it via:

enum_ex_path = Enum.module_info[:compile][:source]

and

{_module, _binary, beam_filename} = :code.get_object_code(:erlang)

(see elixir-ls/cli.ex at 25dc8f0a39fe158c1593749692d33e85f796c5c5 · elixir-lsp/elixir-ls · GitHub)

On Windows this unfortunately results in something like: d:/home/runner/work/elixir/elixir which is totally not a valid path at all.

I’m therefore wondering if anyone has managed to teach elixir-ls where to find Elixir’s source. It seems like there might be two possible approaches:

  1. Download the source manually and explicitly teach elixir-ls where it resides on the file system
  2. Build Elixir from source (I couldn’t find a simple way of doing this on Windows)

It would be lovely to get this stuff working out of the box for Windows VS Code users. In pursuit of this I raised the following comment definition not able to locate elixir sources on some ocasions · Issue #44 · elixir-lsp/elixir_sense · GitHub but am also open to suggestions on what to do to improve this situation.

1 Like

Another option might be for the Windows Elixir installer to offer a ‘dev’ version of Elixir which includes all the source: elixir-lang/elixir-windows-setup: Elixir Installer powered by Inno Setup http://elixir-lang.org/ (github.com)

Is the problem a lack of a more “pure Windows” solution than using asdf through WSL? At some point developers will generally have far less friction diving into WSL for more than just Elixir. Pure windows solutions are worth pursuing but I wonder if people more often go the WSL route because there are numerous articles on it. WSL is also a lot of extra hoops newbies will stumble through, even though I vehemently suggest using asdf over global installations.

I do find the experience fragmented when you realize you need to install Elixir with source for that to work. You also need to compile Erlang source with a few extra options to include Erlang docs when using the h() help function in iex.

I believe both the Windows installer and asdf grab the zip from Release v1.14.2 · elixir-lang/elixir · GitHub as https://elixir-lang/elixir.csv points to https://github.com/elixir-lang/elixir/releases/download/v1.14.2/elixir-otp-25.zip for the otp-25 version. These files do include some sources and namely the pure .ex files but when running Enum.module_info()[:compile][:source] in iex on my installation, I see '/home/build/elixir/lib/elixir/lib/enum.ex' which would likely be where it was built using Github Actions. I do see that when running {_module, _binary, beam_filename} = :code.get_object_code(:erlang) it points to the asdf location at '/Users/jbrayton/.asdf/installs/erlang/25.0.2/lib/erts-13.0.2/ebin/erlang.beam'. The source zip from the releases section does include more files but they’re largely tests and a few choice .erl files. I don’t believe ElixirLS really needs those files over compared to the release zip.

I typically don’t notice I’m missing this behavior as I’ve been conditioned to hover over a function and click the link to view on hexdocs. My guess is people that aren’t newbies are also conditioned for this?. Following the steps in Fixing "Go to Definition" for Elixir's standard library | Random Developer's Blog to compile Elixir with asdf is rather straightforward but finding it again weeks later through a Google search was my biggest hurdle.

All of the Elixir modules using erlang functions are prefixed with Elixir so doing something like {_module, _binary, beam_filename} = :code.get_object_code(Elixir.Enum) gets me '/Users/jbrayton/.asdf/installs/elixir/1.14.2-otp-25/bin/../lib/elixir/ebin/Elixir.Enum.beam'. I’m wondering if armed with the beam file location, couldn’t we walk the relative path up to enum.ex? I can’t seem to find why the full source is necessary when I only see functions returning the .ex files that seem to be included. There’s clearly something I’m missing.

I do see where your #1 was proposed as src_path by Marlus at definition not able to locate elixir sources on some ocasions · Issue #44 · elixir-lsp/elixir_sense · GitHub. As for #2, there are Github actions defined to running the tests on Windows Server 2019 at elixir/ci.yml at main · elixir-lang/elixir · GitHub that may help. The 2 uses lines hides the complexities of those actions but the first is likely just a git clone/checkout actions/checkout@v3 and the second sets up OTP with erlef/setup-beam@v1. If we follow that down it configures git, runs the checkout action, runs the setup-beam action, deletes the .git directory, make compile, run bin/elixir --version to verify the version, then make test_formatted && echo "All Elixir source code files are properly formatted." to check formatting, make --keep-going test_erlang for erlang tests, and make --keep-going test_elixir for mix tests. The setup-beam action can be found at GitHub - erlef/setup-beam: Set up your BEAM-based GitHub Actions workflow (Erlang, Elixir, Gleam, ...) but it looks like it installs Erlang from pre-built binaries so that may be out. Erlang seems to be the biggest hurdle when it comes to compiling and that’s true for asdf as well. If I had a Windows machine that wasn’t a VM, I would look into #2 as a good guide could be extremely useful. I may try seeing if I can hack around #1 but my guess is I’ll run into those hidden walls I can’t see yet.

1 Like

As a bit of background I’m developing on ‘pure Windows’ because Windows is the most popular deployment target for my app :slight_smile:

I therefore made the decision to start developing on Windows so I could find issues and fix them during development rather than trying to “fix weird issues in the Windows build” after I got thing running smoothly on macOS/Linux.

I’ll take a look at compiling Elixir using the steps you kindly illustrated. That certainly looks a lot more achievable than building Erlang on Windows. Still, I wonder if idea #3 has legs - which is to get an official dev release of Elixir for Windows that ships with the source.

Hell I realize what a wall of text that was, sorry. I also realize if you have a “pure Windows” solution you can use releases for your end users. What we’re focused on would be for developers like yourself or people contributing to your project. If this were me, I would create releases and build binaries for end users for every platform.

Users shouldn’t need any of these hoops because they’re likely not going to use VSCode or iex for that matter. They’re going to run what you’ve built and that should be possible today with the existing installers even if you never touch releases.

I absolutely do want a better developer experience for “pure Windows” because all the pieces seem to be there. I think #1 or 2 are far less friction than 3 but 3 also seems doable. If the elixir.csv had a source url column and the UI were changed to all people to select that over the release, it should download and unpack the zip just as it does for releases. From there you should be able to run the make commands but I could be missing something very important. Tackling #1 also solves the problem of asdf users like myself having to remember to pull the source instead of the release version.

Absolutely right - I do indeed create binaries for end-users on all platforms. Previously this included a custom-built BEAM, but since the last major release I moved to using Elixir and use mix release as part of the app-building process.

As you say, this issue is only really a problem for Windows developers that run VS Code natively and not under WSL.

Ultimately I believe that reducing the barriers to entry for new Elixir devs that only have access to a Windows machine can only be a good thing for the Elixir community in general.

1 Like

I wonder if option 1, pointing elixir-ls to some downloaded source, might be easier?

Option 2 is probably possible. There are open issues for both scoop :heart: and chocolatey :face_vomiting: around this which look like dead-ends. There is winbrew, which is a package manager for building from source. If we can wrangle the Elixir makefile to be Windows compatible, create separate one, or if winbrew is happy to compile in msys2 then we should be on our way.

It’s an ugly, obvious workaround, but what helped me was to simply git clone the elixir sources matching the installed binaries on my Windows 10 system into the directory above the one ElixirLS is asking for (on my machine ‘C:\home\runner\work\elixir’). This will create another ‘elixir’ directory within the elixir directory at the end of the path, and the sources end up there. I restarted my editor (VSCodium) and the error in the ElixirLS output about not being able to find the elixir sources went away.

No idea what side effects in building actual running software this hack might create–my grand total exposure to Elixir is about four hours–but the editor to my very limited testing seems to work acceptably now for learning. My setup is VSCodium 1.77.3, ElixirLS v0.14.7, Elixir 1.14.4, Erlang/OTP 25. I hope this helps someone just getting their feet wet with VS Code and Elixir like me.