You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

121 lines
4.5 KiB

  1. -module(rebar_prv_compile).
  2. -behaviour(provider).
  3. -export([init/1,
  4. do/1,
  5. format_error/1]).
  6. -export([compile/2]).
  7. -include("rebar.hrl").
  8. -define(PROVIDER, compile).
  9. -define(DEPS, [lock]).
  10. %% ===================================================================
  11. %% Public API
  12. %% ===================================================================
  13. -spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
  14. init(State) ->
  15. State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
  16. {module, ?MODULE},
  17. {bare, false},
  18. {deps, ?DEPS},
  19. {example, "rebar3 compile"},
  20. {short_desc, "Compile apps .app.src and .erl files."},
  21. {desc, ""},
  22. {opts, []}])),
  23. {ok, State1}.
  24. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
  25. do(State) ->
  26. ProjectApps = rebar_state:project_apps(State),
  27. Deps = rebar_state:deps_to_build(State),
  28. Cwd = rebar_dir:get_cwd(),
  29. rebar_hooks:run_compile_hooks(Cwd, pre_hooks, compile, State),
  30. %% Need to allow global config vars used on deps
  31. %% Right now no way to differeniate and just give deps a new state
  32. EmptyState = rebar_state:new(),
  33. build_apps(EmptyState, Deps),
  34. %% Use the project State for building project apps
  35. %% Set hooks to empty so top-level hooks aren't run for each project app
  36. State2 = rebar_state:set(rebar_state:set(State, post_hooks, []), pre_hooks, []),
  37. ProjectApps1 = build_apps(State2, ProjectApps),
  38. rebar_hooks:run_compile_hooks(Cwd, post_hooks, compile, State),
  39. {ok, rebar_state:project_apps(State, ProjectApps1)}.
  40. -spec format_error(any()) -> iolist().
  41. format_error(Reason) ->
  42. io_lib:format("~p", [Reason]).
  43. build_apps(State, Apps) ->
  44. [build_app(State, AppInfo) || AppInfo <- Apps].
  45. build_app(State, AppInfo) ->
  46. AppDir = rebar_app_info:dir(AppInfo),
  47. OutDir = rebar_app_info:out_dir(AppInfo),
  48. copy_app_dirs(State, AppDir, OutDir),
  49. S = case rebar_app_info:state(AppInfo) of
  50. undefined ->
  51. C = rebar_config:consult(AppDir),
  52. rebar_state:new(State, C, AppDir);
  53. AppState ->
  54. AppState
  55. end,
  56. %% Legacy hook support
  57. rebar_hooks:run_compile_hooks(AppDir, pre_hooks, compile, S),
  58. AppInfo1 = compile(S, AppInfo),
  59. rebar_hooks:run_compile_hooks(AppDir, post_hooks, compile, S),
  60. true = code:add_patha(rebar_app_info:ebin_dir(AppInfo1)),
  61. AppInfo1.
  62. compile(State, AppInfo) ->
  63. ?INFO("Compiling ~s", [rebar_app_info:name(AppInfo)]),
  64. rebar_erlc_compiler:compile(State, ec_cnv:to_list(rebar_app_info:out_dir(AppInfo))),
  65. case rebar_otp_app:compile(State, AppInfo) of
  66. {ok, AppInfo1} ->
  67. AppInfo1;
  68. Error ->
  69. throw(Error)
  70. end.
  71. %% ===================================================================
  72. %% Internal functions
  73. %% ===================================================================
  74. copy_app_dirs(State, OldAppDir, AppDir) ->
  75. case ec_cnv:to_binary(filename:absname(OldAppDir)) =/=
  76. ec_cnv:to_binary(filename:absname(AppDir)) of
  77. true ->
  78. EbinDir = filename:join([OldAppDir, "ebin"]),
  79. %% copy all files from ebin if it exists
  80. case filelib:is_dir(EbinDir) of
  81. true ->
  82. OutEbin = filename:join(AppDir, "ebin"),
  83. filelib:ensure_dir(filename:join(OutEbin, "dummy.beam")),
  84. rebar_file_utils:cp_r(filelib:wildcard(filename:join(EbinDir, "*")), OutEbin);
  85. false ->
  86. ok
  87. end,
  88. filelib:ensure_dir(filename:join(AppDir, "dummy")),
  89. %% link to src_dirs to be adjacent to ebin is needed for R15 use of cover/xref
  90. ErlOpts = rebar_utils:erl_opts(State),
  91. SrcDirs = proplists:get_value(src_dirs, ErlOpts, ["src"]),
  92. [symlink_or_copy(OldAppDir, AppDir, Dir) || Dir <- ["priv", "include", "test"] ++ SrcDirs];
  93. false ->
  94. ok
  95. end.
  96. symlink_or_copy(OldAppDir, AppDir, Dir) ->
  97. Source = filename:join(OldAppDir, Dir),
  98. Target = filename:join(AppDir, Dir),
  99. rebar_file_utils:symlink_or_copy(Source, Target).