Cannot find :my_app as dependency from git

Background

I have created an OTP compliant application called :my_app and I have it in a GitHub repository. I want to use this application as a dependency in a :mother_app but I am failing to even compile the code.

Code

Here is how I am importing :my_app into :mother_app:

defmodule MotherApp.Mixfile do
  use Mix.Project

  def project do
    [
      app: :mother_app,
      version: 0.1.0,
      elixir: "~> 1.8",
      elixirc_paths: elixirc_paths(Mix.env()),
      compilers: [:phoenix] ++ Mix.compilers(),
      build_embedded: Mix.env() == :prod,
      start_permanent: Mix.env() == :prod,
      deps: deps()
   ]
  end

  def application do
    [
      mod: {MotherApp, []},
      extra_applications: [:my_app]
    ]
  end

  # Specifies which paths to compile per environment.
  defp elixirc_paths(:test), do: ["lib", "web", "test/support"]
  defp elixirc_paths(_), do: ["lib", "web"]

  defp deps do
    [
      {:phoenix,        "~> 1.4"  },
      {:phoenix_html,   "~> 2.0"  },
      {:my_app,          git:  "git@github.com:cool_username/my_app",          tag: "0.1.1"  }
    ]
  end
end

Looks like an ordinary simple file, nothing new here. I use MyApp in a file called dispatcher.ex that looks something like this:

defmodule MotherApp.Dispatcher do

  require MyApp

  def work(args) do
    MyApp.InnerModule.work()
  end
end

Problem

However, when I run mix compile I get the following error:

== Compilation error in file lib/mother_app/dispatcher.ex ==
** (CompileError) lib/mother_app/dispatcher.ex:15: module MyApp is not loaded and could not be found

And mix.exs shows me this cryptic error as well:

an exception was raised:
** (ArgumentError) argument error
(stdlib) eval_bits.erl:101: :eval_bits.eval_exp_field1/6
(stdlib) eval_bits.erl:92: :eval_bits.eval_field/3
(stdlib) eval_bits.erl:68: :eval_bits.expr_grp/4
(stdlib) erl_eval.erl:484: :erl_eval.expr/5
(stdlib) erl_eval.erl:888: :erl_eval.expr_list/6
(stdlib) erl_eval.erl:240: :erl_eval.expr/5
(stdlib) erl_eval.erl:232: :erl_eval.expr/5
(elixir) src/elixir.erl:258: :elixir.eval_forms/4(undefined)

What am I doing wrong?

Just a guess, because I am pretty new to this stuff, but I do recall a similar issue with compiling an older project and brunch where I needed to setup an alias in my brunch config.

Not immediately clear what the issue is other than your dependency module isn’t being found. Perhaps try mix deps.compile --force and see what message you got? That will force compile your dependency and you will at least get clarity as to whether it is compiled.

1 Like

Can you share the source code of mother_app and my_app?

I don’t see how you can get both a compilation error and an ArgumentError from mix.exs. If mix.exs does not evaluate correctly then you should not get to the compilation step.

RCA

The issue was finally solved. Here is how a couple of wounds made be bleed for an unreasonable long time.

1. Be careful which VS code extensions you use

The issue that was most puzzling to me was that my mix.exs didn’t even compile (according to my IDE), but somehow I was able to do mix deps.get and even run mix compile.

I use VSCode and my IDE was showing the cryptic error:

an exception was raised:
** (ArgumentError) argument error
(stdlib) eval_bits.erl:101: :eval_bits.eval_exp_field1/6
(stdlib) eval_bits.erl:92: :eval_bits.eval_field/3
(stdlib) eval_bits.erl:68: :eval_bits.expr_grp/4
(stdlib) erl_eval.erl:484: :erl_eval.expr/5
(stdlib) erl_eval.erl:888: :erl_eval.expr_list/6
(stdlib) erl_eval.erl:240: :erl_eval.expr/5
(stdlib) erl_eval.erl:232: :erl_eval.expr/5
(elixir) src/elixir.erl:258: :elixir.eval_forms/4(undefined)

Why so? It so happens this is an issue from the extension I was using:

This extension painted my screen red and offered no feedback. Eventually this conflicted with another extension I was using, which was actually telling me what the real issue was (that my module was not being found):

To make it clear, I recommend the second extension, and I suggest that if you use the first, remove it and replace it with the second. It’s fine if your personal opinion on extensions does not align with mine, but one thing I will truly try to hammer on your head is to never use both extensions at the same time.

Do with this what you will.

Do you really require me?

Why wasn’t my module being found?
I checked the result of mis deps.get several times. The packages were being downloaded. Everything was in place. So why couldn’t I compile my app?

Turns out the solution is right in the Getting started guides:

# Require the module in order to use its macros
require Foo

The issue here is that MyApp does not have any macros. So, using require was trying to pre-compile a module searching for macros that didn’t exist. Of course it didn’t work. What I should have been using is alias (or import but I am not a fan of import for reasons extraneous to this discussion).

Conclusion

And here it is. How a tool error which resulted in misdirection and a simple error made my head spin for days. I hope this helps someone. If anything, be careful which extensions you use and know your language.

1 Like

Adding require shouldn’t make compilation fail if the module exists (unless you are introducing cyclic dependencies). require doesn’t look for macros, it makes them available if there are any.

1 Like

This is confusing, because the code compiles if I use alias but doesn’t if I use require. MyApp doesn’t depend on MotherApp (no cyclic dependencies here), so I really don’t get how using alias could work then…

Can you share the code that reproduces the issue? If it’s an Elixir bug it would be great to get it fixed.

I really doubt this is a bug from Elixir. I cannot give you the project (company directives, private code, so on, so on), but I believe I managed to create a MWE that replicated the issue I am facing.

Here is a skeleton for MotherApp:

https://github.com/Fl4m3Ph03n1x/mother-app

Here is a skeleton for MyApp:

https://github.com/Fl4m3Ph03n1x/elixir-myapp/

Since you mentioned dependencies, I have also installed the majority of the dependencies we are using for good measure. It is likely their only effect will be an increased compile time, but I’d rather be safe.

Happy hunting.

You have require MyApp, but the module is defined as Myapp. The casing does not match.

1 Like

Failed while trying to create a MWE … sorry for wasting your time.

1 Like

No worries. Important thing is that we found the issue. :slight_smile:

2 Likes