Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

153 рядки
5.9 KiB

10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
  1. -module(rebar_prv_compile).
  2. -behaviour(provider).
  3. -export([init/1,
  4. do/1,
  5. format_error/1]).
  6. -export([compile/3]).
  7. -include_lib("providers/include/providers.hrl").
  8. -include("rebar.hrl").
  9. -define(PROVIDER, compile).
  10. -define(DEPS, [lock]).
  11. %% ===================================================================
  12. %% Public API
  13. %% ===================================================================
  14. -spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
  15. init(State) ->
  16. State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
  17. {module, ?MODULE},
  18. {bare, true},
  19. {deps, ?DEPS},
  20. {example, "rebar3 compile"},
  21. {short_desc, "Compile apps .app.src and .erl files."},
  22. {desc, "Compile apps .app.src and .erl files."},
  23. {opts, []}])),
  24. {ok, State1}.
  25. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
  26. do(State) ->
  27. DepsPaths = rebar_state:code_paths(State, all_deps),
  28. PluginDepsPaths = rebar_state:code_paths(State, all_plugin_deps),
  29. rebar_utils:remove_from_code_path(PluginDepsPaths),
  30. code:add_pathsa(DepsPaths),
  31. ProjectApps = rebar_state:project_apps(State),
  32. Providers = rebar_state:providers(State),
  33. Deps = rebar_state:deps_to_build(State),
  34. Cwd = rebar_state:dir(State),
  35. %% Need to allow global config vars used on deps.
  36. %% Right now no way to differeniate and just give deps a new state.
  37. %% But need an account of "all deps" for some hooks to use.
  38. EmptyState = rebar_state:new(),
  39. build_apps(rebar_state:all_deps(EmptyState,
  40. rebar_state:all_deps(State)), Providers, Deps),
  41. {ok, ProjectApps1} = rebar_digraph:compile_order(ProjectApps),
  42. %% Run top level hooks *before* project apps compiled but *after* deps are
  43. rebar_hooks:run_all_hooks(Cwd, pre, ?PROVIDER, Providers, State),
  44. ProjectApps2 = build_apps(State, Providers, ProjectApps1),
  45. State2 = rebar_state:project_apps(State, ProjectApps2),
  46. ProjAppsPaths = [filename:join(rebar_app_info:out_dir(X), "ebin") || X <- ProjectApps2],
  47. State3 = rebar_state:code_paths(State2, all_deps, DepsPaths ++ ProjAppsPaths),
  48. rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, State2),
  49. has_all_artifacts(State3),
  50. rebar_utils:cleanup_code_path(rebar_state:code_paths(State3, default)),
  51. {ok, State3}.
  52. -spec format_error(any()) -> iolist().
  53. format_error({missing_artifact, File}) ->
  54. io_lib:format("Missing artifact ~s", [File]);
  55. format_error(Reason) ->
  56. io_lib:format("~p", [Reason]).
  57. build_apps(State, Providers, Apps) ->
  58. [build_app(State, Providers, AppInfo) || AppInfo <- Apps].
  59. build_app(State, Providers, AppInfo) ->
  60. AppDir = rebar_app_info:dir(AppInfo),
  61. OutDir = rebar_app_info:out_dir(AppInfo),
  62. copy_app_dirs(State, AppDir, OutDir),
  63. S = rebar_app_info:state_or_new(State, AppInfo),
  64. S1 = rebar_state:all_deps(S, rebar_state:all_deps(State)),
  65. compile(S1, Providers, AppInfo).
  66. compile(State, Providers, AppInfo) ->
  67. ?INFO("Compiling ~s", [rebar_app_info:name(AppInfo)]),
  68. AppDir = rebar_app_info:dir(AppInfo),
  69. rebar_hooks:run_all_hooks(AppDir, pre, ?PROVIDER, Providers, State),
  70. rebar_erlc_compiler:compile(State, ec_cnv:to_list(rebar_app_info:out_dir(AppInfo))),
  71. case rebar_otp_app:compile(State, AppInfo) of
  72. {ok, AppInfo1} ->
  73. rebar_hooks:run_all_hooks(AppDir, post, ?PROVIDER, Providers, State),
  74. has_all_artifacts(State),
  75. AppInfo1;
  76. Error ->
  77. throw(Error)
  78. end.
  79. %% ===================================================================
  80. %% Internal functions
  81. %% ===================================================================
  82. has_all_artifacts(State) ->
  83. case rebar_state:has_all_artifacts(State) of
  84. {false, File} ->
  85. throw(?PRV_ERROR({missing_artifact, File}));
  86. true ->
  87. true
  88. end.
  89. copy_app_dirs(State, OldAppDir, AppDir) ->
  90. case ec_cnv:to_binary(filename:absname(OldAppDir)) =/=
  91. ec_cnv:to_binary(filename:absname(AppDir)) of
  92. true ->
  93. EbinDir = filename:join([OldAppDir, "ebin"]),
  94. %% copy all files from ebin if it exists
  95. case filelib:is_dir(EbinDir) of
  96. true ->
  97. OutEbin = filename:join(AppDir, "ebin"),
  98. filelib:ensure_dir(filename:join(OutEbin, "dummy.beam")),
  99. rebar_file_utils:cp_r(filelib:wildcard(filename:join(EbinDir, "*")), OutEbin);
  100. false ->
  101. ok
  102. end,
  103. filelib:ensure_dir(filename:join(AppDir, "dummy")),
  104. %% link or copy mibs if it exists
  105. case filelib:is_dir(filename:join(OldAppDir, "mibs")) of
  106. true ->
  107. %% If mibs exist it means we must ensure priv exists.
  108. %% mibs files are compiled to priv/mibs/
  109. filelib:ensure_dir(filename:join([OldAppDir, "priv", "dummy"])),
  110. symlink_or_copy(OldAppDir, AppDir, "mibs");
  111. false ->
  112. ok
  113. end,
  114. %% link to src_dirs to be adjacent to ebin is needed for R15 use of cover/xref
  115. SrcDirs = rebar_dir:all_src_dirs(State, ["src"], ["test"]),
  116. [symlink_or_copy(OldAppDir, AppDir, Dir) || Dir <- ["priv", "include"] ++ SrcDirs];
  117. false ->
  118. ok
  119. end.
  120. symlink_or_copy(OldAppDir, AppDir, Dir) ->
  121. Source = filename:join(OldAppDir, Dir),
  122. Target = filename:join(AppDir, Dir),
  123. rebar_file_utils:symlink_or_copy(Source, Target).