From 26707b8babedfec18d984c9394a012f96b87626a Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Sun, 30 Sep 2018 13:42:40 -0600 Subject: [PATCH] allow plugins to add project builders and compilers --- src/rebar_app_info.erl | 7 +++++-- src/rebar_otp_app.erl | 3 ++- src/rebar_packages.erl | 2 +- src/rebar_prv_compile.erl | 22 ++++++++++------------ src/rebar_state.erl | 24 ++++++++++++++++++++++++ 5 files changed, 42 insertions(+), 16 deletions(-) diff --git a/src/rebar_app_info.erl b/src/rebar_app_info.erl index 62f9143f..b1c62431 100644 --- a/src/rebar_app_info.erl +++ b/src/rebar_app_info.erl @@ -71,7 +71,10 @@ -include("rebar.hrl"). -include_lib("providers/include/providers.hrl"). --export_type([t/0]). +-export_type([t/0, + project_type/0]). + +-type project_type() :: rebar3 | mix | undefined. -record(app_info_t, {name :: binary() | undefined, app_file_src :: file:filename_all() | undefined, @@ -93,7 +96,7 @@ is_lock=false :: boolean(), is_checkout=false :: boolean(), valid :: boolean() | undefined, - project_type :: rebar3 | mix | undefined, + project_type :: project_type(), is_available=false :: boolean()}). %%============================================================================ diff --git a/src/rebar_otp_app.erl b/src/rebar_otp_app.erl index 33e35adb..e14975f2 100644 --- a/src/rebar_otp_app.erl +++ b/src/rebar_otp_app.erl @@ -60,7 +60,8 @@ compile(State, App) -> format_error({missing_app_file, Filename}) -> io_lib:format("App file is missing: ~ts", [Filename]); format_error({file_read, AppName, File, Reason}) -> - io_lib:format("Failed to read required ~ts file for processing the application '~ts': ~ts", [File, AppName, file:format_error(Reason)]); + io_lib:format("Failed to read required ~ts file for processing the application '~ts': ~ts", + [File, AppName, file:format_error(Reason)]); format_error({invalid_name, File, AppName}) -> io_lib:format("Invalid ~ts: name of application (~p) must match filename.", [File, AppName]). diff --git a/src/rebar_packages.erl b/src/rebar_packages.erl index 7533a445..7676213e 100644 --- a/src/rebar_packages.erl +++ b/src/rebar_packages.erl @@ -60,7 +60,7 @@ get_all_names(State) -> get_package_versions(Dep, Repo, Table, State) -> ?MODULE:verify_table(State), AllowPreRelease = rebar_state:get(State, deps_allow_prerelease, false), - ets:select(Table, [{#package{key={Dep,{'$1', '$2'}, Repo}, + ets:select(Table, [{#package{key={Dep, {'$1', '$2'}, Repo}, _='_'}, [{'==', '$2', {{[],[]}}} || not AllowPreRelease], [{{'$1', '$2'}}]}]). diff --git a/src/rebar_prv_compile.erl b/src/rebar_prv_compile.erl index 4c1a4eb2..54bdee20 100644 --- a/src/rebar_prv_compile.erl +++ b/src/rebar_prv_compile.erl @@ -198,22 +198,20 @@ compile(State, Providers, AppInfo) -> build_app(AppInfo, State) -> case rebar_app_info:project_type(AppInfo) of - T when T =:= rebar3 ; T =:= undefined -> + Type when Type =:= rebar3 ; Type =:= undefined -> Compilers = rebar_state:compilers(State), rebar_compiler:compile_all(Compilers, AppInfo); - T -> - ProjectBuilders = rebar_state:get(State, project_builders, []), - case lists:keyfind(T, 1, ProjectBuilders) of + Type -> + ProjectBuilders = rebar_state:project_builders(State), + case lists:keyfind(Type, 1, ProjectBuilders) of {_, Module} -> - _ = code:ensure_loaded(Module), - case erlang:function_exported(Module, build, 1) of - true -> - Module:build(AppInfo); - false -> - throw(?PRV_ERROR({bad_project_builder, rebar_app_info:name(AppInfo), T, Module})) - end; + %% load plugins since thats where project builders would be + PluginDepsPaths = rebar_state:code_paths(State, all_plugin_deps), + code:add_pathsa(PluginDepsPaths), + Module:build(AppInfo), + rebar_utils:remove_from_code_path(PluginDepsPaths); _ -> - throw(?PRV_ERROR({unknown_project_type, rebar_app_info:name(AppInfo), T})) + throw(?PRV_ERROR({unknown_project_type, rebar_app_info:name(AppInfo), Type})) end end. update_code_paths(State, ProjectApps, DepsPaths) -> diff --git a/src/rebar_state.erl b/src/rebar_state.erl index 1655a959..c8a94006 100644 --- a/src/rebar_state.erl +++ b/src/rebar_state.erl @@ -39,6 +39,9 @@ to_list/1, compilers/1, compilers/2, + prepend_compilers/2, append_compilers/2, + + project_builders/1, add_project_builder/3, create_resources/2, resources/1, resources/2, add_resource/2, @@ -69,6 +72,7 @@ all_deps = [] :: [rebar_app_info:t()], compilers = [] :: [{compiler_type(), extension(), extension(), compile_fun()}], + project_builders = [] :: [{rebar_app_info:project_type(), module()}], resources = [], providers = [], allow_provider_overrides = false :: boolean()}). @@ -402,9 +406,29 @@ warn_old_resource(ResourceModule) -> compilers(#state_t{compilers=Compilers}) -> Compilers. +prepend_compilers(State=#state_t{compilers=Compilers}, NewCompilers) -> + State#state_t{compilers=NewCompilers++Compilers}. + +append_compilers(State=#state_t{compilers=Compilers}, NewCompilers) -> + State#state_t{compilers=Compilers++NewCompilers}. + compilers(State, Compilers) -> State#state_t{compilers=Compilers}. +project_builders(#state_t{project_builders=ProjectBuilders}) -> + ProjectBuilders. + +add_project_builder(State=#state_t{project_builders=ProjectBuilders}, Type, Module) -> + _ = code:ensure_loaded(Module), + case erlang:function_exported(Module, build, 1) of + true -> + State#state_t{project_builders=[{Type, Module} | ProjectBuilders]}; + false -> + ?WARN("Unable to add project builder for type ~s, required function ~s:build/1 not found.", + [Type, Module]), + State + end. + create_resources(Resources, State) -> lists:foldl(fun(R, StateAcc) -> add_resource(StateAcc, R)