All-in-one Executables

It is possible to embed saved-states into an executable. Together with static linking, this gives an all-in-one executable, an executable that does not depend on external SICStus files.

In the simplest case, creating an all-in-one executable main.exe from a saved state main.sav can be done with a command like

     % spld --output=main.exe --static main.sav
     

This will automatically embed the saved state, any foreign resources needed by the saved state as well the SICStus run-time and its run-time saved state.

The keys to this feature are:

Data resources are added by specifying their internal name and the path to a file as part of the comma separated list of resources passed with the spld option --resources. Each data resource is specified as file=name where file is the path to the file containing the data (it must exist during the call to spld) and name is the name used to access the content of file during run-time. A typical choice of name would be the base name, i.e. without directories, of file, preceded by a slash (/). name should begin with a slash (/) and look like an ordinary lowercase file path made up of /-separated, non-empty, names consisting of a to z, underscore (_, period (.), and digits.

Typically, you would use spld --main=restore, which will automatically restore the first .sav argument. To manually restore an embedded saved-state you should use the syntax URL:x-sicstus-resource:name, e.g. SP_restore("URL:x-sicstus-resource:/main.sav").

An example will make this clearer. Suppose we create a run-time system that consists of a single file main.pl that looks like:

                                  
% main.pl
:- use_module(library(system)). :- use_module(library(clpfd)). % This will be called when the application starts: user:runtime_entry(start) :- %% You may consider putting some other code here... write('hello world'),nl, write('Getting host name:'),nl, host_name(HostName), % from system write(HostName),nl, ( all_different([3,9]) -> % from clpfd write('3 != 9'),nl ; otherwise -> write('3 = 9!?'),nl ).

Then create the saved-state main.sav, which will contain the compiled code of main.pl as well as the Prolog code of library(system) and library(clpfd) and other Prolog libraries needed by library(clpfd).

     % sicstus -i -f
     
     SICStus 3.11.2 ...
     Licensed to SICS
     | ?- compile(main).
     % compiling .../main.pl...
     % ... loading several library modules
     | ?- save_program('main.sav').
     % .../main.sav created in 201 msec
     
     | ?- halt.
     

Finally, tell spld to build an executable statically linked with the SICStus run-time and the foreign resources needed by library(system) and library(clpfd). Also, embed the Prolog run-time saved-state and the application specific saved-state just created. Note that the random foreign resource is needed since it is used by library(clpfd).

As noted above, it is possible to build the all-in-one executable with the command line

     % spld --output=main.exe --static main.sav
     
but for completeness the example below uses all options as if no options were added automatically.

The example is using Cygwin bash (http://www.cygwin.com) under Windows but would look much the same on other platforms. The command should be given on a single line; it is broken up here for better layout.

     % spld
       --output=main.exe
       --static
       --embed-rt-sav
       --main=restore
       --resources=main.sav=/main.sav,clpfd,system,random
     

The arguments are as follows:

--output=main.exe
This tells spld where to put the resulting executable.
--static
Link statically with the SICStus run-time and foreign resources (system and clpfd in this case).
--embed-rt-sav
This option embeds the SICStus run-time .sav file (sprt.sav). This option is not needed since it is added automatically by --static.
--main=restore
Start the application by restoring the saved-state and calling user:runtime_entry(start). This is not strictly needed in the above example since it is the default if any file with extension .sav or a data resource with a name with extension .sav is specified.
--resources=...
This is followed by comma-separated resource specifications:

main.sav=/main.sav
This tells spld to make the content (at the time spld is invoked) of the file main.sav available at run-time in a data resource named /main.sav. That is, the data resource name corresponding to "URL:x-sicstus-resource:/main.sav".

Alternatively, spld can create a default data resource specification when passed a .sav file argument and the option --embed-sav-file (which is the default with --static).

clpfd
system
random
These tell spld to link with the foreign resources (that is, C-code) associated with library(system), library(clpfd) and library(random). Since --static was specified the static versions of these foreign resources will be used.

Alternatively, spld can extract the information about the required foreign resources from the saved-state (main.sav). This feature is enabled by adding the option --resources-from-sav (which is the default with --static). Using --resources-from-sav instead of an explicit list of foreign resources is preferred since it is hard to know what foreign resources are used by the SICStus libraries.

Since both --embed-sav-file and --resources-from-sav are the default when --static is used the example can be built simply by doing

          % spld --output=main.exe --static main.sav
          

Finally, we may run this executable on any machine, even if SICStus is not installed:

     bash-2.04$ ./main.exe
     hello world
     Getting host name:
     EOWYN
     3 != 9
     bash-2.04$