]> granicus.if.org Git - ejabberd/commitdiff
Improve compilation with rebar3
authorPaweł Chmielowski <pchmielowski@process-one.net>
Thu, 26 Jan 2017 15:43:47 +0000 (16:43 +0100)
committerPaweł Chmielowski <pchmielowski@process-one.net>
Thu, 26 Jan 2017 15:45:04 +0000 (16:45 +0100)
rebar.config
rebar.config.script

index 7e9fe145efb07c2f2c514eb397024678b3667660..f824f620f41a222b2d17c68102cb959306e15364 100644 (file)
                                            {tag, "1.0.2"}}}},
         {if_var_true, riak, {riakc, ".*", {git, "https://github.com/basho/riak-erlang-client",
                                            {tag, "2.4.1"}}}},
-        %% Elixir support, needed to run tests
+       %% Elixir support, needed to run tests
         {if_var_true, elixir, {elixir, ".*", {git, "https://github.com/elixir-lang/elixir",
                                               {tag, {if_version_above, "17", "v1.2.6", "v1.1.1"}}}}},
         %% TODO: When modules are fully migrated to new structure and mix, we will not need anymore rebar_elixir_plugin
-        {if_var_true, elixir, {rebar_elixir_plugin, ".*",
-                               {git, "https://github.com/processone/rebar_elixir_plugin", "0.1.0"}}},
+       {if_not_rebar3, {if_var_true, elixir, {rebar_elixir_plugin, ".*",
+                                              {git, "https://github.com/processone/rebar_elixir_plugin", "0.1.0"}}}},
         {if_var_true, iconv, {iconv, ".*", {git, "https://github.com/processone/iconv",
                                             {tag, "1.0.3"}}}},
         {if_var_true, tools, {meck, "0.8.*", {git, "https://github.com/eproxus/meck",
 
 {deps_erl_opts, [{if_var_true, hipe, native}]}.
 
-{plugins, [deps_erl_opts,
-           {if_var_true, elixir, rebar_elixir_compiler},
-           {if_var_true, elixir, rebar_exunit}]}.
+{if_rebar3, {plugins, [rebar3_hex, {provider_asn1, "0.2.0"}]}}.
+{if_not_rebar3, {plugins, [
+                          deps_erl_opts,
+                          {if_var_true, elixir, rebar_elixir_compiler},
+                          {if_var_true, elixir, rebar_exunit}
+                         ]}}.
 
 {if_var_true, elixir,
               {lib_dirs, ["deps/elixir/lib"]}}.
index ba8c66c663126fd982bf7c3f9def28a915f8fb98..5e371b17563c9b76d979166e086b2711d32897d2 100644 (file)
 %%%
 %%%----------------------------------------------------------------------
 
-ModCfg0 = fun(F, Cfg, [Key|Tail], Op, Default) ->
-                 {OldVal,PartCfg} = case lists:keytake(Key, 1, Cfg) of
-                                        {value, {_, V1}, V2} -> {V1, V2};
-                                        false -> {if Tail == [] -> Default; true -> [] end, Cfg}
-                                    end,
-                 case Tail of
-                     [] ->
-                         [{Key, Op(OldVal)} | PartCfg];
-                     _ ->
-                         [{Key, F(F, OldVal, Tail, Op, Default)} | PartCfg]
-                 end
-         end,
-ModCfg = fun(Cfg, Keys, Op, Default) -> ModCfg0(ModCfg0, Cfg, Keys, Op, Default) end,
+Vars = case file:consult("vars.config") of
+          {ok, Terms} ->
+              Terms;
+          _Err ->
+              []
+       end ++ [{cflags, "-g -O2 -Wall"}, {cppflags, "-g -O2 -Wall"}, {ldflags, ""}],
+{cflags, CFlags} = lists:keyfind(cflags, 1, Vars),
+{cppflags, CPPFlags} = lists:keyfind(cppflags, 1, Vars),
+{ldflags, LDFlags} = lists:keyfind(ldflags, 1, Vars),
+
+GetCfg0 = fun(F, Cfg, [Key | Tail], Default) ->
+                 Val = case lists:keyfind(Key, 1, Cfg) of
+                           {Key, V1} -> V1;
+                           false -> Default
+                       end,
+                 case Tail of
+                     [] ->
+                         Val;
+                     _ ->
+                         F(F, Val, Tail, Default)
+                 end
+         end,
+ModCfg0 = fun(F, Cfg, [Key | Tail], Op, Default) ->
+                 {OldVal, PartCfg} = case lists:keytake(Key, 1, Cfg) of
+                                         {value, {_, V1}, V2} -> {V1, V2};
+                                         false -> {if Tail == [] -> Default; true -> [] end, Cfg}
+                                     end,
+                 case Tail of
+                     [] ->
+                         [{Key, Op(OldVal)} | PartCfg];
+                     _ ->
+                         [{Key, F(F, OldVal, Tail, Op, Default)} | PartCfg]
+                 end
+         end,
+
+FilterConfig = fun(F, Cfg, [{Path, true, ModFun, Default} | Tail]) ->
+                      F(F, ModCfg0(ModCfg0, Cfg, Path, ModFun, Default), Tail);
+                 (F, Cfg, [{Path, SourcePath, true, ModFun, Default, SourceDefault} | Tail]) ->
+                      SourceVal = GetCfg0(GetCfg0, Cfg, SourcePath, SourceDefault),
+                      ModFun2 = fun(V) -> ModFun(V, SourceVal) end,
+                      F(F, ModCfg0(ModCfg0, Cfg, Path, ModFun2, Default), Tail);
+                 (F, Cfg, [_ | Tail]) ->
+                      F(F, Cfg, Tail);
+                 (_, Cfg, []) ->
+                      Cfg
+              end,
 
 IsRebar3 = case application:get_key(rebar, vsn) of
               {ok, VSN} ->
                   [VSN1 | _] = string:tokens(VSN, "-"),
-                  [Maj, Min, Patch] = string:tokens(VSN1, "."),
+                  [Maj, _Min, _Patch] = string:tokens(VSN1, "."),
                   (list_to_integer(Maj) >= 3);
               undefined ->
                   lists:keymember(mix, 1, application:loaded_applications())
           end,
-Cfg = case file:consult(filename:join(filename:dirname(SCRIPT), "vars.config")) of
-          {ok, Terms} ->
-              Terms;
-          _Err ->
-              []
-      end,
+
+SysVer = erlang:system_info(otp_release),
 
 ProcessSingleVar = fun(F, Var, Tail) ->
                           case F(F, [Var], []) of
@@ -55,10 +84,10 @@ ProcessSingleVar = fun(F, Var, Tail) ->
                   end,
 
 ProcessVars = fun(_F, [], Acc) ->
-                      lists:reverse(Acc);
-                 (F, [{Type, Ver, Value} | Tail], Acc) when
-                        Type == if_version_above orelse
-                        Type == if_version_below ->
+                     lists:reverse(Acc);
+                (F, [{Type, Ver, Value} | Tail], Acc) when
+                       Type == if_version_above orelse
+                       Type == if_version_below ->
                      SysVer = erlang:system_info(otp_release),
                      Include = if Type == if_version_above ->
                                        SysVer > Ver;
@@ -66,78 +95,127 @@ ProcessVars = fun(_F, [], Acc) ->
                                        SysVer < Ver
                                end,
                      if Include ->
-                              F(F, Tail, ProcessSingleVar(F, Value, Acc));
+                             F(F, Tail, ProcessSingleVar(F, Value, Acc));
                         true ->
-                              F(F, Tail, Acc)
+                             F(F, Tail, Acc)
                      end;
-                 (F, [{Type, Ver, Value, ElseValue} | Tail], Acc) when
-                        Type == if_version_above orelse
-                        Type == if_version_below ->
-                     SysVer = erlang:system_info(otp_release),
+                (F, [{Type, Ver, Value, ElseValue} | Tail], Acc) when
+                       Type == if_version_above orelse
+                       Type == if_version_below ->
                      Include = if Type == if_version_above ->
                                        SysVer > Ver;
                                   true ->
                                        SysVer < Ver
                                end,
                      if Include ->
-                              F(F, Tail, ProcessSingleVar(F, Value, Acc));
+                             F(F, Tail, ProcessSingleVar(F, Value, Acc));
                         true ->
-                              F(F, Tail, ProcessSingleVar(F, ElseValue, Acc))
+                             F(F, Tail, ProcessSingleVar(F, ElseValue, Acc))
+                     end;
+                (F, [{Type, Var, Value} | Tail], Acc) when
+                       Type == if_var_true orelse
+                       Type == if_var_false ->
+                     Flag = Type == if_var_true,
+                     case proplists:get_bool(Var, Vars) of
+                         V when V == Flag ->
+                             F(F, Tail, ProcessSingleVar(F, Value, Acc));
+                         _ ->
+                             F(F, Tail, Acc)
+                     end;
+                (F, [{Type, Value} | Tail], Acc) when
+                       Type == if_rebar3 orelse
+                       Type == if_not_rebar3 ->
+                     Flag = Type == if_rebar3,
+                     case IsRebar3 == Flag of
+                         true ->
+                             F(F, Tail, ProcessSingleVar(F, Value, Acc));
+                         _ ->
+                             F(F, Tail, Acc)
+                     end;
+                (F, [{Type, Var, Match, Value} | Tail], Acc) when
+                       Type == if_var_match orelse
+                       Type == if_var_no_match ->
+                     case proplists:get_value(Var, Vars) of
+                         V when V == Match ->
+                             F(F, Tail, ProcessSingleVar(F, Value, Acc));
+                         _ ->
+                             F(F, Tail, Acc)
                      end;
-                 (F, [{Type, Var, Value} | Tail], Acc) when
-                        Type == if_var_true orelse
-                        Type == if_var_false ->
-                      Flag = Type == if_var_true,
-                      case proplists:get_bool(Var, Cfg) of
-                          V when V == Flag ->
-                              F(F, Tail, ProcessSingleVar(F, Value, Acc));
-                          _ ->
-                              F(F, Tail, Acc)
-                      end;
-                 (F, [{Type, Var, Match, Value} | Tail], Acc) when
-                        Type == if_var_match orelse
-                        Type == if_var_no_match ->
-                      case proplists:get_value(Var, Cfg) of
-                          V when V == Match ->
-                              F(F, Tail, ProcessSingleVar(F, Value, Acc));
-                          _ ->
-                              F(F, Tail, Acc)
-                      end;
-                 (F, [Other1 | Tail1], Acc) ->
-                      F(F, Tail1, [F(F, Other1, []) | Acc]);
-                 (F, Val, Acc) when is_tuple(Val) ->
-                      list_to_tuple(F(F, tuple_to_list(Val), Acc));
-                 (_F, Other2, _Acc) ->
-                      Other2
-              end,
-
-CFLags = proplists:get_value(cflags, Cfg, ""),
-CPPFLags = proplists:get_value(cppflags, Cfg, ""),
-LDFLags = proplists:get_value(ldflags, Cfg, ""),
-
-ConfigureCmd = fun(Pkg, Flags) ->
-                       {'get-deps',
-                        "sh -c 'cd deps/" ++ Pkg ++
-                            " && CFLAGS=\""++ CFLags ++"\" CPPFLAGS=\""++ CPPFLags ++"\" LDFLAGS=\""++ LDFLags ++"\"" ++
-                            " ./configure " ++ Flags ++ "'"}
-               end,
-
-Conf = ProcessVars(ProcessVars, CONFIG, []),
-
-Conf1 = case lists:keytake(post_hook_configure, 1, Conf) of
-            {value, {_, Items}, Rest} ->
-                [{post_hooks, [ConfigureCmd(Mod, string:join(Opts, " ")) || {Mod, Opts} <- Items]} | Rest];
-            _ ->
-                Conf
-        end,
+                (F, [Other1 | Tail1], Acc) ->
+                     F(F, Tail1, [F(F, Other1, []) | Acc]);
+                (F, Val, Acc) when is_tuple(Val) ->
+                     list_to_tuple(F(F, tuple_to_list(Val), Acc));
+                (_F, Other2, _Acc) ->
+                     Other2
+             end,
+
+MaybeApply = fun(Val) when is_function(Val) ->
+                    Val();
+               (Val) ->
+                    Val
+            end,
+MaybeApply2 = fun(Val, Arg) when is_function(Val) ->
+                     Val(Arg);
+                (Val, _) ->
+                     Val
+             end,
+
+AppendStr = fun(Append) ->
+                   fun("") ->
+                           lists:flatten(MaybeApply(Append));
+                      (Val) ->
+                           lists:flatten([Val, " ", MaybeApply(Append)])
+                   end
+           end,
+AppendList = fun(Append) ->
+                    fun(Val) ->
+                            Val ++ MaybeApply(Append)
+                    end
+            end,
+AppendStr2 = fun(Append) ->
+                    fun("", Arg) ->
+                            lists:flatten(MaybeApply2(Append, Arg));
+                       (Val, Arg) ->
+                            lists:flatten([Val, " ", MaybeApply2(Append, Arg)])
+                    end
+            end,
+AppendList2 = fun(Append) ->
+                     fun(Val, Arg) ->
+                             Val ++ MaybeApply2(Append, Arg)
+                     end
+             end,
+
+Rebar3DepsFilter =
+fun(DepsList) ->
+       lists:map(fun({DepName, _, {git, _, {tag, Version}}}) ->
+                         {DepName, Version};
+                    (Dep) ->
+                         Dep
+                 end, DepsList)
+end,
+
+GlobalDepsFilter =
+fun(Deps) ->
+       DepNames = lists:map(fun({DepName, _, _}) -> DepName;
+                               ({DepName, _}) -> DepName
+                            end, Deps),
+       lists:filtermap(fun(Dep) ->
+                               case code:lib_dir(Dep) of
+                                   {error, _} ->
+                                       {true, "Unable to locate dep '" ++ atom_to_list(Dep) ++ "' in system deps."};
+                                   _ ->
+                                       false
+                               end
+                       end, DepNames)
+end,
 
 {ok, Cwd} = file:get_cwd(),
 TestConfigFile = filename:join([Cwd, "test", "config.ctc"]),
 TestConfig = case file:read_file_info(TestConfigFile) of
-                 {ok, _} ->
-                     "-userconfig ct_config_plain " ++ TestConfigFile ++ " ";
-                 _ ->
-                     ""
+                {ok, _} ->
+                    ["-userconfig ct_config_plain ", TestConfigFile, " "];
+                _ ->
+                    ""
             end,
 
 ResolveDepPath = case IsRebar3 of
@@ -145,102 +223,119 @@ ResolveDepPath = case IsRebar3 of
                         fun("deps/" ++ Rest) ->
                                 Slash = string:str(Rest, "/"),
                                 Dir = "_build/default/lib/" ++
-                                    string:sub_string(Rest, 1, Slash-1),
+                                    string:sub_string(Rest, 1, Slash - 1),
                                 Dir ++ string:sub_string(Rest, Slash);
                            (Path) ->
                                 Path
                         end;
                     _ ->
                         fun(P) ->
-                                 P
+                                P
                         end
                 end,
 
-CtIncludes = case lists:keyfind(eunit_compile_opts, 1, Conf1) of
-                false ->
-                    [];
-                {_, EunitCompOpts} ->
-                    [[" -include ", filename:join([Cwd, ResolveDepPath(IncPath)])]
-                     || {i, IncPath} <- EunitCompOpts]
-            end,
+CtParams = fun(CompileOpts) ->
+                  ["-ct_hooks cth_surefire ",
+                   lists:map(fun({i, IncPath}) ->
+                                     [" -include ", filename:join([Cwd, ResolveDepPath(IncPath)])]
+                             end, CompileOpts),
+                   TestConfig]
+          end,
 
-ProcessErlOpt = fun({i, Path}) ->
-                       {i, ResolveDepPath(Path)};
-                  (ErlOpt) ->
-                       ErlOpt
-                end,
+GenDepConfigureLine =
+fun(DepPath, Flags) ->
+       ["sh -c 'if test ! -f ",DepPath,"config.status -o ",
+        "config.status -nt ",DepPath,"config.status; ",
+        "then (cd ", DepPath, " && ",
+        "CFLAGS=\"", CFlags,"\" ",
+        "CPPFLAGS=\"", CPPFlags, "\" "
+        "LDFLAGS=\"", LDFlags, "\"",
+        " ./configure ", string:join(Flags, " "),
+        "); fi'"]
+end,
+
+GenDepsConfigure =
+fun(Hooks) ->
+       lists:map(fun({Pkg, Flags}) ->
+                         DepPath = ResolveDepPath("deps/" ++ Pkg ++ "/"),
+                         {'compile',
+                          lists:flatten(GenDepConfigureLine(DepPath, Flags))}
+                 end, Hooks)
+end,
+
+ProcessErlOpt = fun(Vals) ->
+                       lists:map(
+                         fun({i, Path}) ->
+                                 {i, ResolveDepPath(Path)};
+                            (ErlOpt) ->
+                                 ErlOpt
+                         end, Vals)
+               end,
+
+ProcssXrefExclusions = fun(Items) ->
+                              [{lists:flatten(["(XC - UC) || (XU - X - B ",
+                                              [[" - ", V] || V <- Items], ")"]),
+                               []}]
+                      end,
+
+ProcessFloatingDeps =
+fun(Deps, FDeps) ->
+       lists:map(fun({DepName, _Ver, {git, Repo, _Commit}} = Dep) ->
+                         case lists:member(DepName, FDeps) of
+                             true ->
+                                 {DepName, ".*", {git, Repo}};
+                             _ ->
+                                 Dep
+                         end;
+                    (Dep2) ->
+                         Dep2
+                 end, Deps)
+end,
+
+TravisPostHooks =
+fun(true) ->
+       [{eunit, "echo '\n%%! -pa .eunit/ deps/coveralls/ebin\n" ++
+             "main(_)->{ok,F}=file:open(\"erlang.json\",[write])," ++
+             "io:fwrite(F,\"~s\",[coveralls:convert_file(" ++
+             "\".eunit/cover.coverdata\", \"" ++
+             os:getenv("TRAVIS_JOB_ID") ++
+             "\", \"travis-ci\",\"\")]).' > getcover.erl"},
+        {eunit, "escript ./getcover.erl"}];
+   (_) ->
+       []
+end,
+
+Rules = [
+        {[provider_hooks], IsRebar3,
+         AppendList([{pre, [
+                            {compile, {asn, compile}},
+                            {clean, {asn, clean}}
+                           ]}]), []},
+        {[deps], os:getenv("TRAVIS") == "true",
+         AppendList([{coveralls, ".*", {git, "https://github.com/markusn/coveralls-erl.git", "master"}}]), []},
+        {[post_hooks], [cover_enabled], os:getenv("TRAVIS") == "true",
+         AppendList2(TravisPostHooks), [], false},
+        {[pre_hooks], [post_hook_configure], true,
+         AppendList2(GenDepsConfigure), [], []},
+        {[ct_extra_params], [eunit_compile_opts], true,
+         AppendStr2(CtParams), "", []},
+        {[erl_opts], true,
+         ProcessErlOpt, []},
+        {[xref_queries], [xref_exclusions], true,
+         AppendList2(ProcssXrefExclusions), [], []},
+        {[deps], [floating_deps], IsRebar3,
+         ProcessFloatingDeps, [], []},
+        {[deps], IsRebar3,
+         Rebar3DepsFilter, []},
+        {[deps], os:getenv("USE_GLOBAL_DEPS") /= false,
+         GlobalDepsFilter, []}
+       ],
+
+Config = FilterConfig(FilterConfig, ProcessVars(ProcessVars, CONFIG, []), Rules),
+
+%io:format("ejabberd configuration:~n  ~p~n", [Config]),
 
-Conf1a = ModCfg(Conf1, [erl_opts],
-                fun(ErlOpts) -> lists:map(ProcessErlOpt, ErlOpts) end, []),
-
-Conf2a = [{ct_extra_params, lists:flatten(["-ct_hooks cth_surefire ", TestConfig,
-                                         CtIncludes])} | Conf1a],
-
-Conf2 = case IsRebar3 of
-           true ->
-               DepsFun = fun(DepsList) ->
-                                 lists:filtermap(fun({rebar_elixir_plugin, _, _}) ->
-                                                         false;
-                                                    ({DepName,_, {git,_, _} = Git}) ->
-                                                         {true, {DepName, Git}};
-                                                    (Dep) ->
-                                                         true
-                                                 end, DepsList)
-                         end,
-               RB1 = ModCfg(Conf2a, [deps], DepsFun, []),
-               ModCfg(RB1, [plugins], fun(V) -> V -- [deps_erl_opts,
-                                                      rebar_elixir_compiler,
-                                                      rebar_exunit] ++
-                                                    [rebar3_hex] end, []);
-           false ->
-               Conf2a
-       end,
-
-
-Conf3 = case lists:keytake(xref_exclusions, 1, Conf2) of
-            {value, {_, Items2}, Rest2} ->
-                [{xref_queries, [{lists:flatten(["(XC - UC) || (XU - X - B ",
-                                                 [[" - ", V] || V <- Items2], ")"]), []}]} | Rest2];
-            _ ->
-                Conf2
-        end,
-
-Conf5 = case lists:keytake(floating_deps, 1, Conf3) of
-            {value, {_, FloatingDeps}, Rest4} ->
-                case lists:keytake(deps, 1, Rest4) of
-                    {value, {_, Deps}, Rest41} ->
-                        ND = lists:map(fun({DepName, Ver, {git, Repo, _Commit}}=Dep) ->
-                                               case lists:member(DepName, FloatingDeps) of
-                                                   true ->
-                                                       {DepName, ".*", {git, Repo}};
-                                                   _ ->
-                                                       Dep
-                                               end;
-                                          (Dep2) ->
-                                               Dep2
-                                       end, Deps),
-                        [{deps, ND} | Rest41];
-                    _ ->
-                        Rest4
-                end;
-            _ ->
-                Conf3
-        end,
-
-%% When running Travis test, upload test coverage result to coveralls:
-Conf6 = case {lists:keyfind(cover_enabled, 1, Conf5), os:getenv("TRAVIS")} of
-            {{cover_enabled, true}, "true"} ->
-                JobId = os:getenv("TRAVIS_JOB_ID"),
-                CfgTemp = ModCfg(Conf5, [deps], fun(V) -> [{coveralls, ".*", {git, "https://github.com/markusn/coveralls-erl.git", "master"}}|V] end, []),
-                ModCfg(CfgTemp, [post_hooks], fun(V) -> V ++ [{ct, "echo '\n%%! -pa ebin/ deps/coveralls/ebin\nmain(_)->{ok,F}=file:open(\"erlang.json\",[write]),io:fwrite(F,\"~s\",[coveralls:convert_file(\"logs/all.coverdata\", \""++JobId++"\", \"travis-ci\", \"\")]).' > getcover.erl"},
-                                                              {ct, "escript ./getcover.erl"}] end, []);
-            _ ->
-                Conf5
-        end,
-
-%io:format("ejabberd configuration:~n  ~p~n", [Conf6]),
-
-Conf6.
+Config.
 
 %% Local Variables:
 %% mode: erlang