From 9aa2d92d9048fb0fd7e1ec9d443aab8be7d33a8f Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 22 Jul 2015 10:48:44 +0200 Subject: [PATCH] Allow include of simple dependencies (EJAB-1737)(#391) Either contributed module include dependencies this way deps/ dep1/ src/ include/ dep1/ src/ include/ Or includes rebar.config or rebar.config.script: In this case, only git is supported (if git command available) and ext_mod checkout code in deps directory. In both case, only basic built procedure is supported. ext_mod does not do more than bare compilation like this: erlc -I include src/*erl --- src/ext_mod.erl | 77 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 3 deletions(-) diff --git a/src/ext_mod.erl b/src/ext_mod.erl index bfc448dcf..070fdf9d3 100644 --- a/src/ext_mod.erl +++ b/src/ext_mod.erl @@ -445,9 +445,14 @@ compile_and_install(Module, Spec) -> true -> {ok, Dir} = file:get_cwd(), file:set_cwd(SrcDir), - Result = case compile(Module, Spec, LibDir) of - ok -> install(Module, Spec, LibDir); - Error -> Error + Result = case compile_deps(Module, Spec, LibDir) of + ok -> + case compile(Module, Spec, LibDir) of + ok -> install(Module, Spec, LibDir); + Error -> Error + end; + Error -> + Error end, file:set_cwd(Dir), Result; @@ -459,6 +464,35 @@ compile_and_install(Module, Spec) -> end end. +compile_deps(_Module, _Spec, DestDir) -> + case filelib:is_dir("deps") of + true -> ok; + false -> fetch_rebar_deps() + end, + Ebin = filename:join(DestDir, "ebin"), + filelib:ensure_dir(filename:join(Ebin, ".")), + Result = lists:foldl(fun(Dep, Acc) -> + Inc = filename:join(Dep, "include"), + Src = filename:join(Dep, "src"), + Options = [{outdir, Ebin}, {i, Inc}], + [file:copy(App, Ebin) || App <- filelib:wildcard(Src++"/*.app")], + Acc++[case compile:file(File, Options) of + {ok, _} -> ok; + {ok, _, _} -> ok; + {ok, _, _, _} -> ok; + error -> {error, {compilation_failed, File}}; + Error -> Error + end + || File <- filelib:wildcard(Src++"/*.erl")] + end, [], filelib:wildcard("deps/*")), + case lists:dropwhile( + fun(ok) -> true; + (_) -> false + end, Result) of + [] -> ok; + [Error|_] -> Error + end. + compile(_Module, _Spec, DestDir) -> Ebin = filename:join(DestDir, "ebin"), filelib:ensure_dir(filename:join(Ebin, ".")), @@ -470,6 +504,7 @@ compile(_Module, _Spec, DestDir) -> Options = [{outdir, Ebin}, {i, "include"}, {i, EjabInc}, verbose, report_errors, report_warnings] ++ Logger ++ ExtLib, + [file:copy(App, Ebin) || App <- filelib:wildcard("src/*.app")], Result = [case compile:file(File, Options) of {ok, _} -> ok; {ok, _, _} -> ok; @@ -504,6 +539,42 @@ install(Module, Spec, DestDir) -> Error -> Error end. +%% -- minimalist rebar spec parser, only support git + +fetch_rebar_deps() -> + case rebar_deps("rebar.config")++rebar_deps("rebar.config.script") of + [] -> + ok; + Deps -> + filelib:ensure_dir(filename:join("deps", ".")), + lists:foreach(fun({_App, Cmd}) -> + os:cmd("cd deps; "++Cmd++"; cd ..") + end, Deps) + end. +rebar_deps(Script) -> + case file:script(Script) of + {ok, Config} when is_list(Config) -> + [rebar_dep(Dep) || Dep <- proplists:get_value(deps, Config, [])]; + {ok, {deps, Deps}} -> + [rebar_dep(Dep) || Dep <- Deps]; + _ -> + [] + end. +rebar_dep({App, _, {git, Url}}) -> + {App, "git clone "++Url++" "++filename:basename(App)}; +rebar_dep({App, _, {git, Url, {branch, Ref}}}) -> + {App, "git clone -n "++Url++" "++filename:basename(App)++ + "; (cd "++filename:basename(App)++ + "; git checkout -q origin/"++Ref++")"}; +rebar_dep({App, _, {git, Url, {tag, Ref}}}) -> + {App, "git clone -n "++Url++" "++filename:basename(App)++ + "; (cd "++filename:basename(App)++ + "; git checkout -q "++Ref++")"}; +rebar_dep({App, _, {git, Url, Ref}}) -> + {App, "git clone -n "++Url++" "++filename:basename(App)++ + "; (cd "++filename:basename(App)++ + "; git checkout -q "++Ref++")"}. + %% -- YAML spec parser consult(File) ->