Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

555 righe
22 KiB

  1. -module(rebar_profiles_SUITE).
  2. -export([init_per_suite/1,
  3. end_per_suite/1,
  4. init_per_testcase/2,
  5. end_per_testcase/2,
  6. all/0,
  7. profile_new_key/1,
  8. profile_merge_keys/1,
  9. explicit_profile_deduplicate_deps/1,
  10. implicit_profile_deduplicate_deps/1,
  11. all_deps_code_paths/1,
  12. profile_merges/1,
  13. same_profile_deduplication/1,
  14. stack_deduplication/1,
  15. add_to_profile/1,
  16. add_to_existing_profile/1,
  17. profiles_remain_applied_with_config_present/1,
  18. deduplicated_paths/1,
  19. test_profile_applied_at_completion/1,
  20. test_profile_applied_before_compile/1,
  21. test_profile_applied_before_eunit/1,
  22. test_profile_applied_to_apps/1,
  23. test_profile_erl_opts_order_1/1,
  24. test_profile_erl_opts_order_2/1,
  25. test_profile_erl_opts_order_3/1,
  26. test_profile_erl_opts_order_4/1,
  27. test_profile_erl_opts_order_5/1,
  28. first_files_exception/1]).
  29. -include_lib("common_test/include/ct.hrl").
  30. -include_lib("eunit/include/eunit.hrl").
  31. -include_lib("kernel/include/file.hrl").
  32. all() ->
  33. [profile_new_key, profile_merge_keys, all_deps_code_paths, profile_merges,
  34. explicit_profile_deduplicate_deps, implicit_profile_deduplicate_deps,
  35. same_profile_deduplication, stack_deduplication,
  36. add_to_profile, add_to_existing_profile,
  37. profiles_remain_applied_with_config_present,
  38. deduplicated_paths,
  39. test_profile_applied_at_completion,
  40. test_profile_applied_before_compile,
  41. test_profile_applied_before_eunit,
  42. test_profile_applied_to_apps,
  43. test_profile_erl_opts_order_1,
  44. test_profile_erl_opts_order_2,
  45. test_profile_erl_opts_order_3,
  46. test_profile_erl_opts_order_4,
  47. test_profile_erl_opts_order_5,
  48. first_files_exception].
  49. init_per_suite(Config) ->
  50. application:start(meck),
  51. Config.
  52. end_per_suite(_Config) ->
  53. application:stop(meck).
  54. init_per_testcase(_, Config) ->
  55. rebar_test_utils:init_rebar_state(Config, "profiles_").
  56. end_per_testcase(_, Config) ->
  57. meck:unload(),
  58. Config.
  59. profile_new_key(Config) ->
  60. AppDir = ?config(apps, Config),
  61. AllDeps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}
  62. ,{"b", "1.0.0", []}]),
  63. {SrcDeps, []} = rebar_test_utils:flat_deps(AllDeps),
  64. mock_git_resource:mock([{deps, SrcDeps}]),
  65. Name = rebar_test_utils:create_random_name("profile_new_key_"),
  66. Vsn = rebar_test_utils:create_random_vsn(),
  67. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  68. Deps = rebar_test_utils:top_level_deps(
  69. rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}
  70. ,{"b", "1.0.0", []}])),
  71. ct:pal("Deps ~p", [Deps]),
  72. RebarConfig = [{profiles,
  73. [{ct,
  74. [{deps, Deps}]}]}],
  75. rebar_test_utils:run_and_check(Config, RebarConfig,
  76. ["as", "ct", "compile"], {ok, [{app, Name}
  77. ,{dep, "a", "1.0.0"}
  78. ,{dep, "b", "1.0.0"}]}).
  79. profile_merge_keys(Config) ->
  80. AppDir = ?config(apps, Config),
  81. AllDeps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}
  82. ,{"b", "1.0.0", []}
  83. ,{"b", "2.0.0", []}]),
  84. {SrcDeps, []} = rebar_test_utils:flat_deps(AllDeps),
  85. mock_git_resource:mock([{deps, SrcDeps}]),
  86. Name = rebar_test_utils:create_random_name("profile_new_key_"),
  87. Vsn = rebar_test_utils:create_random_vsn(),
  88. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  89. Deps = rebar_test_utils:top_level_deps(
  90. rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}
  91. ,{"b", "1.0.0", []}])),
  92. ProfileDeps = rebar_test_utils:top_level_deps(
  93. rebar_test_utils:expand_deps(git, [{"b", "2.0.0", []}])),
  94. RebarConfig = [{deps, Deps},
  95. {profiles,
  96. [{ct,
  97. [{deps, ProfileDeps}]}]}],
  98. rebar_test_utils:run_and_check(Config, RebarConfig,
  99. ["as", "ct", "compile"], {ok, [{app, Name}
  100. ,{dep, "a", "1.0.0"}
  101. ,{dep, "b", "2.0.0"}]}).
  102. explicit_profile_deduplicate_deps(Config) ->
  103. AppDir = ?config(apps, Config),
  104. AllDeps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}
  105. ,{"a", "2.0.0", []}
  106. ,{"b", "1.0.0", []}
  107. ,{"b", "2.0.0", []}]),
  108. {SrcDeps, []} = rebar_test_utils:flat_deps(AllDeps),
  109. mock_git_resource:mock([{deps, SrcDeps}]),
  110. Name = rebar_test_utils:create_random_name("explicit_profile_deduplicate_deps_"),
  111. Vsn = rebar_test_utils:create_random_vsn(),
  112. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  113. FooDeps = rebar_test_utils:top_level_deps(
  114. rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []},
  115. {"b", "2.0.0", []}])),
  116. BarDeps = rebar_test_utils:top_level_deps(
  117. rebar_test_utils:expand_deps(git, [{"b", "1.0.0", []}])),
  118. RebarConfig = [{profiles,
  119. [{foo,
  120. [{deps, FooDeps}]},
  121. {bar,
  122. [{deps, BarDeps}]}]}],
  123. rebar_test_utils:run_and_check(Config, RebarConfig,
  124. ["as", "bar,foo,bar", "compile"], {ok, [{app, Name}
  125. ,{dep, "a", "1.0.0"}
  126. ,{dep, "b", "1.0.0"}]}).
  127. implicit_profile_deduplicate_deps(Config) ->
  128. AppDir = ?config(apps, Config),
  129. AllDeps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}
  130. ,{"a", "2.0.0", []}
  131. ,{"b", "1.0.0", []}
  132. ,{"b", "2.0.0", []}]),
  133. {SrcDeps, []} = rebar_test_utils:flat_deps(AllDeps),
  134. mock_git_resource:mock([{deps, SrcDeps}]),
  135. Name = rebar_test_utils:create_random_name("implicit_profile_deduplicate_deps_"),
  136. Vsn = rebar_test_utils:create_random_vsn(),
  137. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  138. TestDeps = rebar_test_utils:top_level_deps(
  139. rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []},
  140. {"b", "2.0.0", []}])),
  141. ProfileDeps = rebar_test_utils:top_level_deps(
  142. rebar_test_utils:expand_deps(git, [{"b", "1.0.0", []}])),
  143. RebarConfig = [{profiles,
  144. [{test,
  145. [{deps, TestDeps}]},
  146. {bar,
  147. [{deps, ProfileDeps}]}]}],
  148. rebar_test_utils:run_and_check(Config, RebarConfig,
  149. ["as", "test,bar", "eunit"], {ok, [{app, Name}
  150. ,{dep, "a", "1.0.0"}
  151. ,{dep, "b", "2.0.0"}]}).
  152. all_deps_code_paths(Config) ->
  153. AppDir = ?config(apps, Config),
  154. AllDeps = rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}
  155. ,{"b", "2.0.0", []}]),
  156. {SrcDeps, []} = rebar_test_utils:flat_deps(AllDeps),
  157. mock_git_resource:mock([{deps, SrcDeps}]),
  158. Name = rebar_test_utils:create_random_name("all_deps_code_paths"),
  159. Vsn = rebar_test_utils:create_random_vsn(),
  160. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  161. Deps = rebar_test_utils:top_level_deps(
  162. rebar_test_utils:expand_deps(git, [{"a", "1.0.0", []}])),
  163. ProfileDeps = rebar_test_utils:top_level_deps(
  164. rebar_test_utils:expand_deps(git, [{"b", "2.0.0", []}])),
  165. RebarConfig = [{deps, Deps},
  166. {profiles,
  167. [{all_deps_test,
  168. [{deps, ProfileDeps}]}]}],
  169. os:putenv("REBAR_PROFILE", "all_deps_test"),
  170. {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig,
  171. ["compile"], {ok, [{app, Name}
  172. ,{dep, "a", "1.0.0"}
  173. ,{dep, "b", "2.0.0"}]}),
  174. os:putenv("REBAR_PROFILE", ""),
  175. Paths = rebar_state:code_paths(State, all_deps),
  176. Path = lists:reverse(["_build", "all_deps_test", "lib", "b", "ebin"]),
  177. ?assert(lists:any(fun(X) ->
  178. Path =:= lists:sublist(lists:reverse(filename:split(X)), 5)
  179. end, Paths)).
  180. profile_merges(_Config) ->
  181. RebarConfig = [{test1, [{key1, 1, 2}, key2]},
  182. {test2, "hello"},
  183. {test3, [key3]},
  184. {test4, "oldvalue"},
  185. {test5, [{key5, true}]},
  186. {test6, [{key6, false}]},
  187. {profiles,
  188. [{profile1,
  189. [{test1, [{key3, 5}, key1]}]},
  190. {profile2, [{test2, "goodbye"},
  191. {test3, []},
  192. {test4, []},
  193. {test5, [{key5, false}]},
  194. {test6, [{key6, true}]}
  195. ]}]}],
  196. State = rebar_state:new(RebarConfig),
  197. State1 = rebar_state:apply_profiles(State, [profile1, profile2]),
  198. %% Combine lists
  199. ?assertEqual(lists:sort([key1, key2, {key1, 1, 2}, {key3, 5}]),
  200. lists:sort(rebar_state:get(State1, test1))),
  201. %% Use new value for strings
  202. "goodbye" = rebar_state:get(State1, test2),
  203. %% Check that a newvalue of []/"" doesn't override non-string oldvalues
  204. [key3] = rebar_state:get(State1, test3),
  205. [] = rebar_state:get(State1, test4),
  206. [{key5, false}, {key5, true}] = rebar_state:get(State1, test5),
  207. [{key6, true}, {key6, false}] = rebar_state:get(State1, test6).
  208. same_profile_deduplication(_Config) ->
  209. RebarConfig = [{test1, [{key1, 1, 2}, key2]},
  210. {test2, [foo]},
  211. {test3, [key3]},
  212. {profiles,
  213. [{profile1,
  214. [{test1, [{key3, 5}, {key2, "hello"}]},
  215. {test2, [bar]},
  216. {test3, []}
  217. ]}]
  218. }],
  219. State = rebar_state:new(RebarConfig),
  220. State1 = rebar_state:apply_profiles(State, [profile1, profile1, profile1]),
  221. ?assertEqual([default, profile1], rebar_state:current_profiles(State1)),
  222. Test1 = rebar_state:get(State1, test1),
  223. %% Combine lists
  224. ?assertEqual(lists:sort([key2, {key1, 1, 2}, {key3, 5}, {key2, "hello"}]),
  225. lists:sort(Test1)),
  226. %% Key2 from profile1 overrides key2 from default profile
  227. ?assertEqual("hello", proplists:get_value(key2, Test1)),
  228. %% Check that a newvalue of []/"" doesn't override non-string oldvalues
  229. ?assertEqual([key3], rebar_state:get(State1, test3)),
  230. ?assertEqual([bar, foo], rebar_state:get(State1, test2)).
  231. stack_deduplication(_Config) ->
  232. RebarConfig = [
  233. {test_key, default},
  234. {test_list, [ {foo, default} ]},
  235. {profiles, [
  236. {a, [
  237. {test_key, a},
  238. {test_list, [ {foo, a} ]}
  239. ]},
  240. {b, [
  241. {test_key, b},
  242. {test_list, [ {foo, b} ]}
  243. ]},
  244. {c, [
  245. {test_key, c},
  246. {test_list, [ {foo, c} ]}
  247. ]},
  248. {d, [
  249. {test_key, d},
  250. {test_list, [ {foo, d} ]}
  251. ]},
  252. {e, [
  253. {test_key, e},
  254. {test_list, [ {foo, e} ]}
  255. ]}
  256. ]}
  257. ],
  258. State = rebar_state:new(RebarConfig),
  259. State1 = rebar_state:apply_profiles(State, [a, b, c, d, e, a, e, b]),
  260. ?assertEqual(b, rebar_state:get(State1, test_key)),
  261. TestList = rebar_state:get(State1, test_list),
  262. ?assertEqual(
  263. [{foo, b}, {foo, e}, {foo, a}, {foo, d}, {foo, c}, {foo, default} ],
  264. TestList
  265. ),
  266. ?assertEqual(b, proplists:get_value(foo, TestList)).
  267. add_to_profile(_Config) ->
  268. RebarConfig = [{foo, true}, {bar, false}],
  269. State = rebar_state:new(RebarConfig),
  270. State1 = rebar_state:add_to_profile(State, test, [{foo, false}]),
  271. State2 = rebar_state:apply_profiles(State1, test),
  272. Opts = rebar_state:opts(State2),
  273. lists:map(fun(K) -> false = dict:fetch(K, Opts) end, [foo, bar]).
  274. add_to_existing_profile(_Config) ->
  275. RebarConfig = [{foo, true}, {bar, false}, {profiles, [
  276. {test, [{foo, false}]}
  277. ]}],
  278. State = rebar_state:new(RebarConfig),
  279. State1 = rebar_state:add_to_profile(State, test, [{baz, false}]),
  280. State2 = rebar_state:apply_profiles(State1, test),
  281. Opts = rebar_state:opts(State2),
  282. lists:map(fun(K) -> false = dict:fetch(K, Opts) end, [foo, bar, baz]).
  283. profiles_remain_applied_with_config_present(Config) ->
  284. AppDir = ?config(apps, Config),
  285. Name = rebar_test_utils:create_random_name("profiles_remain_applied_"),
  286. Vsn = rebar_test_utils:create_random_vsn(),
  287. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  288. RebarConfig = [{erl_opts, []}, {profiles, [
  289. {not_ok, [{erl_opts, [{d, not_ok}]}]}
  290. ]}],
  291. rebar_test_utils:create_config(AppDir, RebarConfig),
  292. rebar_test_utils:run_and_check(Config, RebarConfig,
  293. ["as", "not_ok", "compile"], {ok, [{app, Name}]}),
  294. Path = filename:join([AppDir, "_build", "not_ok", "lib", Name, "ebin"]),
  295. code:add_patha(Path),
  296. Mod = list_to_atom("not_a_real_src_" ++ Name),
  297. true = lists:member({d, not_ok}, proplists:get_value(options, Mod:module_info(compile), [])).
  298. deduplicated_paths(Config) ->
  299. AppDir = ?config(apps, Config),
  300. Name = rebar_test_utils:create_random_name("deduplicated_paths_"),
  301. Vsn = rebar_test_utils:create_random_vsn(),
  302. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  303. RebarConfig = [],
  304. rebar_test_utils:create_config(AppDir, RebarConfig),
  305. rebar_test_utils:run_and_check(Config, RebarConfig,
  306. ["as", "a,b,c,d,e,a,e,b", "compile"],
  307. {ok, [{app, Name}]}),
  308. Path = filename:join([AppDir, "_build", "c+d+a+e+b", "lib", Name, "ebin"]),
  309. ?assert(filelib:is_dir(Path)).
  310. test_profile_applied_at_completion(Config) ->
  311. AppDir = ?config(apps, Config),
  312. Name = rebar_test_utils:create_random_name("test_profile_at_completion_"),
  313. Vsn = rebar_test_utils:create_random_vsn(),
  314. rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]),
  315. RebarConfig = [{erl_opts, [{d, some_define}]}],
  316. rebar_test_utils:create_config(AppDir, RebarConfig),
  317. {ok, State} = rebar_test_utils:run_and_check(Config,
  318. RebarConfig,
  319. ["eunit"],
  320. return),
  321. [App] = rebar_state:project_apps(State),
  322. ErlOpts = rebar_app_info:get(App, erl_opts),
  323. true = lists:member({d, 'TEST'}, ErlOpts).
  324. test_profile_applied_before_compile(Config) ->
  325. AppDir = ?config(apps, Config),
  326. Name = rebar_test_utils:create_random_name("test_profile_before_compile_"),
  327. Vsn = rebar_test_utils:create_random_vsn(),
  328. rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]),
  329. RebarConfig = [{erl_opts, [{d, some_define}]}],
  330. rebar_test_utils:create_config(AppDir, RebarConfig),
  331. {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["eunit"], {ok, [{app, Name}]}),
  332. code:add_paths(rebar_state:code_paths(State, all_deps)),
  333. S = list_to_atom("not_a_real_src_" ++ Name),
  334. true = lists:member({d, 'TEST'}, proplists:get_value(options, S:module_info(compile), [])).
  335. test_profile_applied_before_eunit(Config) ->
  336. AppDir = ?config(apps, Config),
  337. Name = rebar_test_utils:create_random_name("test_profile_before_eunit_"),
  338. Vsn = rebar_test_utils:create_random_vsn(),
  339. rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]),
  340. RebarConfig = [{erl_opts, [{d, some_define}]}],
  341. rebar_test_utils:create_config(AppDir, RebarConfig),
  342. {ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["eunit"], {ok, [{app, Name}]}),
  343. code:add_paths(rebar_state:code_paths(State, all_deps)),
  344. T = list_to_atom("not_a_real_src_" ++ Name ++ "_tests"),
  345. true = lists:member({d, 'TEST'}, proplists:get_value(options, T:module_info(compile), [])).
  346. test_profile_applied_to_apps(Config) ->
  347. AppDir = ?config(apps, Config),
  348. Name = rebar_test_utils:create_random_name("test_profile_applied_to_apps_"),
  349. Vsn = rebar_test_utils:create_random_vsn(),
  350. rebar_test_utils:create_eunit_app(AppDir, Name, Vsn, [kernel, stdlib]),
  351. RebarConfig = [{erl_opts, [{d, some_define}]}],
  352. rebar_test_utils:create_config(AppDir, RebarConfig),
  353. {ok, State} = rebar_test_utils:run_and_check(Config,
  354. RebarConfig,
  355. ["eunit"],
  356. return),
  357. Apps = rebar_state:project_apps(State),
  358. lists:foreach(fun(App) ->
  359. Opts = rebar_app_info:opts(App),
  360. ErlOpts = dict:fetch(erl_opts, Opts),
  361. true = lists:member({d, 'TEST'}, ErlOpts)
  362. end, Apps).
  363. test_profile_erl_opts_order_1(Config) ->
  364. Opts = get_compiled_profile_erl_opts([default], Config),
  365. Opt = last_erl_opt(Opts, [warn_export_all, nowarn_export_all], undefined),
  366. undefined = Opt.
  367. test_profile_erl_opts_order_2(Config) ->
  368. Opts = get_compiled_profile_erl_opts([strict], Config),
  369. Opt = last_erl_opt(Opts, [warn_export_all, nowarn_export_all], undefined),
  370. warn_export_all = Opt.
  371. test_profile_erl_opts_order_3(Config) ->
  372. Opts = get_compiled_profile_erl_opts([loose], Config),
  373. Opt = last_erl_opt(Opts, [warn_export_all, nowarn_export_all], undefined),
  374. nowarn_export_all = Opt.
  375. test_profile_erl_opts_order_4(Config) ->
  376. Opts = get_compiled_profile_erl_opts([strict, loose], Config),
  377. Opt = last_erl_opt(Opts, [warn_export_all, nowarn_export_all], undefined),
  378. nowarn_export_all = Opt.
  379. test_profile_erl_opts_order_5(Config) ->
  380. Opts = get_compiled_profile_erl_opts([loose, strict], Config),
  381. Opt = last_erl_opt(Opts, [warn_export_all, nowarn_export_all], undefined),
  382. warn_export_all = Opt.
  383. first_files_exception(_Config) ->
  384. RebarConfig = [{erl_first_files, ["c","a","b"]},
  385. {mib_first_files, ["c","a","b"]},
  386. {other, ["c","a","b"]},
  387. {profiles,
  388. [{profile2, [{erl_first_files, ["a","e"]},
  389. {mib_first_files, ["a","e"]},
  390. {other, ["a","e"]}
  391. ]}]}],
  392. State = rebar_state:new(RebarConfig),
  393. State1 = rebar_state:apply_profiles(State, [profile2]),
  394. %% Combine lists
  395. ?assertEqual(["a","b","c","e"], rebar_state:get(State1, other)),
  396. %% there is no specific reason not to dedupe "a" here aside from "this is how it is"
  397. ?assertEqual(["c","a","b","a","e"], rebar_state:get(State1, erl_first_files)),
  398. ?assertEqual(["c","a","b","a","e"], rebar_state:get(State1, mib_first_files)),
  399. ok.
  400. get_compiled_profile_erl_opts(Profiles, Config) ->
  401. AppDir = ?config(apps, Config),
  402. PStrs = [atom_to_list(P) || P <- Profiles],
  403. Name = rebar_test_utils:create_random_name(
  404. lists:flatten(["erl_opts_order_" | [[S, $_] || S <- PStrs]])),
  405. Vsn = rebar_test_utils:create_random_vsn(),
  406. rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
  407. RebarConfig = [
  408. {erl_opts, [warnings_as_errors, {d, profile_default}]},
  409. {profiles, [
  410. {strict, [{erl_opts, [warn_export_all, {d, profile_strict}]}]},
  411. {loose, [{erl_opts, [nowarn_export_all, {d, profile_loose}]}]} ]}],
  412. rebar_test_utils:create_config(AppDir, RebarConfig),
  413. Command = case Profiles of
  414. [] ->
  415. ["compile"];
  416. [default] ->
  417. ["compile"];
  418. _ ->
  419. ["as", string:join(PStrs, ","), "compile"]
  420. end,
  421. {ok, State} = rebar_test_utils:run_and_check(
  422. Config, RebarConfig, Command, {ok, [{app, Name}]}),
  423. code:add_paths(rebar_state:code_paths(State, all_deps)),
  424. Mod = list_to_atom(Name),
  425. proplists:get_value(options, Mod:module_info(compile), []).
  426. % macro definitions get special handling
  427. last_erl_opt([{d, Macro} = Opt | Opts], Targets, Last) ->
  428. case lists:any(erl_opt_macro_match_fun(Macro), Targets) of
  429. true ->
  430. last_erl_opt(Opts, Targets, Opt);
  431. _ ->
  432. last_erl_opt(Opts, Targets, Last)
  433. end;
  434. last_erl_opt([{d, Macro, _} = Opt | Opts], Targets, Last) ->
  435. case lists:any(erl_opt_macro_match_fun(Macro), Targets) of
  436. true ->
  437. last_erl_opt(Opts, Targets, Opt);
  438. _ ->
  439. last_erl_opt(Opts, Targets, Last)
  440. end;
  441. last_erl_opt([Opt | Opts], Targets, Last) ->
  442. case lists:member(Opt, Targets) of
  443. true ->
  444. last_erl_opt(Opts, Targets, Opt);
  445. _ ->
  446. last_erl_opt(Opts, Targets, Last)
  447. end;
  448. last_erl_opt([], _, Last) ->
  449. Last.
  450. erl_opt_macro_match_fun(Macro) ->
  451. fun({d, M}) ->
  452. M == Macro;
  453. ({d, M, _}) ->
  454. M == Macro;
  455. (_) ->
  456. false
  457. end.