summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ebin/rebar.app2
-rw-r--r--rebar.config1
-rw-r--r--rebar.config.sample4
-rw-r--r--src/rebar_proto_gpb_compiler.erl119
4 files changed, 126 insertions, 0 deletions
diff --git a/ebin/rebar.app b/ebin/rebar.app
index f92f574..6e3609b 100644
--- a/ebin/rebar.app
+++ b/ebin/rebar.app
@@ -30,6 +30,7 @@
rebar_port_compiler,
rebar_proto_compiler,
rebar_protobuffs_compiler,
+ rebar_proto_gpb_compiler,
rebar_qc,
rebar_rel_utils,
rebar_reltool,
@@ -70,6 +71,7 @@
rebar_abnfc_compiler,
rebar_proto_compiler,
rebar_protobuffs_compiler,
+ rebar_proto_gpb_compiler,
rebar_neotoma_compiler,
rebar_asn1_compiler,
rebar_dia_compiler,
diff --git a/rebar.config b/rebar.config
index 1c62a55..9150e98 100644
--- a/rebar.config
+++ b/rebar.config
@@ -24,6 +24,7 @@
- (\"lfe_comp\":\"file\"/\"2\")
- (\"neotoma\":\"file\"/\"2\")
- (\"protobuffs_compile\":\"scan_file\"/\"2\")
+ - (\"gpb_compile\":\"file\"/\"2\")
- (\"diameter_codegen\":\"from_dict\"/\"4\")
- (\"diameter_dict_util\":\"format_error\"/\"1\")
- (\"diameter_dict_util\":\"parse\"/\"2\"))",
diff --git a/rebar.config.sample b/rebar.config.sample
index d2a7869..107a02f 100644
--- a/rebar.config.sample
+++ b/rebar.config.sample
@@ -93,7 +93,11 @@
{proto_compiler, protobuffs}.
%% Available compilers for protocol buffer files (*.proto):
%% protobuffs (default)
+%% gpb
+%% Options for the gpb protocol buffer compiler,
+%% if selected by the proto_compiler option
+{gpb_opts, []}.
%% == EUnit ==
diff --git a/src/rebar_proto_gpb_compiler.erl b/src/rebar_proto_gpb_compiler.erl
new file mode 100644
index 0000000..e6798ab
--- /dev/null
+++ b/src/rebar_proto_gpb_compiler.erl
@@ -0,0 +1,119 @@
+%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
+%% ex: ts=4 sw=4 et
+%% -------------------------------------------------------------------
+%%
+%% rebar: Erlang Build Tools
+%%
+%% Copyright (c) 2014 Tomas Abrahamsson (tomas.abrahamsson@gmail.com)
+%%
+%% Permission is hereby granted, free of charge, to any person obtaining a copy
+%% of this software and associated documentation files (the "Software"), to deal
+%% in the Software without restriction, including without limitation the rights
+%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+%% copies of the Software, and to permit persons to whom the Software is
+%% furnished to do so, subject to the following conditions:
+%%
+%% The above copyright notice and this permission notice shall be included in
+%% all copies or substantial portions of the Software.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+%% THE SOFTWARE.
+%% -------------------------------------------------------------------
+-module(rebar_proto_gpb_compiler).
+
+-export([key/0,
+ proto_compile/3,
+ proto_clean/3]).
+
+%% for internal use only
+-export([proto_info/2]).
+
+-include("rebar.hrl").
+
+%% ===================================================================
+%% Public API
+%% ===================================================================
+
+key() ->
+ gpb.
+
+proto_compile(Config, _AppFile, _ProtoFiles) ->
+ %% Check for gpb library -- if it's not present, fail
+ %% since we have.proto files that need building
+ case gpb_is_present() of
+ true ->
+ rebar_base_compiler:run(Config, [],
+ "src", ".proto",
+ "src", ".erl",
+ fun compile_gpb/3,
+ [{check_last_mod, true}]);
+ false ->
+ ?ERROR("The gpb library is not present in code path!\n", []),
+ ?FAIL
+ end.
+
+proto_clean(Config, _AppFile, ProtoFiles) ->
+ GpbOpts = gpb_opts(Config),
+ MPrefix = proplists:get_value(module_name_prefix, GpbOpts, ""),
+ MSuffix = proplists:get_value(module_name_suffix, GpbOpts, ""),
+ rebar_file_utils:delete_each(
+ [beam_relpath(MPrefix, F, MSuffix) || F <- ProtoFiles]
+ ++ [erl_relpath(MPrefix, F, MSuffix) || F <- ProtoFiles]
+ ++ [hrl_relpath(MPrefix, F, MSuffix) || F <- ProtoFiles]),
+ ok.
+
+%% ===================================================================
+%% Internal functions
+%% ===================================================================
+
+proto_info(help, compile) ->
+ ?CONSOLE(
+ " gpb_opts is passed as options to gpb_compile:file/2.~n"
+ " erl_opts is used when compiling the generated erlang files,~n"
+ " so you might want to add an include path to gpb here,~n"
+ " for gpb.hrl, or else use the include_as_lib gpb_opts option,~n"
+ " or the defs_as_proplists gpb_opts option.~n",
+ []);
+proto_info(help, clean) ->
+ ?CONSOLE("", []).
+
+gpb_opts(Config) ->
+ rebar_config:get_local(Config, gpb_opts, []).
+
+gpb_is_present() ->
+ code:which(gpb) =/= non_existing.
+
+compile_gpb(Source, _Target, Config) ->
+ SourceFullPath = filename:absname(Source),
+ DefaultDestOpts = [{o_erl, "src"}, {o_hrl, "include"}],
+ SelfIncludeOpt = [{i,filename:dirname(SourceFullPath)}],
+ GpbOpts = gpb_opts(Config) ++ DefaultDestOpts ++ SelfIncludeOpt,
+ ok = filelib:ensure_dir(filename:join("ebin", "dummy")),
+ ok = filelib:ensure_dir(filename:join("include", "dummy")),
+ ?CONSOLE("Compiling ~s\n", [Source]),
+ case gpb_compile:file(SourceFullPath, GpbOpts) of
+ ok ->
+ ok;
+ {error, _Reason} ->
+ ?ERROR("Failed to compile ~s~n", [Source]),
+ ?FAIL
+ end.
+
+beam_relpath(Prefix, Proto, Suffix) ->
+ proto_filename_to_relpath("ebin", Prefix, Proto, Suffix, ".beam").
+
+erl_relpath(Prefix, Proto, Suffix) ->
+ proto_filename_to_relpath("src", Prefix, Proto, Suffix, ".erl").
+
+hrl_relpath(Prefix, Proto, Suffix) ->
+ proto_filename_to_relpath("include", Prefix, Proto, Suffix, ".hrl").
+
+proto_filename_to_relpath(Dir, Prefix, Proto, Suffix, NewExt) ->
+ BaseNoExt = filename:basename(Proto, ".proto"),
+ filename:join([Dir, Prefix ++ BaseNoExt ++ Suffix ++ NewExt]).
+