Rebar3 strange compilation behaviour

I have noticed some strange behavior from rebar3 while compiling my project and I shrank it down to the minimal example.

Lets say we have a following rebar3 app (showing only important files):

my_app
|__ src
    |__b.erl
    |__m1.erl

b.erl defnies a behaviour and requires export of only one function; cb/0.
m1.erl implements that behavior, but it doesn’t export cb/0, so compilation of the project returns “undefined callback …” warning. However, if we add module m2.erl which implements the same behavior and it does export cb/0 there are no more warnings. If I add more modules that are missing the callback I still get no warnings…

EDIT: I get a warning when compiling directly with erlc.
EDIT2: dialyzer also displays a warning

In addition to that, I’d like to ask why compilation of the project with rebar3 stops as soon as the first module fails to compile.

Using rebar 3.22.0 on Erlang/OTP 26

I tried to reproduce this but couldn’t :frowning:

You might want to attach a tarball of your minimal example.

1 Like

Couldn’t attach a tarball, but here are file contents:
b.erl:

-module(b).
-callback cb() -> ok.

m1.erl:

-module(m1).
-behaviour(b).

m2.erl:

-module(m2).
-behaviour(b).

What I just discovered is that when you do rebar3 clean it displays the warning, but only first time after cleaning, every following compilation it doesn’t… If you compile it second time in a row it doesn’t display a warning.

EDIT: Aha, the thing is that it doesn’t even get compiled (because file is unchanged) so there are no warnings displayed… Should it be like that or should we cache warnings in some way?

I normally use the warnings_as_errors compiler flag, which prevents this becoming an issue.

1 Like

Confirming that this is as expected. We cache the artifacts, not the warnings, and so it makes sense it only shows up once (it could get annoying working on project with hundreds or thousands of files to always warn even if nothing changed!)

Turning the warning to error works because the error prevents the beam file from being produced and so there’s nothing to cache and we build every time.

Do note as well that the rebar3 compiler tracks the graph of files based on compile-time dependencies, and if the implementation isn’t too buggy, changing the module that defines the behaviour should trigger a rebuild and show the warning again as well.

2 Likes

Nice, didn’t know that.

The thing about warning is clear now, but what about second question:

That causes errors from only one module to be displayed at the time. So if I got error in multiple files, I’ll have to trigger recompile multiple times. Does it have something to do with dependency tracking or something else?

I think that’s just how we built it. We can build files independently so it should in theory be possible to keep running.

It could likely generate a ton more errors (all dependent files could generate errors after the dependency fails to build) and we’d need to track a state a bit more complex to support our API mode (where we return whether a task succeeded or if not, its error) but there’s nothing that should fundamentally prevent it from being implemented

3 Likes