A surprising ex_cldr issue was opened this morning and I hope someone can help clarify the behaviour of what triggers (re)compilation in mix run
that is different to mix compile
and iex -S mix
. Its easily reproducible and a test app repo is here.
mix compile
compiles once as expected
mix compile
proceeds as expected - the module is compiled (along with several other modules generated at compile time). The next time compilation is requested, nothing is compiled (normal expectation).
kip@Kips-MBP my_app % rm -rf _build
kip@Kips-MBP my_app % mix compile
==> decimal
Compiling 4 files (.ex)
Generated decimal app
...
==> my_app
Compiling 1 file (.ex)
Generating MyApp for 3 locales named [:en, :fr, :und] with a default locale named :fr
Generated my_app app
kip@Kips-MBP my_app % mix compile
kip@Kips-MBP my_app % mix compile
kip@Kips-MBP my_app % iex -S mix
Erlang/OTP 25 [erts-13.2] [source] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [jit] [dtrace]
Interactive Elixir (1.14.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)>
mix run
compiles every time
It appears mix run
uses a different recompilation model to mix compile
or iex -S mix
but I can’t work out what is triggering (re)compilation. The generated modules are also always recompiled (but without the warnings) if I rename my_app.ex
to my_app.exs
. The warnings are for modules that are generated at compile time. I typically understand these warnings to mean that the module was created but one already existed - which is true, they have already been compiled.
kip@Kips-MBP my_app % rm -rf _build
kip@Kips-MBP my_app % mix run lib/my_app.ex
==> decimal
Compiling 4 files (.ex)
Generated decimal app
==> jason
...
==> my_app
Compiling 1 file (.ex)
Generating MyApp for 3 locales named [:en, :fr, :und] with a default locale named :fr
Generated my_app app
warning: redefining module MyApp (current version loaded from _build/dev/lib/my_app/ebin/Elixir.MyApp.beam)
lib/my_app.ex:1
Generating MyApp for 3 locales named [:en, :fr, :und] with a default locale named :fr
warning: redefining module MyApp.Locale (current version loaded from _build/dev/lib/my_app/ebin/Elixir.MyApp.Locale.beam)
lib/my_app.ex:1
warning: redefining module MyApp.AcceptLanguage (current version loaded from _build/dev/lib/my_app/ebin/Elixir.MyApp.AcceptLanguage.beam)
lib/my_app.ex:1
...
# Each invocation always rebuilds
kip@Kips-MBP my_app % mix run lib/my_app.ex
warning: redefining module MyApp (current version loaded from _build/dev/lib/my_app/ebin/Elixir.MyApp.beam)
lib/my_app.ex:1
Generating MyApp for 3 locales named [:en, :fr, :und] with a default locale named :fr
warning: redefining module MyApp.Locale (current version loaded from _build/dev/lib/my_app/ebin/Elixir.MyApp.Locale.beam)
lib/my_app.ex:1
warning: redefining module MyApp.AcceptLanguage (current version loaded from _build/dev/lib/my_app/ebin/Elixir.MyApp.AcceptLanguage.beam)
lib/my_app.ex:1
Sample app
The code for this very small example is here. Its a simple module (same principle in all ex_cldr
applications).
defmodule MyApp do
use Cldr,
locales: ["en", "fr"],
default_locale: "fr",
providers: []
end
And the deps are equally simple:
defp deps do
[
{:jason, "~> 1.0"},
{:ex_cldr_numbers, "~> 2.30"}
]
end
If you got this far - thank you! Any and all suggestions welcome. Tested on Elixir 1.12 and 1.14.4.