Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example C program crashes with "cannot open shared object file" #1193

Open
kamahen opened this issue Aug 19, 2023 · 25 comments
Open

Example C program crashes with "cannot open shared object file" #1193

kamahen opened this issue Aug 19, 2023 · 25 comments

Comments

@kamahen
Copy link
Member

kamahen commented Aug 19, 2023

The traceback doesn't make sense. When I ran under gdb, the crash seems to have happened somewhere inside PL_initialise(), where it calls prologTopLevel() (pl-init.c:1247).

[peter@penguin man (master=)]$ swipl-ld -goal true -o calc calc.c calc.pl
% Disabled autoloading (loaded 30 files)
% Disabled autoloading (loaded 0 files)
% halt
[peter@penguin man (master=)]$ ./calc pi/2
ERROR: /home/peter/.local/lib/swipl/library/uri.pl:59: Initialization goal raised exception:
ERROR: uri: cannot open shared object file: No such file or directory
ERROR: In:
ERROR:   [18] throw(error(shared_object(open,'uri: cannot open shared object file: No such file or directory'),context(...,_4354)))
ERROR:   [16] <meta call>
ERROR:   [15] with_mutex('$foreign',load_foreign_library(foreign(uri),uri,[])) <foreign>
ERROR:   [11] '$run_init_goal'('$syspreds':use_foreign_library_noi(...)) at /home/peter/src/swipl-devel/boot/init.pl:823
ERROR:   [10] catch(system:'$run_init_goal'(...),_4488,system:'$initialization_error'(_4510,...,...)) at /home/peter/src/swipl-devel/boot/init.pl:563
ERROR:    [9] catch_with_backtrace(system:'$run_init_goal'(...),_4546,system:'$initialization_error'(_4568,...,...)) at /home/peter/src/swipl-devel/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.
ERROR: /home/peter/.local/lib/swipl/library/time.pl:134: Initialization goal raised exception:
ERROR: time: cannot open shared object file: No such file or directory
ERROR: In:
ERROR:   [18] throw(error(shared_object(open,'time: cannot open shared object file: No such file or directory'),context(...,_218)))
ERROR:   [16] <meta call>
ERROR:   [15] with_mutex('$foreign',load_foreign_library(foreign(time),time,[])) <foreign>
ERROR:   [11] '$run_init_goal'('$syspreds':use_foreign_library_noi(...)) at /home/peter/src/swipl-devel/boot/init.pl:823
ERROR:   [10] catch(system:'$run_init_goal'(...),_352,system:'$initialization_error'(_374,...,...)) at /home/peter/src/swipl-devel/boot/init.pl:563
ERROR:    [9] catch_with_backtrace(system:'$run_init_goal'(...),_410,system:'$initialization_error'(_432,...,...)) at /home/peter/src/swipl-devel/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.
1.5707963267948966
[peter@penguin man (master=)]$ ldd ./calc
	linux-vdso.so.1 (0x00007ffd9c1d4000)
	libswipl.so.9 => /home/peter/.local/lib/swipl/lib/x86_64-linux/libswipl.so.9 (0x00007ec3c7af4000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ec3c7907000)
	libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007ec3c78d8000)
	libgmp.so.10 => /lib/x86_64-linux-gnu/libgmp.so.10 (0x00007ec3c7857000)
	libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007ec3c783a000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007ec3c7832000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007ec3c76ee000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007ec3c76cc000)
	/lib64/ld-linux-x86-64.so.2 (0x00007ec3c7c9d000)
@kamahen
Copy link
Member Author

kamahen commented Aug 19, 2023

Probably unrelated, but it seems that the wrong compiler is used by swipl-ld:

$ swipl-ld --version
cc (Debian 10.2.1-6) 10.2.1 20210110
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

but I built with:

$ gcc --version
gcc (GCC) 13.2.0
Copyright (C) 2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

@JanWielemaker
Copy link
Member

Probably requires --no-pce to be passed to creating the saved state. Probably that should be default. Not sure what selects the default compiler these days. May be hardcoded to use cc. It is unrelated.

@kamahen
Copy link
Member Author

kamahen commented Aug 19, 2023

It seems that gcc is used for the link step by /usr/bin/cc is hard-coded for the step that generates the .o file.

I tried running the individual steps manually, changing the /usr/bin/cc to gcc and adding --pce=no to the swipl/qsave line. It didn't make a difference (and ldd showed the same libraries):

++ swipl --dump-runtime-variables
+ eval 'PLBASE="/home/peter/.local/lib/swipl";' 'PLARCH="x86_64-linux";' 'PLBITS="64";' 'PLVERSION="90114";' 'PLSOEXT="so";' 'PLSOPATH="LD_LIBRARY_PATH";' 'PLLIBDIR="/home/peter/.local/lib/swipl/lib/x86_64-linux";' 'PLLIB="-lswipl";' 'PLLIBSWIPL="/home/peter/.local/lib/swipl/lib/x86_64-linux/libswipl.so.9";' 'PLSHARED="yes";' 'PLTHREADS="yes";'
++ PLBASE=/home/peter/.local/lib/swipl
++ PLARCH=x86_64-linux
++ PLBITS=64
++ PLVERSION=90114
++ PLSOEXT=so
++ PLSOPATH=LD_LIBRARY_PATH
++ PLLIBDIR=/home/peter/.local/lib/swipl/lib/x86_64-linux
++ PLLIB=-lswipl
++ PLLIBSWIPL=/home/peter/.local/lib/swipl/lib/x86_64-linux/libswipl.so.9
++ PLSHARED=yes
++ PLTHREADS=yes
+ gcc -c -g -O0 -D_REENTRANT -D__SWI_PROLOG__ -D__SWI_EMBEDDED__ -I/home/peter/.local/lib/swipl/include -o calc.o calc.c
+ gcc -o calc -g -Wl,-rpath=/home/peter/.local/lib/swipl/lib/x86_64-linux calc.o -L/home/peter/.local/lib/swipl/lib/x86_64-linux -lswipl
+ swipl --pce=no -f none -F none -g true -t 'consult(['\''calc.pl'\'']),qsave_program('\''pltmp-8637'\'',[goal=true,toplevel=prolog,init_file=none])'
% Disabled autoloading (loaded 30 files)
% Disabled autoloading (loaded 0 files)
% halt
+ cat pltmp-8637
+ chmod 755 calc
+ rm pltmp-8637

The expected external references were there:

$ nm calc
0000000000404068 B __bss_start
0000000000404068 b completed.0
0000000000404058 D __data_start
0000000000404058 W data_start
00000000004010f0 t deregister_tm_clones
00000000004010e0 T _dl_relocate_static_pie
0000000000401160 t __do_global_dtors_aux
0000000000403dd8 d __do_global_dtors_aux_fini_array_entry
0000000000404060 D __dso_handle
0000000000403de0 d _DYNAMIC
0000000000404068 D _edata
0000000000404070 B _end
0000000000401344 T _fini
0000000000401190 t frame_dummy
0000000000403dd0 d __frame_dummy_init_array_entry
000000000040214c r __FRAME_END__
0000000000404000 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
0000000000402010 r __GNU_EH_FRAME_HDR
0000000000401000 T _init
0000000000403dd8 d __init_array_end
0000000000403dd0 d __init_array_start
0000000000402000 R _IO_stdin_used
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
0000000000401340 T __libc_csu_fini
00000000004012e0 T __libc_csu_init
                 U __libc_start_main@GLIBC_2.2.5
0000000000401196 T main
                 U PL_call_predicate
                 U PL_halt
                 U PL_initialise
                 U PL_new_term_refs
                 U PL_predicate
                 U PL_put_atom_chars
0000000000401120 t register_tm_clones
00000000004010b0 T _start
                 U strcpy@GLIBC_2.2.5
                 U strlen@GLIBC_2.2.5
0000000000404068 D __TMC_END__

@kamahen
Copy link
Member Author

kamahen commented Aug 19, 2023

When I copied calc.{c,cpp} to another directory, everything worked. So, there appears to be something in the man directory that's being picked up, causing the problem. One hint is that when I stripped the code down to the minimum (just calling PL_initialise()), and removed the calc.pl from the swipl-ld line, I still got a Could not find system resources error.

@kamahen
Copy link
Member Author

kamahen commented Aug 19, 2023

Update - it appears to not be anything in the man directory but something to do with where the directory is.
When I copied (recursively) the contents of the man directory to /tmp, everything worked fine.

@JanWielemaker
Copy link
Member

May well be that the algorithm to find the home dir is disturbed at some place by the stuff that is in the build environment. See docs for the various steps tried to find the resource file.

@kamahen
Copy link
Member Author

kamahen commented Aug 20, 2023

That seems to be the problem -- when I set the environment variable SWI_HOME_DIR or SWIPL, it works properly.

The problem seems to be that at pl_init.c:314, the code determines that directory /home/peter/src/swipl-devel exists, and it then uses /home/peter/src/swipl-devel/swipl.home (because PLHOMEFILE is defined), which contains "." . Presumably this is desired behaviour for some testing?

@kamahen
Copy link
Member Author

kamahen commented Aug 20, 2023

After all, the traceback doesn't indicate a crash -- calc.c runs (and calls calc/1 (in calc.pl, which it is able to find even though it can't findthe "home" directory) ... the output is the one line without ERROR: (which is to stdout; the error lines are to stderr).

Is the traceback from a different thread than what runs calc.c's main()?

I read the documentation on resources (which doesn't mention the swipl.home file -- I got that from tracing the code) but I'm a bit confused about how it works or what uses it. The traceback is missing a bit of information. Also, does swipl-ld --no-pce do anything? - swipl-ld seems to just ignore options it doesn't understand, and the -v output showed no difference with no-pce (presumably, it's pce that wants library(time) and library(uri)).

@kamahen
Copy link
Member Author

kamahen commented Aug 20, 2023

I tried running swipl-ld with `-pl-options '--no-pce' but misbehaved (I'll try to figure this out later).

Instead, I ran the commands by hand, adding --no-pce to the qsave step:

swipl --no-pce -f none -F none -g true -t "consult(['calc.pl']),qsave_program('pltmp-2246',[goal=true,toplevel=prolog,init_file=none])"

This also got the traceback (to stderr) and the expected output (to stdout).
So, pce doesn't seem to be the cause.

I wonder if this should be debugged using --threads=false ... if so, how would I specify this to the qsave step?

@JanWielemaker
Copy link
Member

--no-pce doesn't seem to be necessary as it uses -F none, which also disables xpce. It works for me when not creating the sate in the build tree but copying cal.c and calc.pl to some other directory. I wonder why ...

@JanWielemaker
Copy link
Member

I see. In both cases the state includes library(ansi_term) which depends on uri_file_name/2 and thus includes library(uri) which depends on the uri.so foreign object. When started outside the Prolog source tree, it still gets the actual installation location and can load the foreign object. When started inside the man dir, using swipl.home in the parent directory of the executable, it thinks the home is the source tree. But now, the foreign object is not in the expected place and thus we cannot find the uri object.

Now it is a little unclear what to do. One is to use the foreign(save) option of qsave_program to include uri.so in the saved state. Another is to avoid the dependency on uri_file_name/2 or, probably even better on library(ansi_term). Better control over the dependency is probably the best way to go in the long term. How exactly is non-trivial. Part of the unwanted dependencies consider the support for debugging and interactive behavior.

@JanWielemaker
Copy link
Member

Pushed a commit to remove the old swipl.home and swipl.rc from the top of the source. These were old remains from the pre-cmake build setup. This makes calc in man work, but does not resolve the issue otherwise.

@kamahen
Copy link
Member Author

kamahen commented Aug 21, 2023

Is there a way to turn on trace at the beginning of the executable?

Anyway, I noticed that toplevel.pl has predicate setup_colors/0, which uses library(ansi_term). There's also a call to library(time) in the traceback (which also seems to come from library(ansi_term) - see below). setup_colors/0 is called from initalise_prolog/0, which is called from $initialise/0.

I tried this, but it didn't fix the problem (I reinstated swipl.home, swipl.rc so that the bug would be trigered):

~/src/swipl-devel/build/src/swipl-ld  -pl-options='--no-threads' -v -o calc -class runtime -cc gcc -ld gcc -goal true -toplevel halt calc.c calc.pl

which expanded to:

swipl --no-threads -f none -F none -g true -t "consult(['calc.pl']),qsave_program('pltmp-3995',[goal=true,toplevel=halt,init_file=none,class=runtime])"

hmmm ... shouldn't it have called ~/src/swipl-devel/build/src/swipl instead of swipl? Anyway, I solved that by adding -pl /home/peter/src/swipl-devel/build/src/swipl and got this (no surprise; the binary is in the build tree):

	/home/peter/src/swipl-devel/build/src/swipl --no-threads -f none -F none -g true -t "consult(['calc.pl']),qsave_program('pltmp-4083',[goal=true,toplevel=halt,init_file=none,class=runtime])"
ERROR: /home/peter/src/swipl-devel/build/home/library/uri.pl:59:
ERROR:    /home/peter/src/swipl-devel/build/home/library/uri.pl:59: Initialization goal raised exception:
ERROR:    open_shared_object/3: uri: cannot open shared object file: No such file or directory
ERROR: /home/peter/src/swipl-devel/build/home/library/ansi_term.pl:45:
ERROR:    Exported procedure uri:uri_iri/2 is not defined
ERROR: /home/peter/src/swipl-devel/build/home/library/ansi_term.pl:45:
ERROR:    Exported procedure uri:uri_encoded/3 is not defined
ERROR: /home/peter/src/swipl-devel/build/home/library/ansi_term.pl:45:
ERROR:    Exported procedure uri:uri_authority_components/2 is not defined
ERROR: /home/peter/src/swipl-devel/build/home/library/ansi_term.pl:45:
ERROR:    Exported procedure uri:uri_query_components/2 is not defined
ERROR: /home/peter/src/swipl-devel/build/home/library/ansi_term.pl:45:
ERROR:    Exported procedure uri:uri_normalized_iri/3 is not defined
ERROR: /home/peter/src/swipl-devel/build/home/library/ansi_term.pl:45:
ERROR:    Exported procedure uri:uri_resolve/3 is not defined
ERROR: /home/peter/src/swipl-devel/build/home/library/ansi_term.pl:45:
ERROR:    Exported procedure uri:uri_normalized/3 is not defined
ERROR: /home/peter/src/swipl-devel/build/home/library/ansi_term.pl:45:
ERROR:    Exported procedure uri:uri_normalized_iri/2 is not defined
ERROR: /home/peter/src/swipl-devel/build/home/library/ansi_term.pl:45:
ERROR:    Exported procedure uri:iri_normalized/2 is not defined
ERROR: /home/peter/src/swipl-devel/build/home/library/ansi_term.pl:45:
ERROR:    Exported procedure uri:uri_normalized/2 is not defined
ERROR: /home/peter/src/swipl-devel/build/home/library/ansi_term.pl:45:
ERROR:    Exported procedure uri:iri_normalized/3 is not defined
ERROR: /home/peter/src/swipl-devel/build/home/library/ansi_term.pl:45:
ERROR:    Exported procedure uri:uri_components/2 is not defined
ERROR: /home/peter/src/swipl-devel/build/home/library/ansi_term.pl:45:
ERROR:    Exported procedure uri:uri_is_global/1 is not defined
ERROR: /home/peter/src/swipl-devel/build/home/library/time.pl:134:
ERROR:    /home/peter/src/swipl-devel/build/home/library/time.pl:134: Initialization goal raised exception:
ERROR:    open_shared_object/3: time: cannot open shared object file: No such file or directory
ERROR: /home/peter/src/swipl-devel/build/home/library/ansi_term.pl:47:
ERROR:    Exported procedure time:alarm_at/4 is not defined
ERROR: /home/peter/src/swipl-devel/build/home/library/ansi_term.pl:47:
ERROR:    Exported procedure time:uninstall_alarm/1 is not defined
ERROR: /home/peter/src/swipl-devel/build/home/library/ansi_term.pl:47:
ERROR:    Exported procedure time:install_alarm/2 is not defined
ERROR: /home/peter/src/swipl-devel/build/home/library/ansi_term.pl:47:
ERROR:    Exported procedure time:remove_alarm/1 is not defined
ERROR: /home/peter/src/swipl-devel/build/home/library/ansi_term.pl:47:
ERROR:    Exported procedure time:install_alarm/1 is not defined
ERROR: /home/peter/src/swipl-devel/build/home/library/ansi_term.pl:47:
ERROR:    Exported procedure time:alarm/3 is not defined
ERROR: /home/peter/src/swipl-devel/build/home/library/ansi_term.pl:47:
ERROR:    Exported procedure time:alarm_at/3 is not defined
ERROR: /home/peter/src/swipl-devel/build/home/library/ansi_term.pl:47:
ERROR:    Exported procedure time:alarm/4 is not defined
% Disabled autoloading (loaded 30 files)
% Disabled autoloading (loaded 0 files)
% halt

@kamahen
Copy link
Member Author

kamahen commented Aug 22, 2023

I tried commenting out setup_colors/0 (plus a few other "setup" predicates") in toplevel.pl and that didn't change anything.

@JanWielemaker
Copy link
Member

As is, you cannot create a saved state using swipl-ld from the version running in the build directory because it uses -F none, which means that home/swipl.rc is not read and this is required to make the build version find all the components in the build tree where they are not in their final place. An option might be not to use -F, but to use --no-pce. Not sure ..

It might be.a good idea to change building the state to use swipl -o out [options] -c file.pl .... When swipl-ld was written this provided limited functionality, but it mow covers all qsave_program.2 options.

Tracing is a bit hard. You can insert set_prolog_flag(access_level, system), trace. at the entry point. You can also use the class() option,I think development, to avoid locking up the code as system predicates and keep some more info around.

@kamahen
Copy link
Member Author

kamahen commented Aug 28, 2023

Is the swipl.home logic needed any more?
It seems that the build could just set SWI_HOME_DIR or SWIPL, although there seems to be some fiddling around with files dot.txt and dotdot.txt in top-level CMakeLists.txt. (And PLHOMEFILE in pl-init.h)

swipl-ld also needs a bit of clean-up (see issue #1195).

@JanWielemaker
Copy link
Member

Is the swipl.home logic needed any more?

I think so. It is used by the relocatable runtime environments as used for Windows and MacOS to find the home relative to the executable. I seems more elegant then using an environment variable. Environment variables are global. Using this "link" we can find the home from the executable/share object, so we can have multiple installations active.

@kamahen
Copy link
Member Author

kamahen commented Aug 29, 2023

I suppose I should document swipl.home, then. :)

Getting back to the original problem, a saved state contains:

  Length      Date    Time    Name
---------  ---------- -----   ----
      124  2023-08-28 17:12   $prolog/options.txt
   556753  2023-08-28 17:12   $prolog/state.qlf
    31328  2023-08-18 16:56   shlib('x86_64-linux',time)
    29640  2023-08-14 17:17   shlib('x86_64-linux',uri)
---------                     -------
   617845                     4 files

The "verbose" messages from qsave_program don't show any autoloading of time and uri:

/home/peter/.local/bin/swipl -f none -F none -g true -t 'consult(['\''re.pl'\'']),qsave_program('\''pltmp-28205'\'',[goal=true,toplevel=halt,init_file=none,foreign(save),stand_alone(true),verbose(true)])'
% Disabled autoloading (loaded 36 files)
% autoloading error:assertion/1 from /home/peter/.local/lib/swipl/library/debug
% autoloading prolog_clause:nth1/3 from /home/peter/.local/lib/swipl/library/lists
% Disabled autoloading (loaded 0 files)
% Autoloader: loaded 0 files in 1 iterations in 0.052 seconds
% halt

Any suggestions about how to find out why time and uri are being included?

I suppose it doesn't really matter, because if they're needed, they're in the saved state (at least, if foreign_save(true) is specified). Still, it bothers me, for some reason.

@JanWielemaker
Copy link
Member

Any suggestions about how to find out why time and uri are being included?

I think they are included too early by library(ansi_term). URIs are used for smart linking in terminals capable of (non-standard) ANSI sequences to create hyperlinks and timing is used to figure out the fore and background color of the console. Probably we should avoid these to be loaded into an otherwise non-interactive executable or we should move the minimal requirements to the core. It would be nice if pure Prolog executables do not require foreign code in the state.

Debugging the stuff that happens really early is a bit hard. Typically I insert write statements where needed. The ultimate way to find why a library is loaded is to add something like this to the library.

:- backtrace(50).

You may have better results using swipl -o out [option ...] -c file.pl ... as this uses a different entry point. Related, we probably want some way to avoid the steps preparing for interactive behavior.

@kamahen
Copy link
Member Author

kamahen commented Aug 29, 2023

How would I use swipl ... -c file.pl to create a self-contained executable with my C code as "main"?

There seem to be 3 places where ansi_term is used:

  • toplevel.pl (predicate setup_colors/0)
  • library(listing) - ansi_format/3
  • library(theme/auto)

and ansi_term uses library(uri): uri_file_name/2

I could make the error messages go away (and the inclusions of foreign code for uri and time) by commenting out all of setup_color/0 in toplevel.pl and changing the call to ansi_format/3 to format/3incomment/2` in library(listing), and removing the reference to ansi_term in library(theme/auto). (Not sure if the last change was needed)

I don't use ansi_term (but I use emacs shell), so this seems fine to me.

PS: I couldn't figure out how to increase the amount of backtrace from catch_with_backtrace during init ... setting the backtrace_depth didn't change the backtrace, and it was only 10 lines even though the default backtrace_depth is 20.

@JanWielemaker
Copy link
Member

How would I use swipl ... -c file.pl to create a self-contained executable with my C code as "main"?

The problem is the same as using swipl -g ..., no? Roughly, there are two options: you use the standard swipl to create the state, which may fail if the C embedding adds predicates that are required for creating the state. Alternatively you use the executable with Prolog embedded that you just created. But that requires this executable to pass argv/argc to PL_initialise() such that the command line options work the same.

and ansi_term uses library(uri): uri_file_name/2

That is more or less what I expected. The -c entry point ($toplevel:$compile) also calls setup_colors/0, so that won't help. I'm still a bit unsure. I'm tempted to move/have a copy of uri_file_name/2 in the core to avoid that dependency. Possibly we can work around the call_with_time_limit/2 call by using the stream timeout property for implementing ansi_get_color_/3.

IMO, loading library(ansi_term) is in itself ok. Terminal apps may want to use it anyway. You can avoid loading it by ensuring stdin, stdout or stderr is not connected to a terminal.

@kamahen
Copy link
Member Author

kamahen commented Aug 30, 2023

The problem seems to be that library(listing) uses ansi_format/3 ... setup_colors/0 in toplevel.pl appears to do the right thing in a dumb terminal (such as an emacs shell). However, setup_colors/0 does the wrong thing (when compiling) on a terminal that understands colour.

Maybe the problem is that SWI-Prolog doesn't distinguish very well between a development environment (which would use ansi_term etc) and a deployment environment (which would have a minimal set of included stuff and wouldn't colourise by default). It's an interesting philosophical question as to whether an "embedded executable", as created by swipl-ld, should contain library(listing).

@JanWielemaker
Copy link
Member

These are related, but distinct issues IMO. Whether or not color support is desirable depends on whether the final application will talk to a console and whether or not it calls things such as print_message/2 or not. The module isn't really a big deal if it does not depend on the time and uri libraries and checking whether or not colors must be used is redone when the state is started (if not, that is a bug).

Indeed, which part of the development tools must be included is unclear. Having them around ensures sensible error messages in case the application goes wrong (e.g., a backtrace). We have the class option of qsave_program/2 for how the state is intended to be used. Possibly we should extend this?

One of the things I had in mind for a long time is adding either a volatile property to modules to avoid them being saved (this property already exists for predicates). Alternatively we could possibly use the class property of modules to define "development tool" modules that can or cannot be saved depending on the class specified when creating the state?

SWI-Prolog was never very good at optimizing for small programs ...

@kamahen
Copy link
Member Author

kamahen commented Aug 30, 2023

Or put if(current_prolog_flag(color_term,true)) around the autoload(library(ansi_term)) in module listing?
And have two versions of comment/2? ...

How would you access the value of the class option of qsave_program/2?
:-if(\+ current_prolog_flag(qsave_class,runtime)? and listing:comment/2 does a check for color_term?

One reason for making "embedded executables" is to separate the build environment from the deployment environment. The debate over things like shared objects has been going on for years, and I don't see an easy solution.

So, until somebody really needs this, maybe just leave it alone? Perhaps I can make the start-up code a bit more easily understand and/or more flexible ...

@JanWielemaker
Copy link
Member

Or put if(current_prolog_flag(color_term,true)) around the autoload(library(ansi_term)) in module listing?
And have two versions of comment/2? ...

And we have print_message/2 calls coming from everywhere that use this stuff. I think that gets a mess. Pushed two commits that no longer make library(ansi_term) depend on the clib package. That at least turns this into simple innocent Prolog code.

One reason for making "embedded executables" is to separate the build environment from the deployment environment. The debate over things like shared objects has been going on for years, and I don't see an easy solution.

Yes. As is though, that is not so easy. The two are pretty tightly connected all over SWI-Prolog. This is not so bad, but it makes the executables a little larger than necessary. As is, a minimal executable is about 235Kb and runs in 20ms (AMD3950X, Linux). As your program grows, the size grows much slower. For example, sCASP is 365Kb source and produces a state of 487Kb, also pulling in many libraries. Startup time of sCASP is 40ms.

So, until somebody really needs this, maybe just leave it alone? Perhaps I can make the start-up code a bit more easily understand and/or more flexible ...

Looks like low priority, especially after getting rid of the package and foreign extension dependencies for simple programs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants