Is there a way to create portable subset of Prolog executable and library files that I can include into my application distributive, so that I can deploy Prolog and launch it’s executable with my prolog source? Or just some portable distribution that can be just xcopied into target directory and run without any additional configuration?
I’ve read manual (SWI-Prolog -- Deployment options), it suggests user installs complete SWI Prolog into his system. I’d rather bring all needed files in my own installer. Is that possible without too much work?
Next, add the DLLs needed to load myexe.exe to the distribution. You can find these using win_process_modules/1. You can also omit the --foreign=save, load your program and use win_process_modules/1 to find all DLLs used. That makes the system start a little faster.
If SWI-Prolog is embedded into C code this is more or less the same story, but do not use --stand-alone and call PL_initialise() using -x, state.
Creating saved states from a Prolog file comes with some limitations. Notably all code must be included, which implies you must explicitly import all required libraries or at least the system must be able to find all calls into these libraries. Running code cannot simply use :- goal., but must use one of the initialization/1 or initialization/2 directives.
On other platforms the idea is the same, but how to find the required shared objects and how to make the main program find them depends on the OS.
Current versions also allow creating a fully static swipl.exe with required extensions built-in, but that requires building the system yourself from source and some tweaking depending on the platform. Done right, you can get just about any application into a single executable file.
I’ve made my executable. While trying to run it I get following errors for many foreign libs loaded by prolog libraries. It is strange, because I run my executable from prolog bin directory where all binaries present.
ERROR: c:/alex/bin/swipl/library/filesex.pl:85: Initialization goal raised exception:
ERROR: The specified module could not be found.
ERROR: In:
ERROR: [18] throw(error(shared_object(open,‘The specified module could not be found.\r\n’),context(…,_5128)))
ERROR: [16]
ERROR: [15] with_mutex(‘$foreign’,load_foreign_library(foreign(files),files_ex,))
ERROR: [11] ‘$run_init_goal’(‘$syspreds’:use_foreign_library_noi(…)) at c:/alex/bin/swipl/boot/init.pl:823
ERROR: [10] catch(system:‘$run_init_goal’(…),_5262,system:‘$initialization_error’(_5284,…,…)) at c:/alex/bin/swipl/boot/init.pl:563
ERROR: [9] catch_with_backtrace(system:‘$run_init_goal’(…),_5320,system:‘$initialization_error’(_5342,…,…)) at c:/alex/bin/swipl/boot/init.pl:643
ERROR:
ERROR: Note: some frames are missing due to last-call optimization.
ERROR: Re-run your program in debug mode (:- debug.) to get more detail.
Figured it out. It seems that --foreign=save flag is not working properly. Judging by the size of the executable it adds binaries to the exe file, but upon starting it fail to extract it from resources of saved state.
I removed that flag and it worked. The only thing was that writef/1 predicate was missing somehow.
had to explicitly use library(writef).