summaryrefslogtreecommitdiff
path: root/src/rebar_opts.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/rebar_opts.erl')
-rw-r--r--src/rebar_opts.erl155
1 files changed, 155 insertions, 0 deletions
diff --git a/src/rebar_opts.erl b/src/rebar_opts.erl
new file mode 100644
index 0000000..47451c5
--- /dev/null
+++ b/src/rebar_opts.erl
@@ -0,0 +1,155 @@
+-module(rebar_opts).
+
+-export([get/2,
+ get/3,
+ set/3,
+
+ erl_opts/1,
+
+ apply_overrides/3,
+ add_to_profile/3,
+ merge_opts/2,
+ merge_opts/3]).
+
+-include("rebar.hrl").
+
+get(Opts, Key) ->
+ {ok, Value} = dict:find(Key, Opts),
+ Value.
+
+get(Opts, Key, Default) ->
+ case dict:find(Key, Opts) of
+ {ok, Value} ->
+ Value;
+ error ->
+ Default
+ end.
+
+set(Opts, Key, Value) ->
+ dict:store(Key, Value, Opts).
+
+%% @doc Return list of erl_opts
+-spec erl_opts(rebar_dict()) -> list().
+erl_opts(Opts) ->
+ RawErlOpts = filter_defines(?MODULE:get(Opts, erl_opts, []), []),
+ Defines = [{d, list_to_atom(D)} ||
+ D <- ?MODULE:get(Opts, defines, [])],
+ AllOpts = Defines ++ RawErlOpts,
+ case proplists:is_defined(no_debug_info, AllOpts) of
+ true ->
+ [O || O <- AllOpts, O =/= no_debug_info];
+ false ->
+ [debug_info|AllOpts]
+ end.
+
+apply_overrides(Opts, Name, Overrides) ->
+ %% Inefficient. We want the order we get here though.
+ Opts1 = lists:foldl(fun({override, O}, OptsAcc) ->
+ lists:foldl(fun({deps, Value}, OptsAcc1) ->
+ set(OptsAcc1, {deps,default}, Value);
+ ({Key, Value}, OptsAcc1) ->
+ set(OptsAcc1, Key, Value)
+ end, OptsAcc, O);
+ (_, OptsAcc) ->
+ OptsAcc
+ end, Opts, Overrides),
+
+ Opts2 = lists:foldl(fun({override, N, O}, OptsAcc) when N =:= Name ->
+ lists:foldl(fun({deps, Value}, OptsAcc1) ->
+ set(OptsAcc1, {deps,default}, Value);
+ ({Key, Value}, OptsAcc1) ->
+ set(OptsAcc1, Key, Value)
+ end, OptsAcc, O);
+ (_, OptsAcc) ->
+ OptsAcc
+ end, Opts1, Overrides),
+
+ lists:foldl(fun({add, N, O}, OptsAcc) when N =:= Name ->
+ lists:foldl(fun({deps, Value}, OptsAcc1) ->
+ OldValue = ?MODULE:get(OptsAcc1, {deps,default}, []),
+ set(OptsAcc1, {deps,default}, Value++OldValue);
+ ({Key, Value}, OptsAcc1) ->
+ OldValue = ?MODULE:get(OptsAcc1, Key, []),
+ set(OptsAcc1, Key, Value++OldValue)
+ end, OptsAcc, O);
+ (_, OptsAcc) ->
+ OptsAcc
+ end, Opts2, Overrides).
+
+add_to_profile(Opts, Profile, KVs) when is_atom(Profile), is_list(KVs) ->
+ Profiles = ?MODULE:get(Opts, profiles, []),
+ ProfileOpts = dict:from_list(proplists:get_value(Profile, Profiles, [])),
+ NewOpts = merge_opts(Profile, dict:from_list(KVs), ProfileOpts),
+ NewProfiles = [{Profile, dict:to_list(NewOpts)}|lists:keydelete(Profile, 1, Profiles)],
+ set(Opts, profiles, NewProfiles).
+
+merge_opts(Profile, NewOpts, OldOpts) ->
+ Opts = merge_opts(NewOpts, OldOpts),
+
+ Opts2 = case dict:find(plugins, NewOpts) of
+ {ok, Value} ->
+ dict:store({plugins, Profile}, Value, Opts);
+ error ->
+ Opts
+ end,
+
+ case dict:find(deps, NewOpts) of
+ {ok, Value2} ->
+ dict:store({deps, Profile}, Value2, Opts2);
+ error ->
+ Opts2
+ end.
+
+merge_opts(NewOpts, OldOpts) ->
+ dict:merge(fun(deps, _NewValue, OldValue) ->
+ OldValue;
+ ({deps, _}, NewValue, _OldValue) ->
+ NewValue;
+ (plugins, NewValue, _OldValue) ->
+ NewValue;
+ ({plugins, _}, NewValue, _OldValue) ->
+ NewValue;
+ (profiles, NewValue, OldValue) ->
+ dict:to_list(merge_opts(dict:from_list(NewValue), dict:from_list(OldValue)));
+ (_Key, NewValue, OldValue) when is_list(NewValue) ->
+ case io_lib:printable_list(NewValue) of
+ true when NewValue =:= [] ->
+ case io_lib:printable_list(OldValue) of
+ true ->
+ NewValue;
+ false ->
+ OldValue
+ end;
+ true ->
+ NewValue;
+ false ->
+ rebar_utils:tup_umerge(NewValue, OldValue)
+ end;
+ (_Key, NewValue, _OldValue) ->
+ NewValue
+ end, NewOpts, OldOpts).
+
+%% Internal functions
+
+%%
+%% Filter a list of erl_opts platform_define options such that only
+%% those which match the provided architecture regex are returned.
+%%
+filter_defines([], Acc) ->
+ lists:reverse(Acc);
+filter_defines([{platform_define, ArchRegex, Key} | Rest], Acc) ->
+ case rebar_utils:is_arch(ArchRegex) of
+ true ->
+ filter_defines(Rest, [{d, Key} | Acc]);
+ false ->
+ filter_defines(Rest, Acc)
+ end;
+filter_defines([{platform_define, ArchRegex, Key, Value} | Rest], Acc) ->
+ case rebar_utils:is_arch(ArchRegex) of
+ true ->
+ filter_defines(Rest, [{d, Key, Value} | Acc]);
+ false ->
+ filter_defines(Rest, Acc)
+ end;
+filter_defines([Opt | Rest], Acc) ->
+ filter_defines(Rest, [Opt | Acc]).