Current section

Files

Jump to
gpb build compile_descriptor
Raw

build/compile_descriptor

#!/usr/bin/env escript
%% -*- erlang -*-
-include_lib("kernel/include/file.hrl").
is_up_to_date(Target, Deps) ->
case file:read_file_info(Target) of
{ok, #file_info{mtime = TargetMTime}} ->
lists:all(fun(Dep) ->
case file:read_file_info(Dep) of
{ok, #file_info{mtime = MTime}} ->
MTime =< TargetMTime;
_ ->
false
end
end, Deps);
_ ->
false
end.
make_target(Target, Deps, CmdFun) ->
case is_up_to_date(Target, Deps) of
true ->
ok;
_ ->
io:format("Compiling ~s...~n", [filename:basename(hd(Deps))]),
CmdFun()
end.
make(Makescript) ->
lists:foreach(
fun({Target, Deps, CmdFun}) -> make_target(Target, Deps, CmdFun) end,
Makescript).
gpb_compile_file_cmd(Proto, Opts) ->
fun() ->
check_ok_or_halt(gpb_compile:file(Proto, Opts))
end.
compile_file_cmd(Erl, Opts) ->
fun() ->
check_ok_or_halt(compile:file(Erl, Opts))
end.
check_ok_or_halt(Res) ->
if Res =:= ok -> ok;
element(1, Res) =:= ok -> ok;
true -> halt(1)
end.
deps_dir() ->
case os:getenv("REBAR_DEPS_DIR") of
false ->
%% Elixir 1.12+
os:getenv("REBAR_BARE_COMPILER_OUTPUT_DIR");
DepsDir ->
DepsDir
end.
checkouts_out_dir() ->
os:getenv("REBAR_CHECKOUTS_OUT_DIR").
gpb_exists_via_env(DirEnvValue) ->
if DirEnvValue == false ->
false;
is_list(DirEnvValue) ->
filelib:is_dir(filename:join(DirEnvValue, "gpb"))
end.
main(_) ->
REBAR_CHECKOUTS_OUT_DIR = checkouts_out_dir(),
REBAR_DEPS_DIR = deps_dir(),
GpbExistsInCheckoutsOutDir = gpb_exists_via_env(REBAR_CHECKOUTS_OUT_DIR),
GpbExistsInDepsDir = gpb_exists_via_env(REBAR_DEPS_DIR),
{EbinPath, TestPath} =
if GpbExistsInCheckoutsOutDir ->
%% With _checkouts and rebar3 3.14 or later
{filename:join([REBAR_CHECKOUTS_OUT_DIR, "gpb", "ebin"]),
filename:join([REBAR_CHECKOUTS_OUT_DIR, "gpb", "test"])};
GpbExistsInDepsDir ->
{filename:join([REBAR_DEPS_DIR, "gpb", "ebin"]),
filename:join([REBAR_DEPS_DIR, "gpb", "test"])};
true ->
%% rebar2 (or make)
{"./ebin", "./test"}
end,
filelib:ensure_dir(filename:join(EbinPath, ".dummy")),
GpbcOpts = [{i, "priv/proto3/google/protobuf"},
{o, "descr_src"}, {module_name_prefix, "gpb_"},
report],
ErlcOpts = [{i, "descr_src"}, {i,"include"},
{outdir, EbinPath}, debug_info,
report],
code:add_patha(EbinPath),
MakeScript =
[{"descr_src/gpb_descriptor.erl",
["priv/proto3/google/protobuf/descriptor.proto"],
gpb_compile_file_cmd("descriptor.proto", GpbcOpts)},
{filename:join(EbinPath, "gpb_descriptor.beam"),
["descr_src/gpb_descriptor.erl"],
compile_file_cmd("descr_src/gpb_descriptor.erl", ErlcOpts)},
{filename:join(EbinPath, "gpb_compile_descr.beam"),
["descr_src/gpb_compile_descr.erl",
"descr_src/gpb_descriptor.hrl"],
compile_file_cmd("descr_src/gpb_compile_descr.erl", ErlcOpts)},
{filename:join(EbinPath, "gpb_parse_descr.beam"),
["descr_src/gpb_parse_descr.erl",
"descr_src/gpb_descriptor.hrl"],
compile_file_cmd("descr_src/gpb_parse_descr.erl", ErlcOpts)}],
make(MakeScript),
case filelib:is_dir(TestPath) of
true ->
%% eg: "rebar3 eunit" or "rebar2 eunit"
%% but not "rebar3 compile"
%% and not when compiling gpb as a dependency, since
%% the test directory does not exist in the hex package.
ErlcTestOpts = [{i, "descr_src"}, {i, "include"},
{outdir, TestPath}, debug_info],
TestMakeScript =
[{filename:join(TestPath, "gpb_compile_descr_tests.beam"),
["descr_src/gpb_compile_descr_tests.erl",
"descr_src/gpb_compile_descr.erl",
"descr_src/gpb_descriptor.hrl"],
compile_file_cmd("descr_src/gpb_compile_descr_tests.erl",
ErlcTestOpts)},
{filename:join(TestPath, "gpb_parse_descr_tests.beam"),
["descr_src/gpb_parse_descr_tests.erl",
"descr_src/gpb_parse_descr.erl",
"descr_src/gpb_descriptor.hrl"],
compile_file_cmd("descr_src/gpb_parse_descr_tests.erl",
ErlcTestOpts)}],
make(TestMakeScript);
_ ->
next
end.