No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

188 líneas
6.5 KiB

  1. -module(rebar_opts).
  2. -export([get/2,
  3. get/3,
  4. set/3,
  5. erl_opts/1,
  6. apply_overrides/3,
  7. add_to_profile/3,
  8. merge_opts/2,
  9. merge_opts/3]).
  10. -include("rebar.hrl").
  11. get(Opts, Key) ->
  12. {ok, Value} = dict:find(Key, Opts),
  13. Value.
  14. get(Opts, Key, Default) ->
  15. case dict:find(Key, Opts) of
  16. {ok, Value} ->
  17. Value;
  18. error ->
  19. Default
  20. end.
  21. set(Opts, Key, Value) ->
  22. dict:store(Key, Value, Opts).
  23. %% @doc Return list of erl_opts
  24. -spec erl_opts(rebar_dict()) -> list().
  25. erl_opts(Opts) ->
  26. RawErlOpts = filter_defines(?MODULE:get(Opts, erl_opts, []), []),
  27. Defines = [{d, list_to_atom(D)} ||
  28. D <- ?MODULE:get(Opts, defines, [])],
  29. AllOpts = Defines ++ RawErlOpts,
  30. case proplists:is_defined(no_debug_info, AllOpts) of
  31. true ->
  32. [O || O <- AllOpts, O =/= no_debug_info];
  33. false ->
  34. [debug_info|AllOpts]
  35. end.
  36. apply_overrides(Opts, Name, Overrides) ->
  37. %% Inefficient. We want the order we get here though.
  38. Opts1 = lists:foldl(fun({override, O}, OptsAcc) ->
  39. lists:foldl(fun({deps, Value}, OptsAcc1) ->
  40. set(OptsAcc1, {deps,default}, Value);
  41. ({Key, Value}, OptsAcc1) ->
  42. set(OptsAcc1, Key, Value)
  43. end, OptsAcc, O);
  44. (_, OptsAcc) ->
  45. OptsAcc
  46. end, Opts, Overrides),
  47. Opts2 = lists:foldl(fun({override, N, O}, OptsAcc) when N =:= Name ->
  48. lists:foldl(fun({deps, Value}, OptsAcc1) ->
  49. set(OptsAcc1, {deps,default}, Value);
  50. ({Key, Value}, OptsAcc1) ->
  51. set(OptsAcc1, Key, Value)
  52. end, OptsAcc, O);
  53. (_, OptsAcc) ->
  54. OptsAcc
  55. end, Opts1, Overrides),
  56. lists:foldl(fun({add, N, O}, OptsAcc) when N =:= Name ->
  57. lists:foldl(fun({deps, Value}, OptsAcc1) ->
  58. OldValue = ?MODULE:get(OptsAcc1, {deps,default}, []),
  59. set(OptsAcc1, {deps,default}, Value++OldValue);
  60. ({Key, Value}, OptsAcc1) ->
  61. OldValue = ?MODULE:get(OptsAcc1, Key, []),
  62. set(OptsAcc1, Key, Value++OldValue)
  63. end, OptsAcc, O);
  64. (_, OptsAcc) ->
  65. OptsAcc
  66. end, Opts2, Overrides).
  67. add_to_profile(Opts, Profile, KVs) when is_atom(Profile), is_list(KVs) ->
  68. Profiles = ?MODULE:get(Opts, profiles, []),
  69. ProfileOpts = dict:from_list(proplists:get_value(Profile, Profiles, [])),
  70. NewOpts = merge_opts(Profile, dict:from_list(KVs), ProfileOpts),
  71. NewProfiles = [{Profile, dict:to_list(NewOpts)}|lists:keydelete(Profile, 1, Profiles)],
  72. set(Opts, profiles, NewProfiles).
  73. merge_opts(Profile, NewOpts, OldOpts) ->
  74. Opts = merge_opts(NewOpts, OldOpts),
  75. Opts2 = case dict:find(plugins, NewOpts) of
  76. {ok, Value} ->
  77. dict:store({plugins, Profile}, Value, Opts);
  78. error ->
  79. Opts
  80. end,
  81. case dict:find(deps, NewOpts) of
  82. {ok, Value2} ->
  83. dict:store({deps, Profile}, Value2, Opts2);
  84. error ->
  85. Opts2
  86. end.
  87. merge_opts(NewOpts, OldOpts) ->
  88. dict:merge(fun merge_opt/3, NewOpts, OldOpts).
  89. %% Internal functions
  90. %%
  91. %% Function for dict:merge/3 (in merge_opts/2) to merge options by priority.
  92. %%
  93. merge_opt(deps, _NewValue, OldValue) ->
  94. OldValue;
  95. merge_opt({deps, _}, NewValue, _OldValue) ->
  96. NewValue;
  97. merge_opt(plugins, NewValue, _OldValue) ->
  98. NewValue;
  99. merge_opt({plugins, _}, NewValue, _OldValue) ->
  100. NewValue;
  101. merge_opt(profiles, NewValue, OldValue) ->
  102. dict:to_list(merge_opts(dict:from_list(NewValue), dict:from_list(OldValue)));
  103. merge_opt(mib_first_files, Value, Value) ->
  104. Value;
  105. merge_opt(mib_first_files, NewValue, OldValue) ->
  106. OldValue ++ NewValue;
  107. merge_opt(relx, NewValue, OldValue) ->
  108. rebar_utils:tup_umerge(OldValue, NewValue);
  109. merge_opt(Key, NewValue, OldValue)
  110. when Key == erl_opts; Key == eunit_compile_opts; Key == ct_compile_opts ->
  111. merge_erl_opts(lists:reverse(OldValue), NewValue);
  112. merge_opt(_Key, NewValue, OldValue) when is_list(NewValue) ->
  113. case io_lib:printable_list(NewValue) of
  114. true when NewValue =:= [] ->
  115. case io_lib:printable_list(OldValue) of
  116. true ->
  117. NewValue;
  118. false ->
  119. OldValue
  120. end;
  121. true ->
  122. NewValue;
  123. false ->
  124. rebar_utils:tup_umerge(NewValue, OldValue)
  125. end;
  126. merge_opt(_Key, NewValue, _OldValue) ->
  127. NewValue.
  128. %%
  129. %% Merge Erlang compiler options such that the result
  130. %% a) Doesn't contain duplicates.
  131. %% b) Resulting options are ordered by increasing precedence as expected by
  132. %% the compiler.
  133. %% The first parameter is the lower precedence options, in reverse order, to
  134. %% be merged with the higher-precedence options in the second parameter.
  135. %%
  136. merge_erl_opts([Opt | Opts], []) ->
  137. merge_erl_opts(Opts, [Opt]);
  138. merge_erl_opts([Opt | Opts], Merged) ->
  139. case lists:member(Opt, Merged) of
  140. true ->
  141. merge_erl_opts(Opts, Merged);
  142. _ ->
  143. merge_erl_opts(Opts, [Opt | Merged])
  144. end;
  145. merge_erl_opts([], Merged) ->
  146. Merged.
  147. %%
  148. %% Filter a list of erl_opts platform_define options such that only
  149. %% those which match the provided architecture regex are returned.
  150. %%
  151. filter_defines([], Acc) ->
  152. lists:reverse(Acc);
  153. filter_defines([{platform_define, ArchRegex, Key} | Rest], Acc) ->
  154. case rebar_utils:is_arch(ArchRegex) of
  155. true ->
  156. filter_defines(Rest, [{d, Key} | Acc]);
  157. false ->
  158. filter_defines(Rest, Acc)
  159. end;
  160. filter_defines([{platform_define, ArchRegex, Key, Value} | Rest], Acc) ->
  161. case rebar_utils:is_arch(ArchRegex) of
  162. true ->
  163. filter_defines(Rest, [{d, Key, Value} | Acc]);
  164. false ->
  165. filter_defines(Rest, Acc)
  166. end;
  167. filter_defines([Opt | Rest], Acc) ->
  168. filter_defines(Rest, [Opt | Acc]).