Browse Source

Fold plugin build into main dependency workflow

This was a long-standing pending issue with plugins having a weird code
path handling. The work done in the previous commit to do version
detection for the compiler in dependencies along with prior PRs that
added a deps-only mode to the `compile` provider means we can now
re-introduce plugins into the 3.14 compilation mechanism.

This makes compiler version detection a compiler task concern and
removes annoying manual checks, but also solves an unreported issue
(brought up on slack only) where a plugin would no longer have its priv/
or include/ dir included when used as a checkout dependency. Essentially
the latter bug was caused by being out-of-sync with application
preparation for a build task, but by re-folding it into the main flow,
we know we have the proper support as used for deps.
pull/2317/head
Fred Hebert 4 years ago
parent
commit
54396dbfc0
2 changed files with 13 additions and 45 deletions
  1. +3
    -2
      bootstrap
  2. +10
    -43
      src/rebar_plugins.erl

+ 3
- 2
bootstrap View File

@ -20,10 +20,11 @@ main(_) ->
%% cause weird failures when compilers get modified between releases.
rm_rf("_build/prod"),
%% The same pattern happens with default/ as well, particularly when
%% developing new things.
%% Keep other deps in default/lib for build environments like Nix
%% developing new things.
%% Keep other deps in <profile>/lib for build environments like Nix
%% where internet access is disabled that deps are not downloadable.
rm_rf("_build/default/lib/rebar"),
rm_rf("_build/test/lib/rebar"),
%% We fetch a few deps from hex for boostraping,
%% so we must compile r3_safe_erl_term.xrl which

+ 10
- 43
src/rebar_plugins.erl View File

@ -117,12 +117,11 @@ handle_plugin(Profile, Plugin, State, Upgrade) ->
PreBuiltApps = [A || A <- Apps,
Ebin <- [rebar_app_info:ebin_dir(A)],
not lists:member(Ebin, ToBuildPaths)],
{PreUnsafe, PreSafe} = lists:partition(fun needs_rebuild/1, PreBuiltApps),
PreBuiltPaths = [rebar_app_info:ebin_dir(A) || A <- PreSafe],
PreBuiltPaths = [rebar_app_info:ebin_dir(A) || A <- PreBuiltApps],
code:add_pathsa(PreBuiltPaths),
%% Build plugin and its deps
[build_plugin(AppInfo, Apps, State2) || AppInfo <- PreUnsafe++ToBuild],
build_plugins(ToBuild -- PreBuiltApps, Apps, State2),
%% Add newly built deps and plugin to code path
State3 = rebar_state:update_all_plugin_deps(State2, Apps),
@ -140,11 +139,14 @@ handle_plugin(Profile, Plugin, State, Upgrade) ->
{[], State}
end.
build_plugin(AppInfo, Apps, State) ->
Providers = rebar_state:providers(State),
S = rebar_state:all_deps(State, Apps),
S1 = rebar_state:set(S, deps_dir, ?DEFAULT_PLUGINS_DIR),
rebar_prv_compile:compile(S1, Providers, AppInfo).
build_plugins(MustBuildApps, AllApps, State) ->
State1 = rebar_state:deps_to_build(State, MustBuildApps),
State2 = rebar_state:all_deps(State1, AllApps),
State3 = rebar_state:set(State2, deps_dir, ?DEFAULT_PLUGINS_DIR),
{Args, Extra} = rebar_state:command_parsed_args(State),
State4 = rebar_state:command_parsed_args(State3, {[{deps_only, true}|Args], Extra}),
rebar_prv_compile:do(State4),
ok.
plugin_providers({Plugin, _, _, _}) when is_atom(Plugin) ->
validate_plugin(Plugin);
@ -171,38 +173,3 @@ validate_plugin(Plugin) ->
end
end.
%% @private do a quick validation of whether a plugin is expected to need
%% to be rebuilt; usually this is handled by the compiler, but since this
%% module does quick filtering by detection, we need to discriminate against
%% cases like the compiler version having changed that would otherwise
%% trigger a rebuild.
needs_rebuild(AppInfo) ->
Ebin = rebar_app_info:ebin_dir(AppInfo),
application:load(compiler),
{ok, CurrentCompileVsn} = application:get_key(compiler, vsn),
case find_some_beam(Ebin) of
{ok, Beam} ->
case beam_lib:chunks(Beam, [compile_info]) of
{ok, {_mod, Chunks}} ->
CompileInfo = proplists:get_value(compile_info, Chunks, []),
CompileVsn = proplists:get_value(version, CompileInfo, "unknown"),
CurrentCompileVsn =/= CompileVsn;
_ ->
%% could be built without debug_info
false
end;
_ ->
%% well we would expect a plugin to have a beam file
true
end.
find_some_beam(Path) ->
case file:list_dir(Path) of
{error, Reason} ->
{error, Reason};
{ok, Files} ->
case lists:dropwhile(fun(P) -> filename:extension(P) =/= ".beam" end, Files) of
[Beam|_] -> {ok, filename:join(Path, Beam)};
_ -> {error, no_beam}
end
end.

Loading…
Cancel
Save