summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/rebar_app_utils.erl30
-rw-r--r--src/rebar_otp_app.erl59
-rw-r--r--src/rebar_port_compiler.erl8
3 files changed, 78 insertions, 19 deletions
diff --git a/src/rebar_app_utils.erl b/src/rebar_app_utils.erl
index 744af4c..7794b5b 100644
--- a/src/rebar_app_utils.erl
+++ b/src/rebar_app_utils.erl
@@ -27,6 +27,8 @@
-module(rebar_app_utils).
-export([is_app_dir/0, is_app_dir/1,
+ is_app_src/1,
+ app_src_to_app/1,
app_name/1,
app_applications/1,
app_vsn/1]).
@@ -43,14 +45,31 @@ is_app_dir() ->
is_app_dir(rebar_util:get_cwd()).
is_app_dir(Dir) ->
- Fname = filename:join([Dir, "ebin/*.app"]),
- case filelib:wildcard(Fname) of
- [AppFile] ->
- {true, AppFile};
+ AppSrc = filename:join(Dir, "src/*.app.src"),
+ case filelib:wildcard(AppSrc) of
+ [AppSrcFile] ->
+ ?DEBUG("Found app.src: ~p\n", [AppSrcFile]),
+ {true, AppSrcFile};
_ ->
- false
+ App = filename:join([Dir, "ebin/*.app"]),
+ case filelib:wildcard(App) of
+ [AppFile] ->
+ ?DEBUG("Found .app: ~p\n", [AppFile]),
+ {true, AppFile};
+ _ ->
+ false
+ end
end.
+
+is_app_src(Filename) ->
+ %% If removing the extension .app.src yields a shorter name,
+ %% this is an .app.src file.
+ Filename /= filename:rootname(Filename, ".app.src").
+
+app_src_to_app(Filename) ->
+ filename:join("ebin", filename:basename(Filename, ".app.src") ++ ".app").
+
app_name(AppFile) ->
case load_app_file(AppFile) of
{ok, AppName, _} ->
@@ -79,7 +98,6 @@ app_vsn(AppFile) ->
end.
-
%% ===================================================================
%% Internal functions
%% ===================================================================
diff --git a/src/rebar_otp_app.erl b/src/rebar_otp_app.erl
index 8db1044..bcc13fd 100644
--- a/src/rebar_otp_app.erl
+++ b/src/rebar_otp_app.erl
@@ -27,6 +27,7 @@
-module(rebar_otp_app).
-export([compile/2,
+ clean/2,
install/2]).
-include("rebar.hrl").
@@ -36,12 +37,34 @@
%% ===================================================================
compile(_Config, File) ->
- %% Load the app name and version from the .app file and construct
- %% the app identifier
- {ok, AppName, AppData} = rebar_app_utils:load_app_file(File),
- validate_name(AppName, File),
- validate_modules(AppName, proplists:get_value(modules, AppData)),
- ok.
+ %% If we get an .app.src file, it needs to be pre-processed and
+ %% written out as a ebin/*.app file. That resulting file will then
+ %% be validated as usual.
+ case rebar_app_utils:is_app_src(File) of
+ true ->
+ AppFile = preprocess(File);
+ false ->
+ AppFile = File
+ end,
+
+ %% Load the app file and validate it.
+ case rebar_app_utils:load_app_file(AppFile) of
+ {ok, AppName, AppData} ->
+ validate_name(AppName, AppFile),
+ validate_modules(AppName, proplists:get_value(modules, AppData));
+ {error, Reason} ->
+ ?ABORT("Failed to load app file ~s: ~p\n", [AppFile, Reason])
+ end.
+
+clean(_Config, File) ->
+ %% If the app file is a .app.src, delete the generated .app file
+ case rebar_app_utils:is_app_src(File) of
+ true ->
+ file:delete(rebar_app_utils:app_src_to_app(File)),
+ ok;
+ false ->
+ ok
+ end.
install(Config, File) ->
@@ -116,6 +139,25 @@ install_binaries([Bin | Rest], AppDir, BinDir) ->
rebar_file_utils:ln_sf(FqBin, BinDir),
install_binaries(Rest, AppDir, BinDir).
+preprocess(AppSrcFile) ->
+ case rebar_app_utils:load_app_file(AppSrcFile) of
+ {ok, AppName, AppData} ->
+ %% Get a list of all the modules available in ebin/ and update
+ %% the app data accordingly
+ A1 = lists:keystore(modules, 1, AppData, {modules, ebin_modules()}),
+
+ %% Build the final spec as a string
+ Spec = io_lib:format("~p.\n", [{application, AppName, A1}]),
+
+ %% Setup file .app filename and write new contents
+ AppFile = rebar_app_utils:app_src_to_app(AppSrcFile),
+ ok = file:write_file(AppFile, Spec),
+ AppFile;
+
+ {error, Reason} ->
+ ?ABORT("Failed to read ~s for preprocessing: ~p\n", [AppSrcFile, Reason])
+ end.
+
validate_name(AppName, File) ->
%% Convert the .app file name to an atom -- check it against the identifier within the file
@@ -136,7 +178,7 @@ validate_modules(AppName, undefined) ->
validate_modules(AppName, Mods) ->
%% Construct two sets -- one for the actual .beam files in ebin/ and one for the modules
%% listed in the .app file
- EbinSet = ordsets:from_list([rebar_utils:beam_to_mod("ebin", N) || N <- rebar_utils:beams("ebin")]),
+ EbinSet = ordsets:from_list(ebin_modules()),
ModSet = ordsets:from_list(Mods),
%% Identify .beam files listed in the .app, but not present in ebin/
@@ -160,3 +202,6 @@ validate_modules(AppName, Mods) ->
[AppName, Msg2]),
?FAIL
end.
+
+ebin_modules() ->
+ lists:sort([rebar_utils:beam_to_mod("ebin", N) || N <- rebar_utils:beams("ebin")]).
diff --git a/src/rebar_port_compiler.erl b/src/rebar_port_compiler.erl
index 6960a5f..f38b621 100644
--- a/src/rebar_port_compiler.erl
+++ b/src/rebar_port_compiler.erl
@@ -352,12 +352,8 @@ so_specs(Config, AppFile, Bins) ->
undefined ->
%% Ok, neither old nor new form is available. Use the app name and
%% generate a sensible default.
- case rebar_app_utils:load_app_file(AppFile) of
- {ok, AppName, _} ->
- ?FMT("priv/~s", [lists:concat([AppName, "_drv.so"])]);
- error ->
- ?FAIL
- end;
+ AppName = rebar_app_utils:app_name(AppFile),
+ ?FMT("priv/~s", [lists:concat([AppName, "_drv.so"])]);
AName ->
%% Old form is available -- use it