-
-
Notifications
You must be signed in to change notification settings - Fork 32
fix: resolve versions mismatch causing a crash when building engine #93
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
base: main
Are you sure you want to change the base?
Conversation
0f367a6
to
155a081
Compare
I'm going to let @doorgan review this, but the PR title will go on the changelog, so it needs to be more descriptive. |
I'm not sure this is the right approach for this issue, we need to support workspace folders/multiple root projects(like expert) that might be running on different elixir/erlang versions Ultimately the issue here is that we're lacking the complete Enum.map(System.get_env(), fn
{"PATH", path} -> {"PATH", "#{asdf_path}:#{path}"}
other -> other
end) is what's causing part of the issue in #91, There are other issues that won't be fixed unless we manage to get the right environment here, for example if you use rustler then the project compilation will fail because it won't be able to find |
I think it's essential to note that every project overrides its respective versions.
This is not the case for the issue I reported. The problem here is straightforward:
So, to mitigate the version mismatch, this PR generates a .tool-versions file that has the same Elixir and Erlang versions as the project it's compiling for. |
I don't see how this affects the current engine build process, except that there's a plan to integrate Rust in the future. In addition, the changes made cater to merging the versions as needed, assuming the engine source has a .tool-versions file and requires a specific version of Rust. Maybe I need to look into the codebase more to understand what you're trying to point out here. And just to emphasize again, the issue isn't with my project building, but the expert engine build failing because the Elixir version used to compile it was built for a different otp version that is defined in my global .tool-versions file. |
Sorry, I misread part of your PR and I'm wrong about this locking expert to a single version pair. You're right on most of it, and the only scenarios where I think this may cause issues is if two engines are trying to be built(either because you launched more than one expert at the same time or if you open two files from two subprojects at the same time once #18 is merged). So it's probably fine?
To clarify, we use the same method to use the elixir/erlang versions for both the vm that builds the engine, and the vm that runs the engine. If your project has rustler as a dependency, even if Expert doesn't use it itself, the engine node will fail to compile it if
The reason you're getting the wrong version is due to asdf not providing a complete PATH, before I added some code to derive the path to the asdf shims and manually add it to the PATH it wouldn't be able to find erlang at all.
Asdf is not giving me the path to erlang, nor rust, zig or any of the other asdf managed programs I have. This is the issue we need to fix. The reason you're getting the globally installed erlang version is because of the code that prepends this to the PATH: This PR does mitigate the issue for the engine build, but we still need to find a way to get the right PATH |
tl;dr I think we can use this to mitigate the issue temporarily but we still need to fix the root cause |
Reading your comment here really helped me to understand your points better.
I would have suggested generating a lock file, but I worry about when an unexpected interruption happens, leaving a dangling lock file behind. I'm tempted not to support the idea because the goal of the LSP should be a seamless experience without the users having an idea of the internal workings. In addition, if there is an overwrite one way or the other, I would assume a simple server restart should do.
I agree that the PR can be merged temporarily until a robust fix is found (which I will obviously like to take a stab at), so as to prevent other users from facing the same issue as myself which took me hours to figure out. Is there a channel where questions can be asked aside from GitHub issues? I would assume there is a channel in the Elixir Discord Server. |
@doorgan I think in elixir-tools.nvim to install and compile Elixir LS with the projects versions, I would copy the source code to a temporary directory in the project itself so it would see its PATH/etc, but then move the artifacts to the central cache for. A similar thing could work here. I'm on mobile and haven't read the rest of the convo above but the figured I drop this before I forget. |
@mhanberg, I don't think copying to a temporary folder is efficient, considering how large some projects can be. Regardless, I already updated the implementation to pick the current versions specified in a project's |
We would copy the engine source code, not your project source code. In general it would be better to pick a solution that works in general and not for a specific set of tool managers. |
This is clear. My only concern is how fast this would pollute the filesystem, where every project would require its own build of the engine source code (as long as all projects do not necessarily share the same Elixir and Erlang versions). I do understand the rationale behind the current architectural choice. I already have "elixir-1.17.3-erts-15.2.7" and "elixir-1.18.4-erts-16.0.2" folders in my user data directory, and this means the folders would keep increasing as long as I work with different combinations of Elixir and Erlang runtime versions. I would suggest copying to the project
Is this really possible, since one can't enforce the manner of installation that everybody should use? 🤔 |
Unfortunately that's not viable, the engine needs to be built for the exact elixir version that is going to run it. I learned this the hard way a while ago when I got this error: ** (ErlangError) Erlang error: {:exception, :undef, [{:elixir_quote, :shallow_validate_ast, [:default], []}, {Future.Code.Typespec, :type_to_quoted, 1, [file: ~c"lib/future/code/typespec.ex", line: 78]}, {XPEngine.Modules, :"-fetch_types/1-fun-0-", 2, [file: ~c"lib/engine/engine/modules.ex", line: 88]}, {Enum, :"-reduce/3-lists^foldl/2-0-", 3, [file: ~c"lib/enum.ex", line: 2531]}, {XPEngine.Modules, :fetch_types, 1, [file: ~c"lib/engine/engine/modules.ex", line: 86]}, {XPEngine.CodeIntelligence.Docs, :parse_docs, 2, [file: ~c"lib/engine/engine/code_intelligence/docs.ex", line: 46]}, {XPEngine.CodeIntelligence.Docs, :for_module, 2, [file: ~c"lib/engine/engine/code_intelligence/docs.ex", line: 26]}, {XPEngine, :docs, 2, []}]} I compiled the engine with one elixir version, ran it with the respective project's elixir, and it stopped working because some of the compiled code included calls to internal elixir functions that changed between versions. This happened on a ElixirLS does the same we're trying to do here for the very same reason, although it's a bit easier there because it's a single vm that runs everything so there's no PATH issues there.
I want to believe there must be a way but personally I'd be satisfied for now if we can reliably fix the asdf case |
We only need to build the engine once for a set of versions, performance concerns are negligible. I did this for Elixir LS and it was fine. I don't understand what you mean by copying the _build directory, the problem is with what directory we are building the engine side of. The build artifacts are already sent to the appropriate place automatically. If we build the engine inside of the project directory, it should pick up the right versions the same way your shell does. It's been done before. |
Hi @mhanberg @doorgan, I thought to nudge you that the implementation was updated. I don't know what your thoughts are, except that you're still inclined to find a fix that works without considering installed package managers. In addition, this PR also resolves #104, as it was something I faced when I updated one of my environment variables. EDIT: I believe it fixes #128 too |
ae1dfae
to
8a1d9d9
Compare
Thank you for the ping of my issue, will test later if this resolves it. Just something you might consider is to also update the mise functionality since this should have the exact same issue as the asdf pathing in the code. |
@heywhy It seems it does not resolve the issue #128. See #59 (comment) |
please for all that is code, do not depend on a version manager to do this. asdf is not supported on Windows, and not everyone uses it. Making the official LSP depend on it would isolate whoever wants to work on Windows or not use asdf. Supporting each version manager could become a burden too. Most, if not all, LSPs that depend on an executable to be run, uses what is in the path or through configuration. See JDK-Requirements for how vscode-java does it |
@john-eevee for what it's worth, Expert does not depend on version managers, it will use whichever |
@doorgan oh thanks for the link, I saw the focus on asdf and jumped to conclusions. If I'm not mistaken the original issue was due to the Erlang version mismatch? If so the issue also provided an idea to use a If it's the engine application that needs the same version as the project, copying it to the .expert directory and building per project is a more straightforward way, it generates a bit of pollution but nothing crazy. We could need to provide a message to the user that the engine crashed and urge them to check their versions. |
That's part of the issue, the real problem is that we're not getting the right path that the user shell would see in the project directory. @heywhy I opened #162 which uses a more general approach to fix this issue, please feel free to try it out |
Use the
asdf list
command to identify and parse selected/preferred installed tool versions and add them all to the PATH variable. This should resolve potential problem were a particular project requires specific tools to be available for compilation.See #91