1-module(rabbit_prelaunch_erlang_compat).
2
3-include_lib("kernel/include/logger.hrl").
4
5-include_lib("rabbit_common/include/logging.hrl").
6
7-export([check/1]).
8
9-define(OTP_MINIMUM, "23.2").
10-define(ERTS_MINIMUM, "11.1").
11
12check(_Context) ->
13    ?LOG_DEBUG(
14       "~n== Erlang/OTP compatibility check ==", [],
15       #{domain => ?RMQLOG_DOMAIN_PRELAUNCH}),
16
17    ERTSVer = erlang:system_info(version),
18    OTPRel = rabbit_misc:otp_release(),
19    ?LOG_DEBUG(
20      "Requiring: Erlang/OTP ~s (ERTS ~s)~n"
21      "Running:   Erlang/OTP ~s (ERTS ~s)",
22      [?OTP_MINIMUM, ?ERTS_MINIMUM, OTPRel, ERTSVer],
23      #{domain => ?RMQLOG_DOMAIN_PRELAUNCH}),
24
25    case rabbit_misc:version_compare(?ERTS_MINIMUM, ERTSVer, lte) of
26        true when ?ERTS_MINIMUM =/= ERTSVer ->
27            ?LOG_DEBUG(
28              "Erlang/OTP version requirement satisfied", [],
29              #{domain => ?RMQLOG_DOMAIN_PRELAUNCH}),
30            ok;
31        true when ?ERTS_MINIMUM =:= ERTSVer andalso ?OTP_MINIMUM =< OTPRel ->
32            %% When a critical regression or bug is found, a new OTP
33            %% release can be published without changing the ERTS
34            %% version. For instance, this is the case with R16B03 and
35            %% R16B03-1.
36            %%
37            %% In this case, we compare the release versions
38            %% alphabetically.
39            ok;
40        _ ->
41            Msg =
42            "This RabbitMQ version cannot run on Erlang ~s (erts ~s): "
43            "minimum required version is ~s (erts ~s)",
44            Args = [OTPRel, ERTSVer, ?OTP_MINIMUM, ?ERTS_MINIMUM],
45            ?LOG_ERROR(Msg, Args, #{domain => ?RMQLOG_DOMAIN_PRELAUNCH}),
46
47            %% Also print to stderr to make this more visible
48            io:format(standard_error, "Error: " ++ Msg ++ "~n", Args),
49
50            Msg2 = rabbit_misc:format(
51                     "Erlang ~s or later is required, started on ~s",
52                     [?OTP_MINIMUM, OTPRel]),
53            throw({error, {erlang_version_too_old, Msg2}})
54    end.
55