I am looking into a way of building an archive with dependencies. I know people shouldn’t do that because deps in archives conflict with those in a project (as archives are “global” in a way) and so I want to “namespace” all modules in this lab project of mine to be prefixed with something else.
To be more explicit, say we have this module:
defmodule Jason, do: #
I’d like it to be renamed to:
defmodule MyAwesomeArchive.Jason, do: #...
So that I could depend on it instead of Jason and not conflict with anything else.
This is really hacky I know, but is a somewhat common scenario in other languages like Java.
My lab project depends on Jason and if there is no “easy” way of doing this I will probably fork it and just do a global rename to avoid conflicts (even more hacky I’d say!!!).
I know that on Elixir 1.10 we will have “compiler tracers” and I then I “could” write a module on every defmodule of some dep (it keeps getting hackier…) but I want to do it with Elixir 1.7 at least. Is there the same concept in Erlang compiler?
I hope that even if there is no simple answer here, some brighter minds than mine will share some knowledge of the compiler internals.
Thanks in advance!
Why don’t you just depend on regular Jason?
Because I want to build an archive and install it like:
mix archive.install my_awesome_archive
When you do that and you have a different version of Jason on your project it will conflict. Here is what says in the docs:
Archives are meant to contain small projects, usually installed locally. Archives may be installed into a Mix environment by running
mix archive.install . Once installed, the archive is available to all Mix projects. For this reason, the functionality behind archives is limited. For instance, archives do not include dependencies, as those would conflict with any dependency in a Mix project after the archive is installed.
Could you talk a little bit more about your use case? Perhaps instead of an archive you can create an escript in which you totally can have dependencies.
My use case is somewhat simple: I am looking into making elixir-ls an archive instead of the current approach.
I think the experience would be nicer if we could simply:
mix archive.install lsp 1.0.0-otp-21
I think this has several advantages as simply running
mix lsp --options would run the lsp server.
But even though we could go with an escript for my use case or even simply a dependency to the project with runtime false and test only environment (actually this could be the prefered way…), I’d like to know what we could do for this requisite: plug into the compiler somehow or manually rewriting everything.
This is exactly a usecase where you want to use escripts.
Can we install an escript as an archive? I think an escript does not follow the Erlang Archive Format but I might be completely wrong.
I have no issues with escripts I just think that the best experience would be to install an lsp “globally” and by doing that we wouldn’t have to deal with paths and so on. Like Phoenix installer for example.
Wow! That escaped my readings hehehe
Thanks! I still like to know about compiler plugins anyway.
Even without using archives this is a potential problem with ElixirLS. Since ElixirLS depends on
jason and runs the project’s code in the same beam instance only one version of
jason can be loaded. Would be good to solve for that case as well.
Also I wanted to mention that ElixirLS currently depends on GitHub - JakeBecker/mix_task_archive_deps: Mix tasks to create dependencies .ez archives which creates
.ez files of dependencies. It would be nice to move back to escripts but I haven’t investigated that, although ElixirLS used to use escripts but it was changed to the current approach to better handle asdf: elixir-ls/CHANGELOG.md at 61b8b53331255960151a7225d24a8c8357a6ad5a · elixir-lsp/elixir-ls · GitHub
v0.2.4: 25 Oct 2017
- Package ElixirLS as .ez archives instead of escripts. This should make
asdf installs work.