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:
If the application needs foreign resources (predicates
written in C code), as used for example by library(timeout)
and
library(clpfd)
, these foreign resources can be linked
statically with the application as well.
The remaining component is the Prolog code itself; see the next item.
An application needs two saved-states:
sprt.sav
).
This is added automatically when spld is invoked with the --static (or -S) option unless the spld-option --no-embed-rt-sav is specified. It can also be added explicitly with the option --embed-rt-sav.
This saved-state is typically created by loading all
application code using compile/1
and then creating the
saved-state with save_program/2
.
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(random)). :- 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 a random value:'),nl, random(1,10,R), % from random write(R),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(random)
and library(clpfd)
and other Prolog
libraries needed by library(clpfd)
:
% sicstus -i -f SICStus 4.1.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(random)
and library(clpfd)
. Also, embed the Prolog
run-time saved-state and the application specific
saved-state just created. Note that the ‘timeout’ 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,timeout,random
The arguments are as follows:
clpfd
, timeout
, and random
in this case).
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 where the extension is ‘.sav’ is
specified.
main.sav=/main.sav
"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
timeout
random
library(clpfd)
, library(timeout)
, 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 a random value: 4 3 != 9 bash-2.04$