szajbus

szajbus

Implicit compile-time dependencies

I understand what runtime and compile dependencies between modules are and when they happen. But I have a problem understanding one particular situation in which a recompilation of some files is required after changes in others.

Here’s what xref graph shows:

~/dev/elixir/dep-example $ elixir --version
Erlang/OTP 21 [erts-10.2] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [hipe]

Elixir 1.10.0 (compiled with Erlang/OTP 21)
~/dev/elixir/dep-example $ mix xref graph
lib/a.ex
└── lib/b.ex (compile)
    └── lib/c.ex
lib/b.ex
lib/c.ex

There’s only only one compile dependency: A depends on B at compile-time.
However when C changes, it causes recompilation of A.

~/dev/elixir/dep-example $ touch lib/c.ex
~/dev/elixir/dep-example $ mix compile --verbose
Compiling 2 files (.ex)
Compiled lib/c.ex
Compiled lib/a.ex

The compiler works like this: it walks through a list of modules, checks dependencies between them and determines what has changed and what needs to be recompiled in the consequence of the changes.

The process in above situation is as follows:

  1. compiler detects that C changed (on disk), marks it as stale and for recompilation
  2. compiler sees that B depends on something stale (C), so marks it as stale as well, but doesn’t mark it for recompilation because it’s only runtime dependency
  3. compiler sees that A depends on something stale (B), marks it as stale, but this time it’s a compile dependency, so the file is marked for recompilation too.

In the end, both A and C are recompiled, B is left intact.

Clearly A has an implicit compile dependency on C.

What’s the reasoning for that?

I cannot think of any scenario (usage of imports, macros, etc) when lack of recompilation of A in this situation would cause bugs. Can you help me find some examples?

Marked As Solved

axelson

axelson

Scenic Core Team

A concrete example of A that would showcase this issue like this might look like this:

defmodule A
  @the_answer B.search()
  def get_the_answer, do: @the_answer
end

So when C changes, A needs to be recompiled because B.search/0 might call a function in C

Also Liked

wojtekmach

wojtekmach

Hex Core Team

Right, if A has compile-time dependency on B, and B has runtime dependency on C, when C changes, A has to be re-compiled even though B does not have to!

See https://milhouse.dev/2016/08/11/understanding-elixir-recompilation/,
https://telnyx.com/resources/renan-ranelli-understanding-elixirs-re-compilation-at-elixirconf-2018 for more information.

LostKobrakai

LostKobrakai

As far as I understand it the compiler doesn’t know if any code B holds for changing A at compile time is provided by calling into C. Therefore if C changes A needs to change as well.

szajbus

szajbus

Thanks, it makes perfect sense now!

Last Post!

szajbus

szajbus

Thanks, it makes perfect sense now!

Where Next?

Popular in Questions Top

hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New

Other popular topics Top

rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
TunkShif
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
274 42576 114
New

We're in Beta

About us Mission Statement