Ann: SWI-Prolog 9.3.30

Dear SWI-Prolog user,

SWI-Prolog 9.3.30 is ready for download. This fixes notably some
issues in the SDL based xpce.

IMO the most annoying issue left is that the SWI-Prolog.app on MacOS
keeps asking permission to access your files. One way around is to
add /Applications/SWI-Prolog.app/Contents/MacOS to your $PATH
and run Prolog from a terminal as swipl-win [arg...].

The real solution seems to be to split the package into a framework
and application and properly sign the whole thing. If anyone has
the resources to sort that out, please help. I do have an Apple
account that should allow for the signing.

Please keep reporting other issues, so we can start planning to
build a stable 9.4.

Enjoy --- Jan

SWI-Prolog Changelog since version 9.3.29

  • CLEANUP: Avoid unused function warning when compiling for Windows
    without thraeds.

  • FIXED: #1381 building single threaded version for Windows.

  • TEST: term_hash/2,4: WASM produces different results due to 32
    bit limit.

  • FIXED: Starting interactive mode failed if the history cannot be
    initialised. This prevents running Prolog interactively if there is no
    HOME directory or the config directories and files cannot be created.

Package xpce

  • FIXED: Windows: Avoid that a popup causes loss of focus. Popups no
    longer grab the system focus, but instead use xpce’s focus notion to
    forward events to the popup.

  • FIXED: More careful display handling.

  • ADDED: Epilog console: make DEL key send \e[3~. This provides
    forward delete on Linux, but not on Windows. Probably the libedit
    port needs additional patching.

  • FIXED: Bind any key >= 128 to ->insert_self

  • FIXED: Allow entering on Italian keyboards using Alt-gr.
    PceEmacs interpreted these as Alt-, moving over a clause.

2 Likes

One thing seen under MSYS2: The tests for the saved states seem to have problems finding the foreign dlls. Example session (not important, but for the records):

$ cd swipl-devel/build
$ cmake -DINSTALL_TESTS=ON -DMSYS2=1 -DCMAKE_INSTALL_PATH=/home/matthias/swipl ..
$ ninja
$ ninja install
$ cd ~/swipl/bin
$ ./swipl
?- test_installation([packages=false]). % works!
?- halt.
$ cd ~/swipl
$ bin/swipl
?- test_installation([packages=false]). % fails in saved states
?- halt.
$ cp lib/swipl/lib/x64-win64/files.dll .
$ bin/swipl
?- test_installation([packages=false]). % works!

If I run the exe file from the saved state, it also reports having trouble finding the foreign files.dll. I guess I need to try to fix the problem in boot/build_home.pl (?)

(note that under MSYS2, the dlls are not copied into the folder of the executable, but in lib/swipl/lib/x64-win64)

1 Like

The relation between foreign extensions and saved states varies between platforms. On quite a few you have to do something before that works. In this case we could consider using win_add_dll_directory/1 (if not already done in Prolog or MSYS?)

In general, saved states are there primarily to create executables that can work without Prolog being installed. Part of the job is typically to construct a runtime environment that contains all the required DLLs/…

Some people also use it for the faster startup times. Most of that can also be achieved by compiling the application to .qlf files. These use the same format as saved states. Still, loading multiple .qlf files remains slower than loading a single state due to the improved sharing and reduced file system access.

It obviously has to do with win_add_dll_directory/1, I was wondering if build_home.pl is the right place to try a fix.

No. That file is only used for running the system in the build environment. It is not installed. The most obvious location is library(shlib), which takes care of loading foreign extensions at runtime.

ChatGPT says this:

Short answer: it’s TCC (Transparency, Consent, and Control)—not the sandbox.

Even a non-sandboxed app on macOS 10.15+ hits privacy gates for certain locations. When your app touches protected paths (e.g., ~/Desktop, ~/Documents, ~/Downloads, iCloud Drive, external/network volumes, some Library subfolders), macOS prompts the user to allow access. This is independent of the App Sandbox entitlement.

This seems correct. Just make sure you work in a directory outside these avoid the annoying confirmation dialogs. I’ll change the default start directory to ~/Prolog.

1 Like

I still have trouble with the saved states… After installation of the “normal” swipl for Windows, 9.3.30 (no MSYS2 or so, the “official swipl”), I tried:

C:\Users\matth\Documents\Prolog>notepad plain.pl
(insert some simple prolog code, with echo_true/0)
C:\Users\matth\Documents\Prolog>"c:\Program Files\swipl\bin\swipl.exe" -o state.exe -g echo_true -c plain.pl
C:\Users\matth\Documents\Prolog>.\state.exe
(complains that libswipl.dll is missing, ok, makes sense)
C:\Users\matth\Documents\Prolog>copy "\Program Files\swipl\bin\libswipl.dll" .
C:\Users\matth\Documents\Prolog>copy "\Program Files\swipl\bin\libgcc_s_seh-1.dll" .
C:\Users\matth\Documents\Prolog>copy "\Program Files\swipl\bin\libwinpthread-1.dll" .
C:\Users\matth\Documents\Prolog>copy "\Program Files\swipl\bin\libgmp-10.dll" .
C:\Users\matth\Documents\Prolog>copy "\Program Files\swipl\bin\zlib1.dll" .
C:\Users\matth\Documents\Prolog>.\state.exe
(works!)

Next step is to try if this can be done automatically (foreign=copy):

C:\Users\matth\Documents\Prolog>del *.dll
C:\Users\matth\Documents\Prolog>"c:\Program Files\swipl\bin\swipl.exe" -o state.exe -g echo_true -c plain.pl --foreign=copy
ERROR: [Thread main] architecture_shlib(copy) `foreign(files)' does not exist

Or foreign=save?

C:\Users\matth\Documents\Prolog>"c:\Program Files\swipl\bin\swipl.exe" -o state.exe -g echo_true -c plain.pl --foreign=save
(no complaints, but state.exe is way too small)
C:\Users\matth\Documents\Prolog>.\state.exe
(complains that libswipl.dll is missing)
C:\Users\matth\Documents\Prolog>copy "\Program Files\swipl\bin\libswipl.dll" .
C:\Users\matth\Documents\Prolog>copy "\Program Files\swipl\bin\libgcc_s_seh-1.dll" .
C:\Users\matth\Documents\Prolog>copy "\Program Files\swipl\bin\libwinpthread-1.dll" .
C:\Users\matth\Documents\Prolog>copy "\Program Files\swipl\bin\libgmp-10.dll" .
C:\Users\matth\Documents\Prolog>copy "\Program Files\swipl\bin\zlib1.dll" .
C:\Users\matth\Documents\Prolog>.\state.exe
ERROR: [Thread main] c:/program files/swipl/library/ext/clib/filesex.pl:91: Initialization goal raised exception: (etc., basically, that files.dll is missing)
C:\Users\matth\Documents\Prolog>copy "\Program Files\swipl\bin\files.dll" .
(same error, so this does not fix the problem)

This should work, notably on Windows. Looks like a bug. I’m at the ICLP conference, free of Windows :slight_smile:

Maybe just a small thing. qsave_program/2 works as expected (just a warning about a choicepoint):

?- [plain].
?- qsave_program('state.exe', [goal(echo_true), foreign(copy)]).
% Disabled autoloading (loaded 73 files)
% Disabled autoloading (loaded 9 files)
% Disabled autoloading (loaded 0 files)
% Copying c:/program files/swipl/bin/swipl.exe to .
% Copying c:/program files/swipl/bin/libswipl.dll to .
% Copying c:/program files/swipl/bin/libgcc_s_seh-1.dll to .
% Copying c:/program files/swipl/bin/libwinpthread-1.dll to .
% Copying c:/program files/swipl/bin/libgmp-10.dll to .
% Copying c:/program files/swipl/bin/zlib1.dll to .
Warning: qsave_program/2 succeeded with a choice point
true.
?- halt.

C:\Users\matth\Documents\Prolog>del swipl.exe

C:\Users\matth\Documents\Prolog>state
hallo

Note that swipl.exe isn’t actually needed to run the state.

foreign(save) and stand_alone(true) don’t work, though.

Thanks. I fear something got broken with the changes of the initialization of the system to support the new GUI :(. Probably the foreign search path is not set up correctly.

That anyway only deals with foreign extensions. The dlls to start the executable must be installed in a way that the OS can deal with it as otherwise the executable cannot start. For Windows, copy is the preferred.route.

? It is stand alone, no? AFAIK that is the default on Windows as creating a state as we do on Unix using a #! script does not work.

Back on MSYS2 again. Let’s say, for reasons not yet fully understood :roll_eyes:, win_process_modules/1 returns one dll with a UNC path,

2 ?- use_module(library(process)).
true.

3 ?- win_process_modules(_DLLs), member(DLL, _DLLs).
DLL = 'c:/msys64/home/matth/swipl/bin/swipl.exe' ;
DLL = 'c:/windows/system32/ntdll.dll' ;
DLL = 'c:/windows/system32/kernel32.dll' ;
DLL = 'c:/windows/system32/kernelbase.dll' ;
DLL = 'c:/windows/system32/ucrtbase.dll' ;
DLL = 'c:/msys64/home/matth/swipl/bin/libswipl.dll' ;
DLL = 'c:/windows/system32/advapi32.dll' ;
...
DLL = 'c:/windows/system32/imm32.dll' ;
DLL = '//?/c:/msys64/home/matth/swipl/lib/swipl/lib/x64-win64/process.dll'. 

That is not recognized by prolog_dll/1 in qsave.pl, so it is not copied. I can fix it with an extra same_file/2:

prolog_dll(DLL) :-
    file_base_name(DLL, File),
    absolute_file_name(foreign(File), Abs, [ solutions(all) ]),
    same_file(DLL, Abs),
    !.

I have also seen these UNC paths in the new SDL libraries under the “normal” Windows version of swipl.

1 Like

swipl-win builds on MSYS2 after having installed SDL3, SDL3-image, pango, and cairo, but I think it also needs libedit*. The latter might be added as a strict dependency during cmake.

*which isn’t available on MSYS2, at least not as a windows native version, i.e. mingw-w64-ucrt-x86_64-libedit isn’t there. There is a mingw-w64-ucrt-x86_64-wineditline, but this is an emulator of readline (?), see GitHub - ptosco/wineditline: An EditLine API implementation for the native Windows Console

Two more things, and the mistake is not obvious to me, so I just report them: I typically use GitHub - JanWielemaker/environ: Tutorial SWI-Prolog pack to test if compilation of binary packs works. But I need to do two extra steps on MSYS2:

pack_install(environ).

1- Error in PL_register_foreign(“environ”, 1, pl_environ, 0), expected ‘pl_function_t’ {aka ‘long long unsigned int (*)(void)’} but argument is of type ‘foreign_t (*)(term_t)’ {aka ‘long long unsigned int (*)(long long unsigned int)’}. I can fix this in a dubiuos way by casting to void*,

PL_register_foreign("environ", 1, (void*) pl_environ, 0);

but I guess that shouldn’t be necessary.

2- Then I type pack_rebuild(environ), but I need to restart swipl before being able to load the module. Or, alternatively, win_add_dll_directory('C:/msys64/home/matth/.local/share/swi-prolog/pack/environ/lib/x64-win64'). So I guess pack_rebuild does not add the new dll directory to the search path.

Edit: A PR for problem #1 is on the way, was a C11 standard issue.

That is a bit of a nasty story. Libedit does not exist for native Windows. I created a port that runs on Windows consoles and the xpce based Epilog consoles. You find that at GitHub - SWI-Prolog/winlibedit: Windows port for BSD libedit (win32 branch).

There are also GNU-Readline based (very) partial emulations of libedit, but these are unsuitable for SWI-Prolog.

The above provides uniform commandline editing for Unix-based systems and Windows on the native terminal/console and inside the SWI-Prolog Epilog consoles.

Right. Fixed in SWI-Prolog.h. That should make the code work on the most recent C standards, although the story is complicated. In the old days we could define the type

 foreign_t (*func)()

for a pointer to a function that returns foreign_t, but has unspecified arguments. Next, we could cast this to e.g. foreign_t (*func)(term_t, term_t) and call it. But, modern C standards no longer allow for the first type :frowning: So, all we can do is pass the function pointer as void*. Unfortunately the recent standards do not allow casting void* to a function pointer :frowning: Well, most do. For now we rely on that. If that fails we can use the common trick to re-interpret
a value as of being a different type using a union, e.g.

typedef union { void *anon; foreign_t (*func)(term_t, term_t); } cvt;

then fill the void* and read it as a function pointer. That seems even more dubious to me (but it will keep pedantic compilers silent). I think the idea is that C would allow for supporting hardware where function and data pointers are distinct things. I’m not sure though. We’ll see how it evolves. Surely there are more applications around with similar demands, so there will be some solution :slight_smile:

Hi Jan

Firstly, congratulations on winning the Alain Colmerauer Prize. Very much deserved and heartwarming to see, well done Jan.

Given your intentions re stable 9.4 I thought I’d re-raise a couple of issues:

On my system with its English (Australia) keyboard

mike@middleton:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 25.04
Release: 25.04
Codename: plucky

  1. Select, drag and scroll only works to the end of the visible page i.e. doesn’t cause scrolling to allow extension of the selection. That’s fine, I can live withourt that 90’s relic but you suggested ”In the meanwhile, start a selection and use the Emacs ^F^B^N^P cursor movement. That extends the selection. So, to scroll down and select, start a selection and use ^N. It is also more pleasant :slight_smile:”

    In GNU Emacs on my machine Ctrl-Shift-N does indeed extend selection, but in PCE-Emacs I just get a message saying “Undefined“.

  2. When I manually shrink the size of the threads monitor window to a silly small size, these messages appear on the console:

    ?- ERROR: prolog_thread_monitor ->recall: Argument 1 (?): 1..' expected, found -11’
    ERROR: prolog_thread_monitor ->recall: Argument 1 (?): 1..' expected, found -19’
    ERROR: prolog_thread_monitor ->recall: Argument 1 (?): 1..' expected, found -20’

Thanks

Mike

It worked without shift … Now works as it should: deactivate the selection when used without shift and extend the selection with shift. Note that the shift-arrow-keys can be
used to select the extension as well. I think this should be according to current practice,
i.e.

  • arrow keys move normally (char/line)
  • Ctrl-arrow keys move by word/page
  • Shift-arrow extends selection, moving by the current selection unit (char/word/line).

Pushed a fix for that.