> ## 3 The Release Structure

> Erlang programs are organized into modules. Each module in a release must have a unique name.

> Collections of modules which cooperate to solve a particular problem are organized into applications. Applications are described in an application resource file.

> Collections of applications are organized into a release. Releases are described in a release resource file.

> ### 3.1 Naming of Modules, Applications and Releases

> Each module in the system has a version number. An Erlang module should start with

>     -module(Mod).
>     -vsn(Vsn).
>     ...

> and should be stored in a file named as `Mod.erl`.

> The name of the module is `Mod` and the version of the module is `Vsn`. `Mod` must be an atom while `Vsn` can be any valid Erlang term. For example, the version can be an integer or a string, which represents an Ericsson product number.

> Also the applications have versions, but the version must be a string. For example, the application resource file for the application named `snmp` must be stored in a file named `snmp.app` and must start:

>     {application, snmp,
>       [{vsn, Va},
>        {modules,
>          [{lists, V1},
>           {ordsets, V2}
>           ...

> Here, `Va` is the version of the application (a string). The application uses the Erlang module versions `V1, V2, ...`, where `V1, V2, ...` can be any valid Erlang terms. The only requirement is that the module version types (integers, strings, etc.) agrees with the convention used in the module declarations.

> | In the application resource file, the name of a module must be specified in `modules`, but the version number is not a mandatory requirement. Hence the following is also valid contents for an application resource file:
>     {application, snmp,
>       [{vsn, Va},
>        {modules,
>          [lists,
>           ordsets,
>           ...

> Applications can be upgraded and the instructions to do this are placed in the `.appup` file for the application. For example, for the `snmp` application these instructions are placed in the `snmp.appup` file. An `.appup` file contains the following:

>     {Vsn,
>         [{UpFromVsn, UpFromScript}, ...],
>         [{DownToVsn, DownToScript}, ...]
>     }.

> - `Vsn` is the version of the application
> - `UpFromVsn` is a version we can upgrade from
> - `UpFromScript` is the script which describes the sequence of release upgrade instructions. Refer to the section Release Handling Instructions
> - `DownToVsn` is a version to which we can downgrade
> - `DownToScript` is the script which describes the sequence of downgrade instructions.

> In the case of `UpFromScript` and `DownFromScript`, the scripts typically contain one line for each module in the application.

> A release resource file has a structure similar to an application resource file. The file `ReleaseFileName.rel`, which describes the release contains the following:

>     {release, {Name,Vsn}, {erts, EVsn},
>      [{AppName, AppVsn}, {AppName, AppVsn, AppType},  {AppName, AppVsn,
>      IncApps}, {AppName, AppVsn, AppType, IncApps} ...]}.

> - `Name` is the name of the release (a string). `Name` needs not to be the same as `ReleaseFileName` above.
> - `Vsn` is the version of the release (a string).
> - `{erts, EVsn}` indicates which Erlang runtime system version `EVsn` the release is intended for, for example "4.4". `EVsn` must be a string.
> - `AppName` is the name of an application included in the release (an atom).
> - `AppVsn` is the version of the `AppName` application (a string).
> - The application is started by a call to `application:start(AppName, AppType)`, if the `AppType` is `permanent`, `transient` or `temporary`. If `AppType` is `load` the application is loaded but not started, and if it is `none` the application is neither loaded or started.
> - `IncApps` is a list of applications that are included by an application, for example `[AppName, ...]`. This list overrides the `included_applications` key in the application resource file `.app`. It must be a subset of the list of included applications which are specified in the `.app` file.

> | The list of applications must contain the `kernel` and the `stdlib` applications.

> Releases can also be upgraded and instructions for this should be written in the `relup` file (see the definition of the relup file). The tedious work of writing the `relup` file is automated and in most cases, the file will be automatically generated from the `.appup` files for the applications in the release.

> ### 3.2 Release Tools

> There are tools available to build and check release packages. These tools read the release resource file, the application resource files and upgrade files, and they generate a boot script, a release upgrade script, and also build a release package.

> The following functions are in the `systools` module:

> - `make_script` generates a boot script
> - `make_relup` generates a release upgrade script
> - `make_tar` generates a release package `.tar` file .

> These functions read the `.rel` release resource file from the current directory and perform syntax and dependency checks before the output is generated.

> | The generated files are written to the current directory as well.

> Refer to the Reference Manual for more information about these functions.

> ### 3.3 Release Directories

> A release should be divided into the following directories:

>     $ROOTDIR/lib/App1-AVsn1/ebin
>                           /priv
>                 /App2-AVsn2/ebin
>                            /priv
>                 ...
>                 /AppN-AVsnN/ebin
>                            /priv
>             /erts-EVsn/bin
>             /releases/Vsn
>             /bin

> The release resource file includes one `AppN-AVsnN` directory per application. `AppN` is the name and `AVsnN` is the version of the application.

> - The `ebin` directory contains the Erlang object code and the application resource file.
> - The `priv` directory contains any application private data. Specifically, port programs should be located in the `priv` directory. The `priv` directory of an application is found by a call to `code:priv_dir(AppName)`.
> - The boot script and relup files should be located in the `releases/Vsn` directory. `Vsn` is the release version found in the release resource file.
> - The Erlang runtime system executables are located in the `erts-EVsn/bin` directory.
> - The `releases` directory should also contain the `ReleaseFileName.rel` files, and new release packages are installed here.
> - The `bin` directory contains the top level Erlang executable program `erl`.

> Applications are not required to be located under the `$ROOTDIR/lib` directory. Accordingly, several installation directories may exist which contain different parts of a system. For example, the previous example could be extended as follows:

>     $SECOND_ROOT/.../SApp1-SAVsn1/ebin
>                                  /priv
>                     /SApp2-SAVsn2/ebin
>                                  /priv
>                     ...
>                     /SAppN-SAVsnN/ebin
>                                  /priv

>     $THIRD_ROOT/TApp1-TAVsn1/ebin
>                             /priv
>                /TApp2-TAVsn2/ebin
>                             /priv
>                ...
>                /TAppN-TAVsnN/ebin
>                             /priv

> The `$SECOND_ROOT` and `$THIRD_ROOT` are introduced as `variables` in the call to the `systools:make_script/2` function.

> #### 3.3.1 Disk-less and/or Read-Only Clients

> If a complete system consists of some disk-less and/or read-only client nodes, a `clients` directory should be added to the `$ROOTDIR` directory. By a read-only node we mean a node with a read-only file system.

> The `clients` directory should have one sub-directory per supported client node. The name of each client directory should be the name of the corresponding client node. As a minimum, each client directory should contain the `bin` and `releases` sub-directories. These directories are used to store information about installed releases and to appoint the current release to the client. Accordingly, the `$ROOTDIR` directory contains the following:

>     $ROOTDIR/...
>             /clients/ClientName1/bin
>                                 /releases/Vsn
>                     /ClientName2/bin
>                                 /releases/Vsn
>                     ...
>                     /ClientNameN/bin
>                                 /releases/Vsn

> This structure should be used if all clients are running the same type of Erlang machine. If there are clients running different types of Erlang machines, or on different operating systems, the `clients` directory could be divided into one sub-directory per type of Erlang machine. Alternatively, you can set up one `ROOTDIR` per type of machine. For each type, some of the directories specified for the `ROOTDIR` directory should be included:

>     $ROOTDIR/...
>             /clients/Type1/lib
>                           /erts-EVsn
>                           /bin
>                           /ClientName1/bin
>                                       /releases/Vsn
>                           /ClientName2/bin
>                                       /releases/Vsn
>                           ...
>                           /ClientNameN/bin
>                                       /releases/Vsn
>                     ...
>                     /TypeN/lib
>                           /erts-EVsn
>                           /bin
>                           ...

> With this structure, the root directory for clients of `Type1` is `$ROOTDIR/clients/Type1`.

> ### 3.4 Example

> Suppose we have a system called "test", which consists of the three applications: `snmp`, `kernel` and `stdlib`. The `snmp` application is described in the application resource file `snmp.app` as follows:

>     {application, snmp,
>      [{vsn, "10"},
>       {modules,
>        [{snmp_table, 2},
>         {snmp_map, 3},
>         {snmp_stuff,5}]},
>       {applications,
>        [stdlib,
>         kernel]},
>       {mod,
>        {snmp_stuff, [12,34]}}
>      ]}.

> | The resource file shown contains only a sub-set of the information available in the actual resource files. Refer to the Design Principles chapter, section Applications for a more detailed description of the contents of an application resource file.

> In the example shown, version "10" of `snmp` uses version 2 of `snmp_table`, version 3 of `snmp_map` an so on. It requires that `stdlib` and `kernel` are started before this application is started. It is started by evaluating the function `snmp_stuff:start(normal, [12,34])`. `snmp_stuff` is the SNMP application call-back module for the application complying with the behavior `application`.

> | We have used integer version numbers written as strings for the application version. In our further discussion we will simplify things by using integer version numbers. We will also assume that version N+1 is the successor of version N of a system component.

> The application resource file `stdlib.app` for `stdlib` version "6" contains the following:

>     {application, stdlib,
>      [{vsn, "6"},
>       {modules,
>        [{lists,2},
>         {dict,4},
>         {ordsets, 7}]},
>       {applications,
>        []},
>      ]}.

> | `stdlib` is a "code only" application and has no call-back module.

> Finally, the `kernel.app` file of the `kernel` application version "2" contains the following:

>     {application, kernel,
>      [{vsn, "2"},
>       {modules,
>        [{net_kernel, 3},
>         {auth, 3},
>         {rcp, 5}]},
>       {applications,
>        [stdlib]},
>       {mod,
>        {net_kernel,[]}}
>      ]}.

> We can now in the `test1.rel` file define release "5" of the "test" release in terms of these applications:

>     {release,
>      {"test", "5"},
>      {erts, "4.4"},
>      [{kernel, "2"},
>       {stdlib, "6"},
>       {snmp, "10"}
>      ]}.

> | This means that release "5" of the "test" system is built from `kernel` version "2", `stdlib` version "6". The release requires the Erlang runtime system "4.4".

> #### 3.4.1 Making the Start Script

> In the example shown, we have defined enough to be able to generate a system. We now have to generate a start script off-line which will be used when the system is loaded. We evaluate:

>     systools:make_script("test1")

> where `test1` refers to the `test1.rel` file.

> This command reads the `test1.rel` file and checks that all applications required for the release can be found and that all the modules which are required can be located and have the correct version numbers.

> All required application resource files and all required Erlang files must be located somewhere within the current code path, `{path, Path}`.

> If there were no errors, a start script called `test1.script` and a boot file called `test1.boot` are created. The latter is a binary version of the former, and is used when starting the system (e.g. by issuing the command `erl -boot test1`).

> #### 3.4.2 Changing an Application

> Suppose now that we make a change to `snmp` which results in new versions of the modules `snmp_map` and `snmp_stuff`. This is specified as follows in a new version of `snmp.app`:

>     {application, snmp,
>      [{vsn,"11"},
>       {modules,
>        [{snmp_table, 2},
>         {snmp_map, 4},
>         {snmp_stuff,6}]},
>       {applications,
>        [stdlib,
>         kernel]},
>       {mod,
>        {snmp_stuff, [12,34]}}
>      ]}.

> | We have changed the two modules `snmp_map` and `snmp_stuff`. Everything else remains the same.

> We can now define a new release of the system in the file `test2.rel` as follows:

>     {release,
>      {"test","6"},
>      {erts, "4.4"},
>      [{kernel, "2"},
>       {stdlib, "6"},
>       {snmp, "11"}
>      ]}.

> As before we generate the `test2.script` and `test2.boot` file by calling

>     systools:make_script("test2").

> So far we have version "5" and "6" of the "test" release defined in the `test1.rel` and `test2.rel` files, and the generated script and boot files `test1.script`, `test1.boot`, `test2.script`, and `test2.boot`. In our example two versions of the "test" release only differ in the contents of the `snmp` application. In order to be able to update from version "5" to version "6" of the "test" release, we have to provide a specification of the upgrade of the `snmp` application in the form of an application upgrade file `snmp.appup`.

> The contents of the `snmp.appup` file is as follows:

>     {"11",
>      [{"10", [{update, snmp_map, soft, soft_purge, soft_purge, []},
>               {update, snmp_stuff, soft, soft_purge, soft_purge, []}]}],

>      [{"10", [{update, snmp_map, soft, soft_purge, soft_purge, []},
>               {update, snmp_stuff, soft, soft_purge, soft_purge, []}]}]
>     }.

> The `snmp` application is upgraded by changing code for the `snmp_map` and `snmp_stuff` modules. It is downgraded by changing code for the same two modules.

> Since only the `snmp` application was changed between version "5" and version "6" of the "test" release, no `.appup` files are needed for the other applications.

> In order to finish the specification of the upgrade of the complete "test" release, a release upgrade file, `relup`, has to be created (`relup` is not a file suffix; the complete name of the file is `relup`). The `relup` file is created by evaluating:

>     systools:make_relup("test2", ["test1"], ["test1"]).

> Here the first argument is name of the `.rel` file we upgrade to or downgrade from. The second and third arguments are lists of `.rel` files, specifying releases to upgrade from, and downgrade to, respectively.

> A `relup` file contains low-level code change instructions for the whole release, based on all application `.appup` files.

> #### 3.4.3 Making a Release Package

> Next, we want to generate a release package which can be installed in the target system. After evaluating `make_script/1` and `make_relup/3` as described above, we do it by evaluating

>     systools:make_tar("test2").

> A release package file, named `test2.tar.gz` is generated. The release package file may be installed in a target system by using the release_handler.

> In this example, the release package file will contain all applications of version "6" of the "test" release, and also a `releases` directory with the following contents:

>     $ROOTDIR/releases/test2.rel
>                      /6/relup
>                        /start.boot

> where `start.boot` is a copy of the original `test2.boot`.

Copyright © 1991-2003 Ericsson Utvecklings AB