Compiling Erlang project, but transitive dependency uses mix.exs with wrong language option

For … reasons … I’m converting an Erlang codebase to compile with mix, and I’ve run into a problem.

One of my Erlang projects uses “hackney”, so I’ve specified it in my mix.exs as follows:

defp deps do
  [
    # ...
    {:hackney, "~> 1.15.2"}
  ]
end

hackney has a dependency on ssl_verify_fun, specified in its rebar.config:

{deps, [
        % ...
        {ssl_verify_fun, "1.1.5"}

But: ssl_verify_fun has a mix.exs file in it. I don’t know why. This causes it to be compiled with mix, which causes it to add a reference to the elixir app, which it doesn’t actually need, which causes my application (which also doesn’t need elixir) to fail to start, because it’s not included.


If I attempt to use an alternative fork (actually, just using the original repo for demonstration purposes), by adding the following to my mix.exs (that depends on hackney)…

{:ssl_verify_fun, git: "https://github.com/deadtrickster/ssl_verify_fun.erl", tag: "1.1.5"}

…causes “different specs were given …”

Adding override: true causes mix deps.get to pull the correct code from git, but then I get “The lock is missing for package”. I get the same if I attempt to set manager: :rebar3.


I can manually edit the mix.exs to add language: :erlang, which fixes my problem, but isn’t permanent.


If I delete the deps/ssl_verify_fun/mix.exs file (attempting to trick mix into using rebar instead), I get “Could not find a Mix.Project, please …”

And this isn’t permanent, either.


How do I…

  • Use an alternative fork of ssl_verify_fun?
  • OR: edit its mix.exs before compiling?
  • OR: change the manager used to rebar3?
  • OR: something else?
1 Like

Do you get the lock error if you override with a manager?

{:ssl_verify_fun, "~> 1.1", manager: :rebar3, override: true}

If you get the error please share a reproducible project. Your mix.exs and mix.lock files should be enough.

3 Likes

If I try that in my original project, I have the same problem.

It manifests itself as follows:

{"init terminating in do_boot",
    {{badmatch,{error,{elixir,{"no such file or directory","elixir.app"}}}},
    [{my_app,start,0,[{file,"src/my_app.erl"},{line,7}]},
    {init,start_em,1,[]},{init,do_boot,3,[]}]}}
init terminating in do_boot ({{badmatch,{error,{elixir,{_}}}},[{my_app,start,0,[{_},{_}]},
    {init,start_em,1,[]},{init,do_boot,3,[]}]})

…and I can see the problem’s caused by this:

$ ag -sw elixir _build/dev/
_build/dev/lib/ssl_verify_fun/ebin/ssl_verify_fun.app
2:             [{applications,[kernel,stdlib,elixir]},

It’s an umbrella project, so I added that line to the mix.exs file of the app that includes hackney (and therefore ssl_verify_fun).

Interestingly, I can’t easily reproduce it with a smaller project, but I do notice one difference in mix.lock:

In the project that works:

{:ssl_verify_fun, "1.1.5", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
  "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.5",
  "6eaf7ad16cb568bb01753dbbd7a95ff8b91c7979482b95f38443fe2c8852a79b",
[], [], "hexpm"},

In the project that doesn’t work (even with your suggestion):

{:ssl_verify_fun, "1.1.5", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
  "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.5",
"6eaf7ad16cb568bb01753dbbd7a95ff8b91c7979482b95f38443fe2c8852a79b",
[:make, :mix, :rebar3], [], "hexpm"},

Note the [:make, :mix, :rebar3]. Where’s that coming from?

…it’s coming from Hex.SCM.guess_build_tools, because ssl_verify_fun contains mix.exs, Makefile and rebar.config.

But – I think – it’s only part of the lock definition, and isn’t actually used to figure out the build tool.

Oh. Interesting. My test project (that doesn’t didn’t reproduce the problem) just prompted me to upgrade from Hex 0.17.1 to 0.20.1, and now the problem appears.

Here you can see it using rebar to compile ssl_verify_fun:

===> Compiling ssl_verify_fun

Then it prompted me to upgrade hex (because I’d switched to using Elixir 1.10.0-dev):

$ mix deps.get
Mix requires Hex >= 0.19.0 but you have 0.17.1
Shall I abort the current command and update Hex? [Yn] y
* creating /home/roger/.mix/archives/hex-0.20.1

Then you can see it using mix to compile ssl_verify_fun:

==> ssl_verify_fun
Compiling 7 files (.erl)

If I switch back to Elixir 1.9.4, but still with Hex 0.20.1, then the problem remains.

The behaviour changed in hex 0.17.2. There are 88 changes between 0.17.1 and 0.17.2. I guess I’m git bisecting…

Here: https://github.com/hexpm/hex/commit/7c373e8a67 from https://github.com/hexpm/hex/pull/426

So whatever that’s writing to mix.lock is causing my manager: :rebar3 option to be ignored.

2 Likes

For completeness, the repro project is here: https://github.com/rlipscombe/transdep.

4 Likes

Thank you for the reproducing repo, that is always very appreciated.

I have opened a PR that should fix the issue: https://github.com/elixir-lang/elixir/pull/9625.

2 Likes