Packages
rebar3_gpb_plugin
1.6.1
3.0.1
3.0.0
2.23.8
2.23.7
2.23.6
2.23.5
2.23.4
2.23.3
2.23.2
2.23.1
2.23.0
2.22.7
2.22.6
2.22.5
2.22.4
2.22.3
2.22.2
2.22.1
2.22.0
2.21.0
2.20.3
2.20.2
2.20.1
2.20.0
2.19.1
2.19.0
2.18.1
2.18.0
2.17.2
2.17.1
2.17.0
2.16.1
2.16.0
2.15.0
2.14.0
2.13.2
2.13.1
2.13.0
2.12.5
2.12.4
2.12.3
2.12.2
2.12.1
2.12.0
2.11.3
2.11.2
2.11.1
2.11.0
2.10.0
2.9.0
2.8.2
2.8.0
2.7.0
2.6.1
2.6.0
2.5.1
2.5.0
2.4.3
2.4.2
2.4.1
2.4.0
2.3.4
2.3.3
2.3.2
2.3.1
2.3.0
2.2.10
2.2.9
2.2.8
2.2.7
2.2.6
2.2.5
2.2.4
2.2.3
2.2.2
2.2.1
2.2.0
2.1.1
2.1.0
2.0.1
2.0.0
1.12.1
1.12.0
1.11.8
1.11.7
1.11.6
1.11.5
1.11.4
1.11.3
1.11.2
1.11.1
1.11.0
1.10.4
1.10.3
1.10.2
1.10.1
1.10.0
1.9.2
1.9.1
1.9.0
1.8.2
1.8.1
1.8.0
1.7.3
1.7.2
1.7.1
1.7.0
1.6.1
1.6.0
1.5.2
1.5.1
1.4.0
1.3.3
1.3.2
1.3.1
1.3.0
1.2.1
1.2.0
1.0.1
A rebar3 gpb plugin for compiling .proto files
Current section
Files
Jump to
Current section
Files
src/rebar3_gpb_compiler.erl
-module(rebar3_gpb_compiler).
-export([compile/1,
clean/1]).
-define(DEFAULT_PROTO_DIR, "proto").
-define(DEFAULT_OUT_ERL_DIR, "src").
-define(DEFAULT_OUT_HRL_DIR, "include").
-define(DEFAULT_MODULE_SUFFIX, "").
%% ===================================================================
%% Public API
%% ===================================================================
-spec compile(rebar_app_info:t()) -> ok.
compile(AppInfo) ->
AppDir = rebar_app_info:dir(AppInfo),
AppOutDir = rebar_app_info:out_dir(AppInfo),
Opts = rebar_app_info:opts(AppInfo),
{ok, GpbOpts0} = dict:find(gpb_opts, Opts),
%% check if non-recursive
Recursive = proplists:get_value(recursive, GpbOpts0, true),
ModuleNameSuffix = proplists:get_value(module_name_suffix, GpbOpts0,
?DEFAULT_MODULE_SUFFIX),
SourceDirs = proplists:get_all_values(i, GpbOpts0),
TargetErlDir = filename:join([AppOutDir,
proplists:get_value(o_erl, GpbOpts0,
?DEFAULT_OUT_ERL_DIR)]),
TargetHrlDir = filename:join([AppOutDir,
proplists:get_value(o_hrl, GpbOpts0,
?DEFAULT_OUT_HRL_DIR)]),
rebar_api:debug("making sure that target erl dir ~p exists", [TargetErlDir]),
ok = ensure_dir(TargetErlDir),
rebar_api:debug("making sure that target hrl dir ~p exists", [TargetHrlDir]),
ok = ensure_dir(TargetHrlDir),
rebar_api:debug("reading proto files from ~p, generating \"~s.erl\" to ~p "
"and \"~s.hrl\" to ~p",
[SourceDirs, ModuleNameSuffix, TargetErlDir, ModuleNameSuffix, TargetHrlDir]),
%% set the full path for the output directories
%% remove the plugin specific options since gpb will not understand them
GpbOpts = remove_plugin_opts(
default_include_opts(AppDir,
target_erl_opt(TargetErlDir,
target_hrl_opt(TargetHrlDir, GpbOpts0)))),
lists:foreach(fun(SourceDir) ->
ok = rebar_base_compiler:run(Opts, [],
filename:join(AppDir, SourceDir), ".proto",
TargetErlDir, ModuleNameSuffix ++ ".erl",
fun(Source, Target, Config) ->
compile(Source, Target, GpbOpts, Config)
end,
[check_last_mod, {recursive, Recursive}])
end, SourceDirs),
ok.
-spec clean(rebar_app_info:t()) -> ok.
clean(AppInfo) ->
AppDir = rebar_app_info:dir(AppInfo),
AppOutDir = rebar_app_info:out_dir(AppInfo),
Opts = rebar_app_info:opts(AppInfo),
{ok, GpbOpts} = dict:find(gpb_opts, Opts),
ModuleNameSuffix = proplists:get_value(module_name_suffix, GpbOpts,
?DEFAULT_MODULE_SUFFIX),
TargetErlDir = filename:join([AppOutDir,
proplists:get_value(o_erl, GpbOpts,
?DEFAULT_OUT_ERL_DIR)]),
TargetHrlDir = filename:join([AppOutDir,
proplists:get_value(o_hrl, GpbOpts,
?DEFAULT_OUT_HRL_DIR)]),
ProtoFiles = find_proto_files(AppDir, GpbOpts),
GeneratedRootFiles = [filename:rootname(filename:basename(ProtoFile)) ++
ModuleNameSuffix || ProtoFile <- ProtoFiles],
GeneratedErlFiles = [filename:join([TargetErlDir, F ++ ".erl"]) ||
F <- GeneratedRootFiles],
GeneratedHrlFiles = [filename:join([TargetHrlDir, F ++ ".hrl"]) ||
F <- GeneratedRootFiles],
rebar_api:debug("deleting [~p, ~p]",
[GeneratedErlFiles, GeneratedHrlFiles]),
rebar_file_utils:delete_each(GeneratedErlFiles ++ GeneratedHrlFiles).
%% ===================================================================
%% Private API
%% ===================================================================
-spec compile(string(), string(), proplists:proplist(), term()) -> ok.
compile(Source, _Target, GpbOpts, _Config) ->
rebar_api:debug("compiling ~p", [Source]),
rebar_api:debug("opts: ~p", [GpbOpts]),
case gpb_compile:file(filename:basename(Source), GpbOpts) of
ok ->
ok;
{error, Reason} ->
ReasonStr = gpb_compile:format_error(Reason),
rebar_utils:abort("failed to compile ~s: ~s~n", [Source, ReasonStr])
end.
-spec ensure_dir(filelib:dirname()) -> 'ok' | {error, Reason::file:posix()}.
ensure_dir(OutDir) ->
%% Make sure that ebin/ exists and is on the path
case filelib:ensure_dir(filename:join(OutDir, "dummy.beam")) of
ok -> ok;
{error, eexist} ->
rebar_utils:abort("unable to ensure dir ~p, is it maybe a broken symlink?",
[OutDir]);
{error, Reason} -> {error, Reason}
end.
-spec default_include_opts(string(), proplists:proplist()) -> proplists:proplist().
default_include_opts(AppDir, Opts) ->
Opts ++
[{i, filename:join(AppDir, Path)} || {i, Path} <- Opts] ++
[{i, filename:join(AppDir, Path)} || {ipath, Path} <- Opts].
-spec target_erl_opt(string(), proplists:proplist()) -> proplists:proplist().
target_erl_opt(Dir, Opts) ->
lists:keystore(o_erl, 1, Opts, {o_erl, Dir}).
-spec target_hrl_opt(string(), proplists:proplist()) -> proplists:proplist().
target_hrl_opt(Dir, Opts) ->
lists:keystore(o_hrl, 1, Opts, {o_hrl, Dir}).
-spec remove_plugin_opts(proplists:proplists()) -> proplists:proplist().
remove_plugin_opts(Opts) ->
remove_plugin_opts(Opts, [recursive, ipath]).
-spec remove_plugin_opts(proplists:proplist(),
[ipath | recursive]) -> proplists:proplist().
remove_plugin_opts(Opts, []) -> Opts;
remove_plugin_opts(Opts0, [OptToRemove | Rest]) ->
Opts = lists:keydelete(OptToRemove, 1, Opts0),
remove_plugin_opts(Opts, Rest).
find_proto_files(AppDir, GpbOpts) ->
lists:foldl(fun(SourceDir, Acc) ->
Acc ++ rebar_utils:find_files(filename:join(AppDir, SourceDir),
".*\.proto\$")
end, [], proplists:get_all_values(i, GpbOpts)).