Stratus3D / asdf-rebar

Rebar3/Rebar version management plugin for asdf
MIT License
35 stars 7 forks source link

plugins and various erlang versions #15

Open asmodehn opened 1 year ago

asmodehn commented 1 year ago

Hi,

I have been using rebar, erlang and elixir via asdf for a little while now...

I seem to have issues when switching erlang versions:

=ERROR REPORT==== 13-Dec-2022::13:05:07.778850 ===
beam/beam_load.c(162): Error loading module rebar3_run:
  This BEAM file was compiled for a later version of the run-time system than 24.
  To fix this, please recompile this module with an 24 compiler.
  (Use of opcode 178; this emulator supports only up to 176.)

=ERROR REPORT==== 13-Dec-2022::13:05:07.778856 ===
Loading of /home/alexv/.cache/rebar3/plugins/rebar3_run/ebin/rebar3_run.beam failed: badfile

From what I understand, plugins where compiled with otp v25, and I am now using v24.

I have a few questions:

Overall I d like to be able to switch rebar and erlang versions independently, or make the link with the OTP version somewhat more explicit... Thank you for any information.

Stratus3D commented 1 year ago

Unfortunately I don't have a good answer to any of these.

  • is there something obvious that I am missing ?

No, if you compile a rebar version against OTP 25 and then switch to OTP 24 it will break as you have observed.

  • is there a quick immediate fix for that (I don't see a clean/compile commands for rebar3 plugins...)

No. The only "fix" is to uninstall and re-build with the rebar version with the OTP version you are currently using, defeating part of the point of the version manager.

  • is there a proper fix, that would prevent this problem from occuring in the first place (not using the cache, relying on asdf uuid of environment, following elixir by adding the otp version in the string, or some other idea ?)

I've thought about this some, and there are a couple ways I could solve this:

I'm inclined to go with that last option, as this is something that comes up a lot with asdf. There is of course a lot of work to make that happen, and some performance implications as well. Thoughts?

asmodehn commented 1 year ago

Well, for context I also read https://github.com/asdf-vm/asdf/issues/1127 and https://github.com/asdf-vm/asdf/issues/196.

I am also in favor of avoiding the complexity of a full dependency graph resolution in asdf (ordering in .tool-versions is "good enough" imho). Afterall, I use asdf as it is easier to setup and maintain than a full nixpkg setup, yet allows version management of various tools with a simple interface.

I like the idea of version tags, or having another version, but I don't really see an easy way to support it in asdf-vm in a generic way without seeing it blow up and become much complex than anticipated (the usual fate of package management systems). And leaving it to each plugin means the user needs to think and manage these...

So:

Do note that if you are planning to work with multiple Erlang versions on the same machine, you will want to build Rebar3 with the oldest one of them. The 3 newest major Erlang releases are supported at any given time: if the newest version is OTP-24, building with versions as old as OTP-22 will be supported, and produce an executable that will work with those that follow.

I am not used to rebar3 much ( Ive just recently been trying to setup a C/Erlang/Elixir decent dev env), so I may be a bit off-track, but maybe the solution is in two parts:

So compared with your solution, I am thinking to make rebar build more generic, and keep the version hash trick for plugins only... Maybe less generic, but simple enough (no big asdf feature needed) ? Can you see any usecase in which that would be a no go ?

Stratus3D commented 1 year ago

Hi @asmodehn sorry for the late reply here.

  • on asdf-rebar side: enforce this rule of 3 newest major release supported -> build it with the oldest supported one already installed. Maybe coding that check into the shim and forcing a rebuild if necessary would be enough ? Unless you are working on a rebar plugin, the erlang version you are using and the erlang version rebar was built with won't conflict, I m guessing ?

Currently the Erlang version used to build a particular version of Rebar isn't recorded anywhere. This information is only available at install time, as an install may be run from any directory, and the environment may be changed at any time. Doing so would be possible, and then we'd have an exec-env callback script that could maybe print an error when the version doesn't match (or isn't newer). I don't recall whether or not the exec-env callback has the ability to halt execution, which is what we'd ideally want in this cause.

on rebar3 itself : have a different way to manage plugin builds ? Like putting them in a location depending on some uuid depending on the build of rebar itself ? I see a bunch of issues on rebar regarding plugins... Or maybe... in asdf-rebar, via setting REBAR_CACHE_DIR with a hash depending on the rebar/erlang build ? That would sidestep the issue I think, as far as asdf is concerned, since a different rebar build would point to different plugins... But I also see : https://github.com/erlang/rebar3/issues/2762 so we might want to be careful playing with this.

REBAR_CACHE_DIR with a hash depending on the rebar/erlang build ? Hmm... I like the idea of that. However that issue you linked to does seem to indicate setting REBAR_CACHE_DIR would cause other issues for our users.

I guess I'm inclined to either do nothing, or go with the first option for now. Eventually we'll have some basic dependency management baked into asdf.

If we implemented the first option, this is how it might work:

What do you think about this @asmodehn ? Feel free to take a stab at implementing this if you want. If once asdf itself supports dependency management this code could just be deleted.

kivra-pauoli commented 5 days ago

@Stratus3D, instead of building rebar3 locally (in this plugin), could we pick it up from the pre-compiled releases available in GitHub directly?

e.g. https://github.com/erlang/rebar3/releases/download/3.24.0/rebar3

AfaIk these are arch. agnostic and are compiled with at least OTP-2, which would partially prevent compatibility issues when using it locally with different Erlang versions.

e.g.

erlang 27.0.1
rebar3 3.24.0

will mean that that rebar3 is (potentially?) not compatible with say Erlang 26.2.5.3, but if we download the pre-compiled artifact not only is it faster at installing but that issue would go away.

kivra-pauoli commented 5 days ago

Another solution would be to create a rebar3 (specific) plugin, but this would:

  1. not benefit the many installs already out in the wild
  2. potentially cause confusion

(?)

In any case I think I'm gonna hack something locally and if results are promising I can pull request.