Skip to content

Commit

Permalink
Make Erlang installation file system location independent
Browse files Browse the repository at this point in the history
Previously shell scripts (e.g., `erl` and `start`) and the RELEASES file
for an Erlang installation depended on hard coded absolute path to the
installation's root directory. This made it cumbersome to move a
release to a different directory and can be problematic for platforms
such as Android (erlang#2879) where the
installation directory is unknown at compile time. This is fixed by:

* Changing the shell scripts so that they can dynamically find the
  `ROOTDIR`. The dynamically found `ROOTDIR` is selected if it differs
  from the hard-coded `ROOTDIR` and seems to point to a valid Erlang
  installation. The `dyn_erl` program has been changed so that it can
  return its absolute canonicalized path when given the `--realpath`
  argument (dyn_erl gets its absolute canonicalized path from the
  `realpath` POSIX function). The `dyn_erl`'s `--realpath`
  functionality is used by the scripts to get the root dir dynamically.

* Changing the `release_handler` module that reads and writes to the
  `RELEASES` file so that it prepends `code:root_dir()` whenever it
  encounters relative paths. This is necessary since the current
  working directory can be changed so it is something different than
  `code:root_dir()`.
  • Loading branch information
kjellwinblad committed Nov 19, 2021
1 parent ec465f6 commit bf3449c
Show file tree
Hide file tree
Showing 25 changed files with 570 additions and 47 deletions.
4 changes: 3 additions & 1 deletion Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -577,10 +577,12 @@ else
bootstrap_setup: check_recreate_primary_bootstrap bootstrap_setup_target $(BOOTSTRAP_ROOT)/bootstrap/bin/erl $(BOOTSTRAP_ROOT)/bootstrap/bin/erlc $(BOOTSTRAP_ROOT)/bootstrap/bin/escript $(BOOTSTRAP_ROOT)/bootstrap/bin/yielding_c_fun

$(BOOTSTRAP_ROOT)/bootstrap/bin/erl: $(ERL_TOP)/erts/etc/unix/erl.src.src $(BOOTSTRAP_ROOT)/bootstrap/target
@rm -f $(BOOTSTRAP_ROOT)/bootstrap/bin/erl
@rm -f $(BOOTSTRAP_ROOT)/bootstrap/bin/erl
@sed -e "s;%FINAL_ROOTDIR%;$(BOOTSTRAP_ROOT)/bootstrap;" \
-e "s;\$$ROOTDIR/erts-.*/bin;$(ERL_TOP)/bin/$(TARGET);" \
-e "s;EMU=.*;EMU=beam$(TYPEMARKER);" \
-e "s;%DYN_ERL_PATH%;../../bin/$(TARGET)/dyn_erl;" \
-e "s;%DYN_ROOTDIR_BASE_EXT%;/bootstrap;" \
$(ERL_TOP)/erts/etc/unix/erl.src.src > \
$(BOOTSTRAP_ROOT)/bootstrap/bin/erl
@chmod 755 $(BOOTSTRAP_ROOT)/bootstrap/bin/erl
Expand Down
3 changes: 3 additions & 0 deletions erts/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,13 @@ local_setup:
sed -e "s;%FINAL_ROOTDIR%;$(ERL_TOP);" \
-e "s;erts-.*/bin;bin/$(TARGET);" \
-e "s;EMU=.*;EMU=beam$(TYPEMARKER);" \
-e "s;%DYN_ERL_PATH%;$(TARGET)/dyn_erl;" \
-e "s;%DYN_ROOTDIR_BASE_EXT%;;" \
$(ERL_TOP)/erts/etc/unix/erl.src.src > $(ERL_TOP)/bin/erl; \
sed -e "s;%SRC_ROOTDIR%;$(ERL_TOP);" \
-e "s;%TARGET%;$(TARGET);" \
-e "s;%VSN%;$(VSN);" \
-e "s;%DYN_ERL_PATH%;$(TARGET)/dyn_erl;" \
$(ERL_TOP)/erts/etc/unix/cerl.src > $(ERL_TOP)/bin/cerl; \
cp $(ERL_TOP)/bin/$(TARGET)/erl_call $(ERL_TOP)/bin/erl_call; \
cp $(ERL_TOP)/bin/$(TARGET)/dialyzer $(ERL_TOP)/bin/dialyzer; \
Expand Down
2 changes: 2 additions & 0 deletions erts/etc/common/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,8 @@ erl.src: $(UXETC)/erl.src.src ../../vsn.mk $(TARGET)/Makefile
$(vsn_verbose)sed -e 's;%EMULATOR%;$(EMULATOR);' \
-e 's;%EMULATOR_NUMBER%;$(EMULATOR_NUMBER);' \
-e 's;%VSN%;$(VSN);' \
-e 's;%DYN_ERL_PATH%;../erts-$(VSN)/bin/dyn_erl;' \
-e 's;%DYN_ROOTDIR_BASE_EXT%;;' \
$(UXETC)/erl.src.src > erl.src

# ----------------------------------------------------
Expand Down
6 changes: 4 additions & 2 deletions erts/etc/unix/Install.src
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ chmod 755 erl
# Create start file for embedded system use,
#
(cd "$ERL_ROOT/erts-%I_VSN%/bin";
sed -e "s;%FINAL_ROOTDIR%;$TARGET_ERL_ROOT;" start.src > start;
sed -e "s;%FINAL_ROOTDIR%;$TARGET_ERL_ROOT;" \
-e "s;%VSN%;%I_VSN%;" \
start.src > start;
chmod 755 start)

cd "$ERL_ROOT/bin"
Expand Down Expand Up @@ -113,7 +115,7 @@ sed -e "s;%EMU%;%EMULATOR%%EMULATOR_NUMBER%;" "$ERL_ROOT/erts-%I_VSN%/bin/start_
chmod 755 start_erl

echo %I_VSN% %I_SYSTEM_VSN% > "$ERL_ROOT/releases/start_erl.data"
sed -e "s;%ERL_ROOT%;$TARGET_ERL_ROOT;" "$ERL_ROOT/releases/RELEASES.src" > "$ERL_ROOT/releases/RELEASES"
sed -e "s;%ERL_ROOT%/;;" "$ERL_ROOT/releases/RELEASES.src" > "$ERL_ROOT/releases/RELEASES"

if [ "$start_option" = "query" ]
then
Expand Down
19 changes: 19 additions & 0 deletions erts/etc/unix/cerl.src
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,27 @@ run_asan=no
run_rr=no
skip_erlexec=no

prog="$0"
progdir="`dirname ${prog}`"
dyn_erl_path="${progdir}/%DYN_ERL_PATH%"
if [ -f "$dyn_erl_path" ]
then
dyn_rootdir=`${dyn_erl_path} --realpath`
dyn_rootdir=`dirname ${dyn_rootdir}`
dyn_rootdir=`dirname ${dyn_rootdir}`
else
dyn_rootdir=""
fi

# Default rootdir
ROOTDIR=%SRC_ROOTDIR%

if [ "$dyn_rootdir" != "$ROOTDIR" ] && [ "$dyn_rootdir" != "" ]
then
# It is likely that the files have been copied or moved
ROOTDIR="$dyn_rootdir"
fi

BINDIR="$ROOTDIR/bin/`$ROOTDIR/make/autoconf/config.guess`"
TARGET=%TARGET%
#BINDIR="$ROOTDIR/bin/%TARGET%"
Expand Down
9 changes: 9 additions & 0 deletions erts/etc/unix/dyn_erl.c
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,15 @@ main(int argc, char **argv)
char progname[PATH_MAX]; /* Name of this program. */
char erlexec[PATH_MAX]; /* Path to erlexec */

if (argc == 2 && strcmp(argv[1], "--realpath") == 0) {
abspath = find_prog(argv[0]);
/* Remove program name from output */
for (p = abspath+strlen(abspath)-1;p >= abspath && *p != '/'; --p)
;
*p = '\0';
printf("%s", abspath);
return 0;
}
/* Determine progname */
abspath = find_prog(argv[0]);
strcpy(progname, abspath);
Expand Down
23 changes: 23 additions & 0 deletions erts/etc/unix/erl.src.src
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,32 @@
#
# %CopyrightEnd%
#
prog="$0"
progdir="`dirname ${prog}`"
dyn_erl_path="${progdir}/%DYN_ERL_PATH%"
if [ ! -f "$dyn_erl_path" ]
then
dyn_erl_path="${progdir}/dyn_erl"
fi

if [ -f "$dyn_erl_path" ]
then
dyn_rootdir=`${dyn_erl_path} --realpath`
dyn_rootdir=`dirname ${dyn_rootdir}`
dyn_rootdir=`dirname ${dyn_rootdir}`
dyn_rootdir="${dyn_rootdir}%DYN_ROOTDIR_BASE_EXT%"
else
dyn_rootdir=""
fi

if [ -z "$ERL_ROOTDIR" ]
then
ROOTDIR="%FINAL_ROOTDIR%"
if [ "$dyn_rootdir" != "$ROOTDIR" ] && [ "$dyn_rootdir" != "" ]
then
# It is likely that the files have been copied or moved
ROOTDIR="$dyn_rootdir"
fi
else
ROOTDIR="$ERL_ROOTDIR"
fi
Expand Down
22 changes: 22 additions & 0 deletions erts/etc/unix/start.src
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,31 @@
#
# Usage: start [Data]
#
prog="$0"
progdir="`dirname ${prog}`"
dyn_erl_path="${progdir}/../erts-%VSN%/bin/dyn_erl"
if [ ! -f "$dyn_erl_path" ]
then
dyn_erl_path="${progdir}/dyn_erl"
fi

if [ -f "$dyn_erl_path" ]
then
dyn_rootdir=`${dyn_erl_path} --realpath`
dyn_rootdir=`dirname ${dyn_rootdir}`
dyn_rootdir=`dirname ${dyn_rootdir}`
else
dyn_rootdir=""
fi

if [ -z "$ERL_ROOTDIR" ]
then
ROOTDIR="%FINAL_ROOTDIR%"
if [ "$dyn_rootdir" != "$ROOTDIR" ] && [ "$dyn_rootdir" != "" ]
then
# It is likely that the files have been copied or moved
ROOTDIR="$dyn_rootdir"
fi
else
ROOTDIR="$ERL_ROOTDIR"
fi
Expand Down
19 changes: 13 additions & 6 deletions lib/sasl/doc/src/release_handler.xml
Original file line number Diff line number Diff line change
Expand Up @@ -215,12 +215,19 @@
<p>Creates an initial <c>RELEASES</c> file to be used by the
release handler. This file must exist to install new
releases.</p>
<p><c>Root</c> is the root of the installation (<c>$ROOT</c>) as
described earlier. <c>RelDir</c> is the directory where
the <c>RELEASES</c> file is to be created (normally
<c>$ROOT/releases</c>). <c>RelFile</c> is the name
of the <c>.rel</c> file that describes the initial release,
including the extension <c>.rel</c>.</p>
<p><c>Root</c> is the root of the installation (<c>$ROOT</c>)
as described earlier. <c>RelDir</c> is the directory where the
<c>RELEASES</c> file is to be created (normally
<c>$ROOT/releases</c>). <c>RelFile</c> is the name of the
<c>.rel</c> file that describes the initial release, including
the extension <c>.rel</c>. If <c>Root</c> is an empty string,
the <c>RELEASES</c> file will be location independent (i.e, it
will not contain absolute paths unless there are absolute
paths in <c>AppDirs</c>). A <c>RELEASES</c> file should be
made location independent if the installation's <c>$ROOT</c>
is unknown. The <c>release_handler</c> module will interpret
relative paths in a running system's <c>RELEASES</c> file as
being relative to <c>$ROOT</c>.</p>
<p><c>AppDirs</c> can be used to specify from where the modules
for the specified applications are to be loaded. <c>App</c> is
the name of an application, <c>Vsn</c> is the version, and
Expand Down
Loading

0 comments on commit bf3449c

Please sign in to comment.