This is version 3.0 of the support routines for "SAE" (Stand Alone Erlang) - with this you can make small stand-alone Erlang applications which run quickly from the Unix command line prompt (see below for measurements). With SAE you can distribute complete applications in a very small number of files. SAE is currently work in progress and is not supported. This document describes how to put together SAE for the Linux version of otp_src_P8A-20011007-SNAPSHOT. Have fun, /Joe (joe.armstrong+nospam@telia.com)
The basic Erlang run-time kit now requires seven files and a total of 3.5 Mbytes of storage, these files are:
To build these files follow these instructions.
These seven files contain the logical equivalent of about 500 files in the distributed system. Having one .lib file per library makes system administration a lot easier :-)
Firstly you need to distribute the 7 files mentioned in the introduction. If you have a small application, composed of a few files, then you can build the application as follows: > ecc F1.erl F2.erl .... > elink -o Exec -m F1 F2 F3 ... -s Mod Func -args ...This builds the application Exe. Then you distribute this (single) file. If you have several inter-related applications which use a common set of library routines then you can build a private library, using ml_lib:pack/3 - for example, evaluating: mk_lib:pack_library("joe.lib", "/home/joe/src/apps/src", "/home/joe/src/apps/include"). makes a private library called joe.lib from all the BEAM code in /home/joe/src/apps/src and all the .hrl files in /home/joe/src/apps/include. This library should be installed in the same directory as the directory containing stdlib.lib
All .lib files must be placed in the library directory The library directory is defined to be the first directory found which contains the file stdlib.lib. The following directories are searched:
This is done by the function demand_prim:local_lib_dir/0. The motivation for this search order is as follows:
The demand code loader will only demand load code from the library directory.
The SAE distribution consists of one large executable (beam_evm) this is the "Erlang engine". All stand-along executable have the following format: #!/usr/bin/env beam_evm :NNNNN <<binary data>> The first line #!/usr/bin/env beam_evm locates the Erlang executable. The second line :NNNNN is an integer representing the size of the binary data <<binary data>> which follows. When beam_evm starts it gets passed the file name of the executable, it then reads NNNNN and the binary data which follows. The binary data is an Erlang binary (created by the BIF term_to_binary) - beam_evm then spawns a parallel process which evaluates ring0.start(Env, Args) - where Env is the binary which was contained in the executable file and Args comes from the command in arguments. The version of sae-3.0/src/ring0.erl should replace the version found in the distribution at otp_src_P8A-20011007-SNAPSHOT/erts/sae/src/ring0.erl ring0.erl is pre-loaded - in fact it is the only Erlang code that needs to be pre-loaded. Here is ring0.erl.
The executable is created by the program elink.erl, the following lines of code in taken from elink.erl are used to create the start term Ring0term - this term must agree with the term structure used in ring0.erl.
Demand code loading works as follows:
Note that all include files (Lib/include/*.hrl) are also added to the .lib files. These are needed for compiling modules which contain: -include_lib("kernel/include/file.hrl"). directives. A hacked version of epp (called epp_hacked) is used which correctly retrieves the appropriate include file from the .lib archives as necessary.
These are the instruction for building SAE on my home machine in the directory /home/joe. 1) Fetch the latest system http://www.erlang.org/download/otp_src_R8B-0.tar.gz 2) Unpack the distribution in you home directory. this creates the top-level directory /home/joe/otp_src_P8A-20011007-SNAPSHOT. Configure and make. > cd /home/joe > gunzip zcat otp_src_R8B-0.tar.gz | tar -xvf - > cd otp_src_R8B-20011015-SNAPSHOT > ./configure > make %% drink a few cups of coffee chat to mates etc. - wish I had %% a 4GHz machine .... 3) Set a path to locate the correct versions of erl and erlc: > export PATH=/home/joe/otp_src_R8B-20011015-SNAPSHOT/bin:$PATH 4) Unpack sae-30.tgz and copy the version of ring0.erl in the package to the distribution. This replaces the version of ring0 in the distribution with a better one :-). > cp ring0.erl /home/joe/otp_src_R8B-20011015-SNAPSHOT/erts/sae/src/ring0.erl 5) Build sae. > export ERL_TOP=/home/joe/otp_src_R8B-20011015-SNAPSHOT > cd $ERL_TOP/erts > make sae 6) Copy the virtual machine to somewhere in your path: > cp $ERL_TOP/bin/i686-pc-linux-gnu/beam_evm ~/bin 6) Strip it > cd ~/bin > strip beam_evm This reduces the size of beam_evm from 1785363 bytes to 624504 bytes. 7) Build the support tools > cd sae-3.0/src > make This will build the libraries into sae-3.0/dist. 8) set an environment variable so you can find the libraries. > export ERL_SAE_LIB=/home/joe/sae-3.0/dist" 9) Test it. > cd sae-3.0/examples > make > ./test_demand 40 Link args=["1","2","3"] factorial 40=815915283247897734345611269596115894272000000000
Here is a complete example which is taken from the examples directory in the distribution.
To compile and link we give the following commands: > ecc test_demand.erl > elink -E -o test_demand -m test_demand -s test_demand main
Here are a few figures for hello.erl (hello world) which is in the examples directory. > time ../dist/ecc hello.erl "hello.erl" {ok,hello} 0.70user 0.10system 0:00.79 100%CPU > time ../dist/elink -d -o hello -m hello -s hello main 0.11user 0.02system 0:00.14elapsed 92%CPU > time ./hello 'hello world' 0.01user 0.01system 0:00.02elapsed 100%CPU > ls -l hello -rwxr-xr-x 1 joe staff 396 Oct 17 14:59 hello The next test is for ecat.erl (See the examples directory for code) - this is a mini-version of the Unix "cat" utility. > time ./ecat <../dist/stdlib.lib >aa 0.02user 0.05system 0:00.07elapsed 95%CPU > wc ../dist/stdlib.lib ecat 4770 26689 1124078 ../dist/stdlib.lib 18 106 4429 ecat 4788 26795 1128507 total> ls -l ../dist/stdlib.lib This is fast enough (0.07 sec, on my 433MHz Celeron ) and small enough (4429 bytes) to be useful for shell scripts, cgi stuff etc.
The use of .lib files makes it possible to write a "library manager" (somewhat like the red-hat package manager). I am working on an extension to Erlang, whereby modules would begin with a lib declaration. The standard module lists, would begin: -module(lists). -lib(stdlib). ... Meaning that lists belongs to stdlib (naturally enough). With proper use of a lib system we could require that "module names are unique to within a library name but not globaly unique" - which provides a partically solution to the "module namespace pollution problem". This facility is planned in a future release of sae. It would also be very nice to see this stuff ported into windows - volunteers ... |