Skip to content
Ulf Wiger edited this page Jul 2, 2021 · 2 revisions

Example: Installing and Upgrading with Setup

In this example, we will install a very simple system using setup_gen. We will also demonstrate how to add applications to an embedded target, and how to upgrade an application on the fly.

Specifying the system

Setup can read either a reltool.config file or a special 'setup' config. In this example, we will create the simplest possible 'setup' config file.

test.script:

%% -*- erlang -*-
[{apps, [kernel, stdlib, sasl, setup, gproc]}].

The only option we really must provide is apps.

Generating boot script, etc.

From the Unix command-line, we type

escript $SETUP_ROOT/ebin/setup_gen.beam -name test -conf test.script -out test

The -name option (mandatory) gives the release a name. The -conf option points to the config file we just wrote, and the -out option names a target directory for the installation.

Now, we should have some files in the test/ directory:

uwair:setup-test-120502 uwiger# ls test/
setup_gen.eterm	start.boot	start.rel	start.script	sys.config

The setup_gen.eterm is a text file outlining the config options used for the system. The other files are what we expect.

Starting the System

To make things interesting, we will start the system with embedded code loading. This means that all modules are loaded at boot time, and interactive code loading is disabled. This is a common approach for target systems, even though it makes things a bit harder while you're developing and testing (we'll get to that).

uwair:setup-test-120502 uwiger# erl -boot test/start -config test/sys -mode embedded
Erlang R15B (erts-5.9) [source] [64-bit] [smp:4:4] [async-threads:0] [hipe] [kernel-poll:false]


=PROGRESS REPORT==== 4-May-2012::21:09:11 ===
[...]
=PROGRESS REPORT==== 4-May-2012::21:09:11 ===
         application: sasl
          started_at: nonode@nohost
[...]
=PROGRESS REPORT==== 4-May-2012::21:09:11 ===
         application: gproc
          started_at: nonode@nohost
Eshell V5.9  (abort with ^G)
1> 

There! We have a running system, built according to OTP design principles.

Extending the System

Now, as we are testing our system, we may realize that we need dbg, and we don't have it included in our release!

The setup application has a number of convenience functions, some of which try to make things easier during development.

Let's use the function setup:patch_app(App). App in this case is runtime_tools, which is where dbg lives.

First, let's verify that just running dbg doesn't work:

1> dbg:tracer().
** exception error: undefined function dbg:tracer/0

This is embedded code loading for you. ;-)

2> setup:patch_app(runtime_tools).
[runtime_tools vsn "1.8.7"] code:add_patha(/usr/lib/erlang/lib/runtime_tools-1.8.7/ebin)
true

Now we have runtime_tools in the path, but what happened?

Setup checked the current path and figured out which "lib roots" existed within. It then checked all those roots, and also $ERL_LIBS, if set, to see if the wanted application could be found there. In fact, it finds all the instances, and sorts them by version. If (as in our case) no specific version was requested, setup will pick the latest version, and prepend that to the path.

We have to do one more thing before we can run dbg - load the modules.

There is a function for that too:

3> setup:reload_app(runtime_tools).
{ok,[]}
4> dbg:tracer().
{ok,<0.52.0>}

...and now we can run dbg.

Upgrading an Application

Assume we have installed a real target system with rebar/reltool, and thus created a separate code tree. While testing and debugging, we may want to switch an application to the development version. We can use reload_app/1 for that.

First, let's check what version of gproc we're running:

5> code:lib_dir(gproc).
"/Users/uwiger/ETC/git/gproc"

Let's use another convenience function in setup:

6> setup:find_app(gproc).
[{"0.2.7","/Users/uwiger/ETC/git/gproc/ebin"}]

This locates all versions of the app under the lib roots and ERL_LIBS, as discussed above.

Now, let's assume that the development version we need is under a certain $ERL_LIBS root:

7> os:putenv("ERL_LIBS", "/Users/uwiger/FL/git").
true
8> setup:find_app(gproc).                        
[{"0.2.7","/Users/uwiger/ETC/git/gproc/ebin"},
 {"0.2.12-20-gc60b9b4","/Users/uwiger/FL/git/gproc/ebin"}]

Now, setup found a new version. Let's switch to that one. It's the latest (last in the list), so we can be lazy and not specify a particular version:

9> setup:reload_app(gproc).
[gproc vsn "0.2.12-20-gc60b9b4"] soft upgrade from "0.2.7"
{ok,[]}

Setup generated an "appup" script on the fly and used the SASL Release Handler functions to execute it.

Let's just verify that the application has really been switched:

10> code:which(gproc).
"/Users/uwiger/FL/git/gproc/ebin/gproc.beam"
11> application:get_all_key(gproc).
{ok,[{description,"GPROC"},
     {id,"GPROC"},
     {vsn,"0.2.12-20-gc60b9b4"},
     {modules,[gproc,gproc_app,gproc_dist,gproc_info,gproc_init,
               gproc_lib,gproc_monitor,gproc_ps,gproc_sup]},
     {maxP,infinity},
     {maxT,infinity},
     {registered,[]},
     {included_applications,[]},
     {applications,[kernel,stdlib]},
     {env,[{included_applications,[]}]},
     {mod,{gproc_app,[]}},
     {start_phases,undefined}]}