Improve compilation with rebar3

This commit is contained in:
Paweł Chmielowski 2017-01-26 16:43:47 +01:00
parent 11326692f2
commit 2f3f6f8b71
2 changed files with 259 additions and 161 deletions

View File

@ -43,12 +43,12 @@
{tag, "1.0.2"}}}}, {tag, "1.0.2"}}}},
{if_var_true, riak, {riakc, ".*", {git, "https://github.com/basho/riak-erlang-client", {if_var_true, riak, {riakc, ".*", {git, "https://github.com/basho/riak-erlang-client",
{tag, "2.4.1"}}}}, {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", {if_var_true, elixir, {elixir, ".*", {git, "https://github.com/elixir-lang/elixir",
{tag, {if_version_above, "17", "v1.2.6", "v1.1.1"}}}}}, {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 %% 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, ".*", {if_not_rebar3, {if_var_true, elixir, {rebar_elixir_plugin, ".*",
{git, "https://github.com/processone/rebar_elixir_plugin", "0.1.0"}}}, {git, "https://github.com/processone/rebar_elixir_plugin", "0.1.0"}}}},
{if_var_true, iconv, {iconv, ".*", {git, "https://github.com/processone/iconv", {if_var_true, iconv, {iconv, ".*", {git, "https://github.com/processone/iconv",
{tag, "1.0.3"}}}}, {tag, "1.0.3"}}}},
{if_var_true, tools, {meck, "0.8.*", {git, "https://github.com/eproxus/meck", {if_var_true, tools, {meck, "0.8.*", {git, "https://github.com/eproxus/meck",
@ -96,9 +96,12 @@
{deps_erl_opts, [{if_var_true, hipe, native}]}. {deps_erl_opts, [{if_var_true, hipe, native}]}.
{plugins, [deps_erl_opts, {if_rebar3, {plugins, [rebar3_hex, {provider_asn1, "0.2.0"}]}}.
{if_var_true, elixir, rebar_elixir_compiler}, {if_not_rebar3, {plugins, [
{if_var_true, elixir, rebar_exunit}]}. deps_erl_opts,
{if_var_true, elixir, rebar_elixir_compiler},
{if_var_true, elixir, rebar_exunit}
]}}.
{if_var_true, elixir, {if_var_true, elixir,
{lib_dirs, ["deps/elixir/lib"]}}. {lib_dirs, ["deps/elixir/lib"]}}.

View File

@ -18,34 +18,63 @@
%%% %%%
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
ModCfg0 = fun(F, Cfg, [Key|Tail], Op, Default) -> Vars = case file:consult("vars.config") of
{OldVal,PartCfg} = case lists:keytake(Key, 1, Cfg) of {ok, Terms} ->
{value, {_, V1}, V2} -> {V1, V2}; Terms;
false -> {if Tail == [] -> Default; true -> [] end, Cfg} _Err ->
end, []
case Tail of end ++ [{cflags, "-g -O2 -Wall"}, {cppflags, "-g -O2 -Wall"}, {ldflags, ""}],
[] -> {cflags, CFlags} = lists:keyfind(cflags, 1, Vars),
[{Key, Op(OldVal)} | PartCfg]; {cppflags, CPPFlags} = lists:keyfind(cppflags, 1, Vars),
_ -> {ldflags, LDFlags} = lists:keyfind(ldflags, 1, Vars),
[{Key, F(F, OldVal, Tail, Op, Default)} | PartCfg]
end GetCfg0 = fun(F, Cfg, [Key | Tail], Default) ->
end, Val = case lists:keyfind(Key, 1, Cfg) of
ModCfg = fun(Cfg, Keys, Op, Default) -> ModCfg0(ModCfg0, Cfg, Keys, Op, Default) end, {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 IsRebar3 = case application:get_key(rebar, vsn) of
{ok, VSN} -> {ok, VSN} ->
[VSN1 | _] = string:tokens(VSN, "-"), [VSN1 | _] = string:tokens(VSN, "-"),
[Maj, Min, Patch] = string:tokens(VSN1, "."), [Maj, _Min, _Patch] = string:tokens(VSN1, "."),
(list_to_integer(Maj) >= 3); (list_to_integer(Maj) >= 3);
undefined -> undefined ->
lists:keymember(mix, 1, application:loaded_applications()) lists:keymember(mix, 1, application:loaded_applications())
end, end,
Cfg = case file:consult(filename:join(filename:dirname(SCRIPT), "vars.config")) of
{ok, Terms} -> SysVer = erlang:system_info(otp_release),
Terms;
_Err ->
[]
end,
ProcessSingleVar = fun(F, Var, Tail) -> ProcessSingleVar = fun(F, Var, Tail) ->
case F(F, [Var], []) of case F(F, [Var], []) of
@ -55,10 +84,10 @@ ProcessSingleVar = fun(F, Var, Tail) ->
end, end,
ProcessVars = fun(_F, [], Acc) -> ProcessVars = fun(_F, [], Acc) ->
lists:reverse(Acc); lists:reverse(Acc);
(F, [{Type, Ver, Value} | Tail], Acc) when (F, [{Type, Ver, Value} | Tail], Acc) when
Type == if_version_above orelse Type == if_version_above orelse
Type == if_version_below -> Type == if_version_below ->
SysVer = erlang:system_info(otp_release), SysVer = erlang:system_info(otp_release),
Include = if Type == if_version_above -> Include = if Type == if_version_above ->
SysVer > Ver; SysVer > Ver;
@ -66,78 +95,127 @@ ProcessVars = fun(_F, [], Acc) ->
SysVer < Ver SysVer < Ver
end, end,
if Include -> if Include ->
F(F, Tail, ProcessSingleVar(F, Value, Acc)); F(F, Tail, ProcessSingleVar(F, Value, Acc));
true -> true ->
F(F, Tail, Acc) F(F, Tail, Acc)
end; end;
(F, [{Type, Ver, Value, ElseValue} | Tail], Acc) when (F, [{Type, Ver, Value, ElseValue} | Tail], Acc) when
Type == if_version_above orelse Type == if_version_above orelse
Type == if_version_below -> Type == if_version_below ->
SysVer = erlang:system_info(otp_release),
Include = if Type == if_version_above -> Include = if Type == if_version_above ->
SysVer > Ver; SysVer > Ver;
true -> true ->
SysVer < Ver SysVer < Ver
end, end,
if Include -> if Include ->
F(F, Tail, ProcessSingleVar(F, Value, Acc)); F(F, Tail, ProcessSingleVar(F, Value, Acc));
true -> true ->
F(F, Tail, ProcessSingleVar(F, ElseValue, Acc)) F(F, Tail, ProcessSingleVar(F, ElseValue, Acc))
end; end;
(F, [{Type, Var, Value} | Tail], Acc) when (F, [{Type, Var, Value} | Tail], Acc) when
Type == if_var_true orelse Type == if_var_true orelse
Type == if_var_false -> Type == if_var_false ->
Flag = Type == if_var_true, Flag = Type == if_var_true,
case proplists:get_bool(Var, Cfg) of case proplists:get_bool(Var, Vars) of
V when V == Flag -> V when V == Flag ->
F(F, Tail, ProcessSingleVar(F, Value, Acc)); F(F, Tail, ProcessSingleVar(F, Value, Acc));
_ -> _ ->
F(F, Tail, Acc) F(F, Tail, Acc)
end; end;
(F, [{Type, Var, Match, Value} | Tail], Acc) when (F, [{Type, Value} | Tail], Acc) when
Type == if_var_match orelse Type == if_rebar3 orelse
Type == if_var_no_match -> Type == if_not_rebar3 ->
case proplists:get_value(Var, Cfg) of Flag = Type == if_rebar3,
V when V == Match -> case IsRebar3 == Flag of
F(F, Tail, ProcessSingleVar(F, Value, Acc)); true ->
_ -> F(F, Tail, ProcessSingleVar(F, Value, Acc));
F(F, Tail, Acc) _ ->
end; F(F, Tail, Acc)
(F, [Other1 | Tail1], Acc) -> end;
F(F, Tail1, [F(F, Other1, []) | Acc]); (F, [{Type, Var, Match, Value} | Tail], Acc) when
(F, Val, Acc) when is_tuple(Val) -> Type == if_var_match orelse
list_to_tuple(F(F, tuple_to_list(Val), Acc)); Type == if_var_no_match ->
(_F, Other2, _Acc) -> case proplists:get_value(Var, Vars) of
Other2 V when V == Match ->
end, 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, ""), MaybeApply = fun(Val) when is_function(Val) ->
CPPFLags = proplists:get_value(cppflags, Cfg, ""), Val();
LDFLags = proplists:get_value(ldflags, Cfg, ""), (Val) ->
Val
end,
MaybeApply2 = fun(Val, Arg) when is_function(Val) ->
Val(Arg);
(Val, _) ->
Val
end,
ConfigureCmd = fun(Pkg, Flags) -> AppendStr = fun(Append) ->
{'get-deps', fun("") ->
"sh -c 'cd deps/" ++ Pkg ++ lists:flatten(MaybeApply(Append));
" && CFLAGS=\""++ CFLags ++"\" CPPFLAGS=\""++ CPPFLags ++"\" LDFLAGS=\""++ LDFLags ++"\"" ++ (Val) ->
" ./configure " ++ Flags ++ "'"} lists:flatten([Val, " ", MaybeApply(Append)])
end, 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,
Conf = ProcessVars(ProcessVars, CONFIG, []), Rebar3DepsFilter =
fun(DepsList) ->
lists:map(fun({DepName, _, {git, _, {tag, Version}}}) ->
{DepName, Version};
(Dep) ->
Dep
end, DepsList)
end,
Conf1 = case lists:keytake(post_hook_configure, 1, Conf) of GlobalDepsFilter =
{value, {_, Items}, Rest} -> fun(Deps) ->
[{post_hooks, [ConfigureCmd(Mod, string:join(Opts, " ")) || {Mod, Opts} <- Items]} | Rest]; DepNames = lists:map(fun({DepName, _, _}) -> DepName;
_ -> ({DepName, _}) -> DepName
Conf end, Deps),
end, 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(), {ok, Cwd} = file:get_cwd(),
TestConfigFile = filename:join([Cwd, "test", "config.ctc"]), TestConfigFile = filename:join([Cwd, "test", "config.ctc"]),
TestConfig = case file:read_file_info(TestConfigFile) of TestConfig = case file:read_file_info(TestConfigFile) of
{ok, _} -> {ok, _} ->
"-userconfig ct_config_plain " ++ TestConfigFile ++ " "; ["-userconfig ct_config_plain ", TestConfigFile, " "];
_ -> _ ->
"" ""
end, end,
ResolveDepPath = case IsRebar3 of ResolveDepPath = case IsRebar3 of
@ -145,102 +223,119 @@ ResolveDepPath = case IsRebar3 of
fun("deps/" ++ Rest) -> fun("deps/" ++ Rest) ->
Slash = string:str(Rest, "/"), Slash = string:str(Rest, "/"),
Dir = "_build/default/lib/" ++ Dir = "_build/default/lib/" ++
string:sub_string(Rest, 1, Slash-1), string:sub_string(Rest, 1, Slash - 1),
Dir ++ string:sub_string(Rest, Slash); Dir ++ string:sub_string(Rest, Slash);
(Path) -> (Path) ->
Path Path
end; end;
_ -> _ ->
fun(P) -> fun(P) ->
P P
end end
end, end,
CtIncludes = case lists:keyfind(eunit_compile_opts, 1, Conf1) of CtParams = fun(CompileOpts) ->
false -> ["-ct_hooks cth_surefire ",
[]; lists:map(fun({i, IncPath}) ->
{_, EunitCompOpts} -> [" -include ", filename:join([Cwd, ResolveDepPath(IncPath)])]
[[" -include ", filename:join([Cwd, ResolveDepPath(IncPath)])] end, CompileOpts),
|| {i, IncPath} <- EunitCompOpts] TestConfig]
end, end,
ProcessErlOpt = fun({i, Path}) -> GenDepConfigureLine =
{i, ResolveDepPath(Path)}; fun(DepPath, Flags) ->
(ErlOpt) -> ["sh -c 'if test ! -f ",DepPath,"config.status -o ",
ErlOpt "config.status -nt ",DepPath,"config.status; ",
end, "then (cd ", DepPath, " && ",
"CFLAGS=\"", CFlags,"\" ",
"CPPFLAGS=\"", CPPFlags, "\" "
"LDFLAGS=\"", LDFlags, "\"",
" ./configure ", string:join(Flags, " "),
"); fi'"]
end,
Conf1a = ModCfg(Conf1, [erl_opts], GenDepsConfigure =
fun(ErlOpts) -> lists:map(ProcessErlOpt, ErlOpts) end, []), fun(Hooks) ->
lists:map(fun({Pkg, Flags}) ->
DepPath = ResolveDepPath("deps/" ++ Pkg ++ "/"),
{'compile',
lists:flatten(GenDepConfigureLine(DepPath, Flags))}
end, Hooks)
end,
Conf2a = [{ct_extra_params, lists:flatten(["-ct_hooks cth_surefire ", TestConfig, ProcessErlOpt = fun(Vals) ->
CtIncludes])} | Conf1a], lists:map(
fun({i, Path}) ->
{i, ResolveDepPath(Path)};
(ErlOpt) ->
ErlOpt
end, Vals)
end,
Conf2 = case IsRebar3 of ProcssXrefExclusions = fun(Items) ->
true -> [{lists:flatten(["(XC - UC) || (XU - X - B ",
DepsFun = fun(DepsList) -> [[" - ", V] || V <- Items], ")"]),
lists:filtermap(fun({rebar_elixir_plugin, _, _}) -> []}]
false; end,
({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,
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,
Conf3 = case lists:keytake(xref_exclusions, 1, Conf2) of TravisPostHooks =
{value, {_, Items2}, Rest2} -> fun(true) ->
[{xref_queries, [{lists:flatten(["(XC - UC) || (XU - X - B ", [{eunit, "echo '\n%%! -pa .eunit/ deps/coveralls/ebin\n" ++
[[" - ", V] || V <- Items2], ")"]), []}]} | Rest2]; "main(_)->{ok,F}=file:open(\"erlang.json\",[write])," ++
_ -> "io:fwrite(F,\"~s\",[coveralls:convert_file(" ++
Conf2 "\".eunit/cover.coverdata\", \"" ++
end, os:getenv("TRAVIS_JOB_ID") ++
"\", \"travis-ci\",\"\")]).' > getcover.erl"},
{eunit, "escript ./getcover.erl"}];
(_) ->
[]
end,
Conf5 = case lists:keytake(floating_deps, 1, Conf3) of Rules = [
{value, {_, FloatingDeps}, Rest4} -> {[provider_hooks], IsRebar3,
case lists:keytake(deps, 1, Rest4) of AppendList([{pre, [
{value, {_, Deps}, Rest41} -> {compile, {asn, compile}},
ND = lists:map(fun({DepName, Ver, {git, Repo, _Commit}}=Dep) -> {clean, {asn, clean}}
case lists:member(DepName, FloatingDeps) of ]}]), []},
true -> {[deps], os:getenv("TRAVIS") == "true",
{DepName, ".*", {git, Repo}}; AppendList([{coveralls, ".*", {git, "https://github.com/markusn/coveralls-erl.git", "master"}}]), []},
_ -> {[post_hooks], [cover_enabled], os:getenv("TRAVIS") == "true",
Dep AppendList2(TravisPostHooks), [], false},
end; {[pre_hooks], [post_hook_configure], true,
(Dep2) -> AppendList2(GenDepsConfigure), [], []},
Dep2 {[ct_extra_params], [eunit_compile_opts], true,
end, Deps), AppendStr2(CtParams), "", []},
[{deps, ND} | Rest41]; {[erl_opts], true,
_ -> ProcessErlOpt, []},
Rest4 {[xref_queries], [xref_exclusions], true,
end; AppendList2(ProcssXrefExclusions), [], []},
_ -> {[deps], [floating_deps], IsRebar3,
Conf3 ProcessFloatingDeps, [], []},
end, {[deps], IsRebar3,
Rebar3DepsFilter, []},
{[deps], os:getenv("USE_GLOBAL_DEPS") /= false,
GlobalDepsFilter, []}
],
%% When running Travis test, upload test coverage result to coveralls: Config = FilterConfig(FilterConfig, ProcessVars(ProcessVars, CONFIG, []), Rules),
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]), %io:format("ejabberd configuration:~n ~p~n", [Config]),
Conf6. Config.
%% Local Variables: %% Local Variables:
%% mode: erlang %% mode: erlang