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 runtime and its runtime 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 runtime. 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 runtime 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.3.5 … 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 runtime and the foreign resources needed by
library(random)
and library(clpfd)
. Also, embed the Prolog
runtime 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:
This tells spld
where to put the resulting executable.
Link statically with the SICStus runtime and foreign resources
(clpfd
, timeout
, and random
in this case).
This option embeds the SICStus runtime ‘.sav’ file (sprt.sav). This option is not needed since it is added automatically by --static.
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 where the extension is ‘.sav’ is
specified.
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 runtime 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
timeout
random
These tell spld
to link with the foreign resources (that
is, C-code) associated with
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$