aboutsummaryrefslogtreecommitdiff
path: root/rebar.config.script
diff options
context:
space:
mode:
Diffstat (limited to 'rebar.config.script')
-rw-r--r--rebar.config.script493
1 files changed, 350 insertions, 143 deletions
diff --git a/rebar.config.script b/rebar.config.script
index ccafba7ec..0023c25f3 100644
--- a/rebar.config.script
+++ b/rebar.config.script
@@ -1,45 +1,94 @@
-%%%-------------------------------------------------------------------
-%%% @author Evgeniy Khramtsov <ekhramtsov@process-one.net>
-%%% @copyright (C) 2013-2016, Evgeniy Khramtsov
-%%% @doc
+%%%----------------------------------------------------------------------
%%%
-%%% @end
-%%% Created : 1 May 2013 by Evgeniy Khramtsov <ekhramtsov@process-one.net>
-%%%-------------------------------------------------------------------
-
-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,
-
-Cfg = case file:consult(filename:join(filename:dirname(SCRIPT), "vars.config")) of
- {ok, Terms} ->
- Terms;
- _Err ->
- []
- end,
+%%% ejabberd, Copyright (C) 2002-2019 ProcessOne
+%%%
+%%% This program is free software; you can redistribute it and/or
+%%% modify it under the terms of the GNU General Public License as
+%%% published by the Free Software Foundation; either version 2 of the
+%%% License, or (at your option) any later version.
+%%%
+%%% This program is distributed in the hope that it will be useful,
+%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+%%% General Public License for more details.
+%%%
+%%% You should have received a copy of the GNU General Public License along
+%%% with this program; if not, write to the Free Software Foundation, Inc.,
+%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+%%%
+%%%----------------------------------------------------------------------
+Vars = case file:consult(filename:join([filename:dirname(SCRIPT),"vars.config"])) of
+ {ok, Terms} ->
+ Terms;
+ _Err ->
+ []
+ end ++ [{cflags, "-g -O2 -Wall"}, {cppflags, "-g -O2 -Wall"},
+ {ldflags, ""}, {system_deps, false}],
+{cflags, CFlags} = lists:keyfind(cflags, 1, Vars),
+{cppflags, CPPFlags} = lists:keyfind(cppflags, 1, Vars),
+{ldflags, LDFlags} = lists:keyfind(ldflags, 1, Vars),
+{system_deps, SystemDeps} = lists:keyfind(system_deps, 1, Vars),
+
+GetCfg = fun GetCfg(Cfg, [Key | Tail], Default) ->
+ Val = case lists:keyfind(Key, 1, Cfg) of
+ {Key, V1} -> V1;
+ false -> Default
+ end,
+ case Tail of
+ [] ->
+ Val;
+ _ ->
+ GetCfg(Val, Tail, Default)
+ end
+ end,
+ModCfg = fun ModCfg(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, ModCfg(OldVal, Tail, Op, Default)} | PartCfg]
+ end
+ end,
+
+FilterConfig = fun FilterConfig(Cfg, [{Path, true, ModFun, Default} | Tail]) ->
+ FilterConfig(ModCfg(Cfg, Path, ModFun, Default), Tail);
+ FilterConfig(Cfg, [{Path, SourcePath, true, ModFun, Default, SourceDefault} | Tail]) ->
+ SourceVal = GetCfg(Cfg, SourcePath, SourceDefault),
+ ModFun2 = fun(V) -> ModFun(V, SourceVal) end,
+ FilterConfig(ModCfg(Cfg, Path, ModFun2, Default), Tail);
+ FilterConfig(Cfg, [_ | Tail]) ->
+ FilterConfig(Cfg, Tail);
+ FilterConfig(Cfg, []) ->
+ Cfg
+ end,
+
+IsRebar3 = case application:get_key(rebar, vsn) of
+ {ok, VSN} ->
+ [VSN1 | _] = string:tokens(VSN, "-"),
+ [Maj|_] = string:tokens(VSN1, "."),
+ (list_to_integer(Maj) >= 3);
+ undefined ->
+ lists:keymember(mix, 1, application:loaded_applications())
+ end,
+
+SysVer = erlang:system_info(otp_release),
ProcessSingleVar = fun(F, Var, Tail) ->
- case F(F, [Var], []) of
+ case F([Var], []) of
[] -> Tail;
[Val] -> [Val | Tail]
end
end,
-ProcessVars = fun(_F, [], Acc) ->
- lists:reverse(Acc);
- (F, [{Type, Ver, Value} | Tail], Acc) when
- Type == if_version_above orelse
- Type == if_version_below ->
+ProcessVars = fun F([], Acc) ->
+ 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;
@@ -47,129 +96,287 @@ ProcessVars = fun(_F, [], Acc) ->
SysVer < Ver
end,
if Include ->
- F(F, Tail, ProcessSingleVar(F, Value, Acc));
+ F(Tail, ProcessSingleVar(F, Value, Acc));
true ->
- F(F, Tail, Acc)
+ 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(Tail, ProcessSingleVar(F, Value, Acc));
true ->
- F(F, Tail, ProcessSingleVar(F, ElseValue, Acc))
+ 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(Tail, ProcessSingleVar(F, Value, Acc));
+ _ ->
+ 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(Tail, ProcessSingleVar(F, Value, Acc));
+ _ ->
+ 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(Tail, ProcessSingleVar(F, Value, Acc));
+ _ ->
+ 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([{if_have_fun, MFA, Value} | Tail], Acc) ->
+ {Mod, Fun, Arity} = MFA,
+ code:ensure_loaded(Mod),
+ case erlang:function_exported(Mod, Fun, Arity) of
+ true ->
+ F(Tail, ProcessSingleVar(F, Value, Acc));
+ false ->
+ F(Tail, Acc)
+ end;
+ F([Other1 | Tail1], Acc) ->
+ F(Tail1, [F(Other1, []) | Acc]);
+ F(Val, Acc) when is_tuple(Val) ->
+ list_to_tuple(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,
+
+DepAlts = fun("esip") -> ["esip", "p1_sip"];
+ ("xmpp") -> ["xmpp", "p1_xmpp"];
+ ("fast_xml") -> ["fast_xml", "p1_xml"];
+ (Val) -> [Val]
+ end,
+
+LibDirInt = fun F([Dep|Rest], Suffix) ->
+ case code:lib_dir(Dep) of
+ {error, _} ->
+ F(Rest, Suffix);
+ V -> V ++ Suffix
+ end;
+ F([], _) ->
+ error
+ end,
+
+LibDir = fun(Name, Suffix) ->
+ LibDirInt(DepAlts(Name), Suffix)
+ end,
+
+GlobalDepsFilter =
+fun(Deps) ->
+ DepNames = lists:map(fun({DepName, _, _}) -> DepName;
+ ({DepName, _}) -> DepName
+ end, Deps),
+ lists:filtermap(fun(Dep) ->
+ case LibDir(atom_to_list(Dep), "") of
+ error ->
+ exit("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 ++ " ";
- _ ->
- ""
- end,
-
-Conf2 = [{ct_extra_params, "-ct_hooks cth_surefire "
- ++ TestConfig
- ++ "-include "
- ++ filename:join([Cwd, "tools"])} | Conf1],
-
-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.
+ {ok, _} ->
+ [" -userconfig ct_config_plain ", TestConfigFile, " "];
+ _ ->
+ ""
+ end,
+
+ResolveDepPath = case {SystemDeps, IsRebar3} of
+ {true, _} ->
+ fun("deps/" ++ Rest) ->
+ Slash = string:str(Rest, "/"),
+ case LibDir(string:sub_string(Rest, 1, Slash -1), string:sub_string(Rest, Slash)) of
+ error -> Rest;
+ V -> V
+ end;
+ (Path) ->
+ Path
+ end;
+ {_, true} ->
+ fun("deps/" ++ Rest) ->
+ Slash = string:str(Rest, "/"),
+ "_build/default/lib/" ++
+ string:sub_string(Rest, 1, Slash - 1) ++
+ string:sub_string(Rest, Slash);
+ (Path) ->
+ Path
+ end;
+ _ ->
+ fun(P) ->
+ P
+ end
+ end,
+
+CtParams = fun(CompileOpts) ->
+ ["-ct_hooks cth_surefire ",
+ lists:map(fun({i, IncPath}) ->
+ [" -include ", filename:absname(ResolveDepPath(IncPath), Cwd)]
+ end, CompileOpts),
+ TestConfig]
+ end,
+
+GenDepConfigureLine =
+fun(DepPath, Flags) ->
+ ["sh -c 'if test ! -f config.status -o ",
+ "../../config.status -nt config.status; ",
+ "then (",
+ "CFLAGS=\"", CFlags,"\" ",
+ "CPPFLAGS=\"", CPPFlags, "\" "
+ "LDFLAGS=\"", LDFlags, "\"",
+ " ./configure ", string:join(Flags, " "),
+ "); fi'"]
+end,
+
+GenDepsConfigure =
+fun(Hooks) ->
+ lists:map(fun({Pkg, Flags}) ->
+ DepPath = ResolveDepPath("deps/" ++ Pkg ++ "/"),
+ Line = lists:flatten(GenDepConfigureLine(DepPath, Flags)),
+ {add, list_to_atom(Pkg), [{pre_hooks, [{{pc, compile}, Line}, {'compile', Line}, {'configure-deps', Line}]}]}
+ 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},
+ {[overrides], [post_hook_configure], SystemDeps == false,
+ 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], true,
+ ProcessFloatingDeps, [], []},
+ {[deps], IsRebar3,
+ Rebar3DepsFilter, []},
+ {[deps], SystemDeps /= false,
+ GlobalDepsFilter, []}
+ ],
+
+Config = [{plugin_dir, filename:join([filename:dirname(SCRIPT),"plugins"])}]++
+FilterConfig(ProcessVars(CONFIG, []), Rules),
+
+%io:format("ejabberd configuration:~n ~p~n", [Config]),
+
+Config.
%% Local Variables:
%% mode: erlang