aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/relx.erl1
-rw-r--r--src/rlx_app_discovery.erl67
-rw-r--r--src/rlx_cmd_args.erl8
-rw-r--r--src/rlx_prv_assembler.erl126
-rw-r--r--src/rlx_prv_config.erl7
-rw-r--r--src/rlx_state.erl1
6 files changed, 173 insertions, 37 deletions
diff --git a/src/relx.erl b/src/relx.erl
index 359d47d..79eeae2 100644
--- a/src/relx.erl
+++ b/src/relx.erl
@@ -203,6 +203,7 @@ opt_spec_list() ->
"Provide an app name and a directory to override in the form <appname>:<app directory>"},
{config, $c, "config", {string, ""}, "The path to a config file"},
{overlay_vars, undefined, "overlay_vars", string, "Path to a file of overlay variables"},
+ {sys_config, undefined, "sys_config", string, "Path to a file to use for sys.config"},
{system_libs, undefined, "system_libs", string, "Path to dir of Erlang system libs"},
{version, undefined, "version", undefined, "Print relx version"},
{root_dir, $r, "root", string, "The project root directory"}].
diff --git a/src/rlx_app_discovery.erl b/src/rlx_app_discovery.erl
index aaa6e86..4a5620b 100644
--- a/src/rlx_app_discovery.erl
+++ b/src/rlx_app_discovery.erl
@@ -52,8 +52,56 @@ format_error(ErrorDetails)
%%%===================================================================
%%% Internal Functions
%%%===================================================================
+
+-spec app_files(list(binary())) -> list(binary()).
+app_files(LibDirs) ->
+ lists:foldl(fun(LibDir, Acc) ->
+ Files = app_files_paths(LibDir),
+ BinFiles = lists:map(fun(F) ->
+ list_to_binary(F)
+ end, Files),
+ Acc ++ BinFiles
+ end, [], LibDirs).
+
+-spec app_files_paths(binary()) -> list(string()).
+app_files_paths(LibDir) ->
+ %% Search for Erlang apps in the lib dir itself
+ Path1 = filename:join([binary_to_list(LibDir),
+ "*.app"]),
+ %% Search for Erlang apps in subdirs of lib dir
+ Path2 = filename:join([binary_to_list(LibDir),
+ "*",
+ "ebin",
+ "*.app"]),
+ lists:foldl(fun(Path, Acc) ->
+ Files = filelib:wildcard(Path),
+ Files ++ Acc
+ end, [], [Path1, Path2]).
+
+-spec get_app_metadata(rlx_state:t(), list(binary())) -> list({ok, rlx_app_info:t()}).
+get_app_metadata(State, LibDirs) ->
+ lists:foldl(fun(AppFile, Acc) ->
+ case is_valid_otp_app(AppFile) of
+ {ok, _} = AppMeta ->
+ [AppMeta|Acc];
+ {warning, W} ->
+ ec_cmd_log:warn(rlx_state:log(State), format_detail(W)),
+ Acc;
+ {error, E} ->
+ ec_cmd_log:error(rlx_state:log(State), format_detail(E)),
+ Acc;
+ _ ->
+ Acc
+ end
+ end, [], app_files(LibDirs)).
+
resolve_app_metadata(State, LibDirs) ->
- AppMeta0 = lists:flatten(rlx_dscv_util:do(fun discover_dir/2, LibDirs)),
+ AppMeta0 = case rlx_state:get(State, enable_shallow_app_discovery, false) of
+ true ->
+ get_app_metadata(State, LibDirs);
+ false ->
+ lists:flatten(rlx_dscv_util:do(fun discover_dir/2, LibDirs))
+ end,
case [case Err of
{error, Ret} ->
Ret
@@ -139,9 +187,10 @@ discover_dir(_File, directory) ->
discover_dir(File, file) ->
is_valid_otp_app(File).
--spec is_valid_otp_app(file:name()) -> {ok, rlx_app_info:t()} | {error, Reason::term()} |
+-spec is_valid_otp_app(file:name()) -> {ok, rlx_app_info:t()} |
+ {warning, Reason::term()} |
+ {error, Reason::term()} |
{noresult, false}.
-
is_valid_otp_app(File) ->
%% Is this an ebin dir?
EbinDir = filename:dirname(File),
@@ -159,7 +208,9 @@ is_valid_otp_app(File) ->
-spec gather_application_info(file:name(), file:filename()) ->
- {ok, rlx_app_info:t()} | {error, Reason::term()}.
+ {ok, rlx_app_info:t()} |
+ {warning, Reason::term()} |
+ {error, Reason::term()}.
gather_application_info(EbinDir, File) ->
AppDir = filename:dirname(EbinDir),
case file:consult(File) of
@@ -175,7 +226,9 @@ gather_application_info(EbinDir, File) ->
file:name(),
atom(),
proplists:proplist()) ->
- {ok, list()} | {error, Reason::term()}.
+ {ok, list()} |
+ {warning, Reason::term()} |
+ {error, Reason::term()}.
validate_application_info(EbinDir, AppFile, AppName, AppDetail) ->
AppDir = filename:dirname(EbinDir),
case get_modules_list(AppFile, AppDetail) of
@@ -190,7 +243,9 @@ validate_application_info(EbinDir, AppFile, AppName, AppDetail) ->
end.
-spec get_modules_list(file:name(), proplists:proplist()) ->
- {ok, list()} | {error, Reason::term()}.
+ {ok, list()} |
+ {warning, Reason::term()} |
+ {error, Reason::term()}.
get_modules_list(AppFile, AppDetail) ->
case proplists:get_value(modules, AppDetail) of
undefined ->
diff --git a/src/rlx_cmd_args.erl b/src/rlx_cmd_args.erl
index d2402ce..da8f3a0 100644
--- a/src/rlx_cmd_args.erl
+++ b/src/rlx_cmd_args.erl
@@ -253,7 +253,13 @@ create_disable_default_libs(Opts, Acc) ->
{ok, rlx_state:cmd_args()} | relx:error().
create_overlay_vars(Opts, Acc) ->
OverlayVars = proplists:get_all_values(overlay_vars, Opts),
- create_system_libs(Opts, [{overlay_vars, OverlayVars} | Acc]).
+ create_sys_config(Opts, [{overlay_vars, OverlayVars} | Acc]).
+
+-spec create_sys_config([getopt:option()], rlx_state:cmd_args()) ->
+ {ok, rlx_state:cmd_args()} | relx:error().
+create_sys_config(Opts, Acc) ->
+ SysConfig = proplists:get_value(sys_config, Opts, undefined),
+ create_system_libs(Opts, [{sys_config, SysConfig} | Acc]).
-spec create_system_libs([getopt:option()], rlx_state:cmd_args()) ->
{ok, rlx_state:cmd_args()} | relx:error().
diff --git a/src/rlx_prv_assembler.erl b/src/rlx_prv_assembler.erl
index 1a24ab6..d7bf3f1 100644
--- a/src/rlx_prv_assembler.erl
+++ b/src/rlx_prv_assembler.erl
@@ -296,9 +296,10 @@ write_bin_file(State, Release, OutputDir, RelDir) ->
VsnRel = filename:join(BinDir, rlx_release:canonical_name(Release)),
BareRel = filename:join(BinDir, RelName),
ErlOpts = rlx_state:get(State, erl_opts, ""),
+ {OsFamily, _OsName} = os:type(),
StartFile = case rlx_state:get(State, extended_start_script, false) of
false ->
- bin_file_contents(RelName, RelVsn,
+ bin_file_contents(OsFamily, RelName, RelVsn,
rlx_release:erts(Release),
ErlOpts);
true ->
@@ -321,7 +322,7 @@ write_bin_file(State, Release, OutputDir, RelDir) ->
false ->
ok
end,
- extended_bin_file_contents(RelName, RelVsn, rlx_release:erts(Release), ErlOpts)
+ extended_bin_file_contents(OsFamily, RelName, RelVsn, rlx_release:erts(Release), ErlOpts)
end,
%% We generate the start script by default, unless the user
%% tells us not too
@@ -329,15 +330,34 @@ write_bin_file(State, Release, OutputDir, RelDir) ->
false ->
ok;
_ ->
- ok = file:write_file(VsnRel, StartFile),
- ok = file:change_mode(VsnRel, 8#777),
- ok = file:write_file(BareRel, StartFile),
- ok = file:change_mode(BareRel, 8#777)
+ VsnRelStartFile = case OsFamily of
+ unix -> VsnRel;
+ win32 -> string:concat(VsnRel, ".cmd")
+ end,
+ ok = file:write_file(VsnRelStartFile, StartFile),
+ ok = file:change_mode(VsnRelStartFile, 8#777),
+ BareRelStartFile = case OsFamily of
+ unix -> BareRel;
+ win32 -> string:concat(BareRel, ".cmd")
+ end,
+ ok = file:write_file(BareRelStartFile, StartFile),
+ ok = file:change_mode(BareRelStartFile, 8#777)
end,
+ ReleasesDir = filename:join(OutputDir, "releases"),
+ generate_start_erl_data_file(Release, ReleasesDir),
copy_or_generate_vmargs_file(State, Release, RelDir),
copy_or_generate_sys_config_file(State, RelDir),
include_erts(State, Release, OutputDir, RelDir).
+%% @doc generate a start_erl.data file
+-spec generate_start_erl_data_file(rlx_release:t(), file:name()) ->
+ ok | relx:error().
+generate_start_erl_data_file(Release, ReleasesDir) ->
+ ErtsVersion = rlx_release:erts(Release),
+ ReleaseVersion = rlx_release:vsn(Release),
+ Data = ErtsVersion ++ " " ++ ReleaseVersion,
+ ok = file:write_file(filename:join(ReleasesDir, "start_erl.data"), Data).
+
%% @doc copy vm.args or generate one to releases/VSN/vm.args
-spec copy_or_generate_vmargs_file(rlx_state:t(), rlx_release:t(), file:name()) ->
{ok, rlx_state:t()} | relx:error().
@@ -390,29 +410,61 @@ copy_or_symlink_config_file(State, ConfigPath, RelConfPath) ->
-spec include_erts(rlx_state:t(), rlx_release:t(), file:name(), file:name()) ->
{ok, rlx_state:t()} | relx:error().
include_erts(State, Release, OutputDir, RelDir) ->
- case rlx_state:get(State, include_erts, true) of
- true ->
- Prefix = code:root_dir(),
+ Prefix = case rlx_state:get(State, include_erts, true) of
+ false ->
+ false;
+ true ->
+ code:root_dir();
+ P ->
+ filename:absname(P)
+ end,
+
+ case Prefix of
+ false ->
+ make_boot_script(State, Release, OutputDir, RelDir);
+ _ ->
+ ec_cmd_log:info(rlx_state:log(State),
+ "Including Erts from ~s~n", [Prefix]),
ErtsVersion = rlx_release:erts(Release),
ErtsDir = filename:join([Prefix, "erts-" ++ ErtsVersion]),
LocalErts = filename:join([OutputDir, "erts-" ++ ErtsVersion]),
+ {OsFamily, _OsName} = os:type(),
case filelib:is_dir(ErtsDir) of
false ->
?RLX_ERROR({specified_erts_does_not_exist, ErtsVersion});
true ->
ok = ec_file:mkdir_p(LocalErts),
ok = ec_file:copy(ErtsDir, LocalErts, [recursive]),
- Erl = filename:join([LocalErts, "bin", "erl"]),
- ok = ec_file:remove(Erl),
- ok = file:write_file(Erl, erl_script(ErtsVersion)),
- ok = file:change_mode(Erl, 8#755),
+ case OsFamily of
+ unix ->
+ Erl = filename:join([LocalErts, "bin", "erl"]),
+ ok = ec_file:remove(Erl),
+ ok = file:write_file(Erl, erl_script(ErtsVersion)),
+ ok = file:change_mode(Erl, 8#755);
+ win32 ->
+ ErlIni = filename:join([LocalErts, "bin", "erl.ini"]),
+ ok = ec_file:remove(ErlIni),
+ ok = file:write_file(ErlIni, erl_ini(OutputDir, ErtsVersion))
+ end,
+ case rlx_state:get(State, extended_start_script, false) of
+ true ->
+ ok = ec_file:copy(filename:join([Prefix, "bin", "start_clean.boot"]),
+ filename:join([OutputDir, "bin", "start_clean.boot"])),
+ NodeToolFile = nodetool_contents(),
+ InstallUpgradeFile = install_upgrade_escript_contents(),
+ NodeTool = filename:join([LocalErts, "bin", "nodetool"]),
+ InstallUpgrade = filename:join([LocalErts, "bin", "install_upgrade.escript"]),
+ ok = file:write_file(NodeTool, NodeToolFile),
+ ok = file:write_file(InstallUpgrade, InstallUpgradeFile),
+ ok = file:change_mode(NodeTool, 8#755),
+ ok = file:change_mode(InstallUpgrade, 8#755);
+ false ->
+ ok
+ end,
make_boot_script(State, Release, OutputDir, RelDir)
- end;
- _ ->
- make_boot_script(State, Release, OutputDir, RelDir)
+ end
end.
-
-spec make_boot_script(rlx_state:t(), rlx_release:t(), file:name(), file:name()) ->
{ok, rlx_state:t()} | relx:error().
make_boot_script(State, Release, OutputDir, RelDir) ->
@@ -475,16 +527,19 @@ make_relup(State, Release) ->
make_tar(State, Release, OutputDir) ->
Name = atom_to_list(rlx_release:name(Release)),
Vsn = rlx_release:vsn(Release),
- Prefix = code:root_dir(),
ErtsVersion = rlx_release:erts(Release),
- ErtsDir = filename:join([Prefix]),
Opts = [{path, [filename:join([OutputDir, "lib", "*", "ebin"])]},
{outdir, OutputDir} |
case rlx_state:get(State, include_erts, true) of
true ->
+ Prefix = code:root_dir(),
+ ErtsDir = filename:join([Prefix]),
[{erts, ErtsDir}];
false ->
- []
+ [];
+ Prefix ->
+ ErtsDir = filename:join([Prefix]),
+ [{erts, ErtsDir}]
end],
case systools:make_tar(filename:join([OutputDir, "releases", Vsn, Name]),
Opts) of
@@ -519,10 +574,10 @@ update_tar(State, TempDir, OutputDir, Name, Vsn, ErtsVersion) ->
filename:join([OutputDir, "releases", Vsn, "vm.args"])},
{"bin", filename:join([OutputDir, "bin"])} |
case rlx_state:get(State, include_erts, true) of
- true ->
- [{"erts-"++ErtsVersion, filename:join(OutputDir, "erts-"++ErtsVersion)}];
false ->
- []
+ [];
+ _ ->
+ [{"erts-"++ErtsVersion, filename:join(OutputDir, "erts-"++ErtsVersion)}]
end], [compressed]),
ec_cmd_log:info(rlx_state:log(State),
"tarball ~s successfully created!~n", [TarFile]),
@@ -648,13 +703,26 @@ ensure_not_exist(RelConfPath) ->
erl_script(ErtsVsn) ->
render(erl_script_dtl, [{erts_vsn, ErtsVsn}]).
-bin_file_contents(RelName, RelVsn, ErtsVsn, ErlOpts) ->
- render(bin_dtl, [{rel_name, RelName}, {rel_vsn, RelVsn},
- {erts_vsn, ErtsVsn}, {erl_opts, ErlOpts}]).
+bin_file_contents(OsFamily, RelName, RelVsn, ErtsVsn, ErlOpts) ->
+ Template = case OsFamily of
+ unix -> bin_dtl;
+ win32 -> bin_windows_dtl
+ end,
+ render(Template, [{rel_name, RelName}, {rel_vsn, RelVsn},
+ {erts_vsn, ErtsVsn}, {erl_opts, ErlOpts}]).
+
+extended_bin_file_contents(OsFamily, RelName, RelVsn, ErtsVsn, ErlOpts) ->
+ Template = case OsFamily of
+ unix -> extended_bin_dtl;
+ win32 -> extended_bin_windows_dtl
+ end,
+ render(Template, [{rel_name, RelName}, {rel_vsn, RelVsn},
+ {erts_vsn, ErtsVsn}, {erl_opts, ErlOpts}]).
-extended_bin_file_contents(RelName, RelVsn, ErtsVsn, ErlOpts) ->
- render(extended_bin_dtl, [{rel_name, RelName}, {rel_vsn, RelVsn},
- {erts_vsn, ErtsVsn}, {erl_opts, ErlOpts}]).
+erl_ini(OutputDir, ErtsVsn) ->
+ ErtsDirName = string:concat("erts-", ErtsVsn),
+ BinDir = filename:join([OutputDir, ErtsDirName, bin]),
+ render(erl_ini_dtl, [{bin_dir, BinDir}, {output_dir, OutputDir}]).
install_upgrade_escript_contents() ->
render(install_upgrade_escript_dtl).
diff --git a/src/rlx_prv_config.erl b/src/rlx_prv_config.erl
index 0379c2f..da620be 100644
--- a/src/rlx_prv_config.erl
+++ b/src/rlx_prv_config.erl
@@ -188,7 +188,12 @@ load_terms({release, {RelName, Vsn}, {erts, ErtsVsn},
load_terms({vm_args, VmArgs}, {ok, State}) ->
{ok, rlx_state:vm_args(State, filename:absname(VmArgs))};
load_terms({sys_config, SysConfig}, {ok, State}) ->
- {ok, rlx_state:sys_config(State, filename:absname(SysConfig))};
+ case rlx_state:sys_config(State) of
+ undefined ->
+ {ok, rlx_state:sys_config(State, filename:absname(SysConfig))};
+ _ ->
+ {ok, State}
+ end;
load_terms({output_dir, OutputDir}, {ok, State}) ->
{ok, rlx_state:output_dir(State, filename:absname(OutputDir))};
load_terms({overlay_vars, OverlayVars}, {ok, State}) ->
diff --git a/src/rlx_state.erl b/src/rlx_state.erl
index 2d0493b..0d4051e 100644
--- a/src/rlx_state.erl
+++ b/src/rlx_state.erl
@@ -129,6 +129,7 @@ new(PropList, Targets)
output_dir=proplists:get_value(output_dir, PropList, ""),
lib_dirs=[to_binary(Dir) || Dir <- proplists:get_value(lib_dirs, PropList, [])],
config_file=proplists:get_value(config, PropList, undefined),
+ sys_config=proplists:get_value(sys_config, PropList, undefined),
dev_mode = proplists:get_value(dev_mode, PropList),
actions = Targets,
caller = Caller,