diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/relx.erl | 1 | ||||
-rw-r--r-- | src/rlx_app_discovery.erl | 67 | ||||
-rw-r--r-- | src/rlx_cmd_args.erl | 8 | ||||
-rw-r--r-- | src/rlx_prv_assembler.erl | 126 | ||||
-rw-r--r-- | src/rlx_prv_config.erl | 7 | ||||
-rw-r--r-- | src/rlx_state.erl | 1 |
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, |