Qsave_program -

I’m using: SWI-Prolog version 8.11

I want the code to:
Loaded all prolog and program functions as expected
qsave_program(‘willie.p’)
halt to exit
swipl -x willie.p

image

How to go looking into this such as turning on options to get more information, … etc?

Nan

Hard to tell. I’d first try a trivial hello world like example. If that doesn’t work it is probably possible to create a reproducible case and figure out why. If you use initialziation/1 to make your program work, remove that. Then hopefully the program will load and you can start the main goal using the debugger.

HI Jan,

Thank you very much for your valuable input. I tried removing the initialization(cp_server, main) (I am using ClioPatria framework). It loads without issue, and issue cp_server at the prlog prompt and it works.

through debug, it seems stops at the

	    http_server(http_dispatch,
    		    [ port(Port),
    		      workers(Workers)
    		    | HTTPOptions
    		    ]),

Then I tested with ClioPatria - nothing added. The run.pl looks like:

% @HASHBANG@@SWIPL@ @LOADOPTIONS@

:- initialization(cp_server, main).

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
This file provides a skeleton startup file.  It can be localized by running

    % ./configure			(Unix)
    % Double-clicking win-config.exe	(Windows)

After  that,  the  system  may  be  customized  by  copying  or  linking
customization  files  from  config-available    to  config-enabled.  See
config-enabled/README.txt for details.

To run the system, do one of the following:

    * Running for development
      Run ./run.pl (Unix) or open run.pl by double clicking it (Windows)

    * Running as Unix daemon (service)
      See daemon.pl
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

% Setup search path for cliopatria. We add  both a relative and absolute
% path. The absolute path allow us to  start in any directory, while the
% relative one ensures that the system remains working when installed on
% a device that may be mounted on a different location.

add_relative_search_path(Alias, Abs) :-
	is_absolute_file_name(Abs), !,
	prolog_load_context(file, Here),
	relative_file_name(Abs, Here, Rel),
	assertz(user:file_search_path(Alias, Rel)).
add_relative_search_path(Alias, Rel) :-
	assertz(user:file_search_path(Alias, Rel)).

%file_search_path(cliopatria, '@CLIOPATRIA@').
%:- add_relative_search_path(cliopatria, '@CLIOPATRIA@').

file_search_path(cliopatria, '/Project/CP/ClioPatria').
:- add_relative_search_path(cliopatria, '/Project/CP/ClioPatria').

		 /*******************************
		 *	      LOAD CODE		*
		 *******************************/

% Use the ClioPatria help system.  May   be  commented to disable online
% help on the source-code.
:- use_module(cliopatria('applications/help/load')).

% Load ClioPatria itself.  Better keep this line.
:- use_module(cliopatria(cliopatria)).

From DOS, run:
swipl-win -g cp_server run.pl.
Then
qsave_program(‘cp.p’).
halt.

Now at DOS,
swipl-win -x cp.p

I will get the error window popup.

Your advise to get more information is appreciated. Sorry our code size is pretty large, plus half the code is done while learning prolog especially the part of managing modules. the cross reference is pretty messy. So that’s all I can dig.

Thanks as always, You are the best.

By the way, the ultimate goal is to compile and qsave cliopatria with our code to a unix daemon service. (I am on windows simply because we are using eclipse with PDT - seems more stable than the Linux counter part).

Nan

Bit dubious to use -g cp_server as there is already an initialization. With current ClioPatria and SWI-Prolog 8.1.12, this works fine:

  • Configure ClioPatria (using configure (non-windows) or win-config.exe (windows)
  • Run in the directory where you setup ClioPatria:
    • swipl -o cp -c run.pl (add some .exe for Windows)
  • Start as ./cp (cp.exe on Windows)

On Windows you need to copy the dlls used from SWI-Prolog’s bin directory to the location of the .exe or, possibly easier, add the SWI-Prolog bin directory to %PATH%.

The question is why you would like to make an executable? Just make sure Prolog is installed and start run.pl is way easier and the few seconds startup time cannot be a big reason not to.

Upgaded to 8.12.

swipl -o cp -c run.pl works but qsave_program/1 still fail.

-o/-c - here are the steps:

E:\Project\CP\ClioPatria>swipl -o cp1.exe -c run.pl
% Updating GIT version stamps in the background.

E:\Project\CP\ClioPatria>cp1
% Updating GIT version stamps in the background.
% Started server at http://localhost:3030/
1 ?- halt.

But qsave_program/2 still fails. Here are the command line steps:

E:\Project\CP\ClioPatria>swipl run.pl
% Updating GIT version stamps in the background.
% Started server at http://localhost:3030/
1 ?- qsave_program(‘cp.exe’).
true.

2 ?- halt.

E:\Project\CP\ClioPatria>cp
Now the error message window appears.

The two approaches generate different-sized exe files with our app:

  1. -o/-c - it is about 1.3M
  2. qsave_program/1 - it is 13M.
    Only data after starting the program is rdf_db:rdf/4. I didn’t volatile that.

One observation though:
-o/-c generated exe file is about the same size as that of without the initialization(cp_server, main) in our app.

We are happy that -o/-c works but there is another issue: it seems not including all the predicates in saved state/exe file. If I rename the file_search_path of the source pl files, then run the exe file, it reports “library(coc/boot/ip_boot_app))” does not exist" for example. What to do to force a file to be included?

Now the reasons we want to qsave/qlf:

  1. Protection. We understand that this is not a fool-proof protection but at least make it a bit harder for hackers.
  2. Maintenance. with many source files distributed, some curious tech/support will tempt to tinker/explore them. With one fat finger, it will cause trouble, and it is not so easy to identify the cause in prolog - especially with low-level support engineers - that is our experience.

Loading speed is not our concern at the moment. We are not thinking an executable either but a qsave state with -x option to start the program. So far in my example, I didn’t specify the stand_alone=false.

Thanks, Jan, for your support.

If things are going well with us, you and your team deserve a fair share of credit. Look for news…(smily face)…

Nan

That is to be expected: -c doesn’t start the application. You should get about the same if you do swipl -l run.pl and then save. Still, the latter picks additional files to support interactive mode such as the color modules.

It does not load the config files. See cp_server/0. this might indicate the issue is on one of the config files loaded. If the -l works, you can easily load part of the config and see where the problem is. Not that you can use map=somefile for '-cormap(somefile)forqsave_program/2` to find out what goes into the state.

Finally, rdf/4 is a foreign predicate. It is never saved, but re-attached as the state starts (provided the required DLL is present).

Hi Jan,

I have managed to have created a qsave state that is working. Thank you very much for your valuable help.

Run into another issue with protect_static_code -

Once set it to true, -c/-o generate a state much smaller in size without error. When run the state, and got:

ERROR: e:/project/app/ip_run.pl:71: Initialization goal raised exception:
ERROR: clause/2: No permission to access private_procedure error:has_type/2' ERROR: c:/program files/swipl/library/sandbox.pl:473: Initialization goal raised exception: ERROR: clause/3: No permission to access private_proceduresandbox:safe_primitive/1’

Any idea?

Possibly you used the protect_static_code flag? That won’t play with library(sandbox).