Shared vs. Static Object Files

A runtime system is a single executable program that should be easily transferable to a different machine. By default, the executable built by qld will use dynamic libraries where it can, such as the dynamic C library (-lc under UNIX, /MD under Windows). This requires that a corresponding library exist on the target machine on which the executable will be run.

Under UNIX, you may encounter problems if libraries included in your executable are not installed in "standard places" -- e.g. in /usr/lib -- on the target machine. For example, if you specify -lX11, but the corresponding file libX11.so.4.2 resides in /usr/local/lib/X11. Typically, a user has to set the LD_LIBRARY_PATH environment variable to find libraries in non-standard places, although another option at installation time might be to add a call to ldconfig(8) in /etc/rc.local to include the directory containing a shared library into the system-wide list of "standard places" to find shared libraries. The ldd(1) command lists the dynamic dependencies of an executable and whether or not these can be found.

The problem exists under Windows but the details are different. In particular Windows shared libraries are looked for in the folders specified by the PATH environment variable and in some further "standard places". Consult the Windows documentation for details.

In addition to shared libraries, your executable may contain shared object files, specified in calls to load_foreign_executable/1. qld passes the absolute file paths for these files to the linker, which results in the dependencies for these shared object files being stored in the runtime system executable as absolute filenames. Note that this problem can arise even if you have no foreign code of your own, if you are using the Quintus Prolog library or X interfaces.

A solution to the shared object files problem is to use the -S option with qld, which tries to substitute archive files for shared object files where they exist. If the shared object files have dependencies on other shared libraries then those libraries need to be explicitly listed in the qld command, as qld does not track these dependencies. This makes your executable file larger, as the library code is stored within the executable rather than linked in at start-up time. Each shared object file provided in the Quintus libraries has an equivalent archive file that can be substituted by the qld -S command.

For example, under UNIX, building a runtime system from the file in (A) with the command (B) produces an a.out file, which prints the date and time, as in (C).

                                    
test.pl
:- use_module(library(date)). (A) runtime_entry(start) :- datime(X), portray_date(X), nl.
     % qpc test.pl (B)
     
     % ./a.out (C)
     2:10:09 PM 1-Feb-91
     

This a.out file has a dependency on the Prolog library as well as on the C library, as shown by the ldd(1) command:

     % ldd a.out
         /usr/local/quintus/generic/qplib3.5/library/sun4-5/libpl.so
         libc.so.1 => /usr/lib/libc.so.1.8
     

Under Windows, the example would be almost the same, with the difference that the default name of the executable produced by qpc is a.exe rather than a.out. To view dependencies you can type dumbin /DEPENDENTS a.exe.

Hence this runtime system will not work on a machine where Quintus Prolog is not installed. To build a runtime system that does not have this dependency, it is necessary to call qld -S explicitly, rather than just calling qpc test.pl as shown above. Under UNIX, the necessary command sequence is:

     % qpc -c test.pl
     % qld -Sd test.qof
     

That is, qpc is called with the -c option so that it stops after producing a .qof file, rather than calling qld. Then qld is called with the -S option so that it substitutes libpl.a for libpl.so. The result is an executable that depends only on the C shared library:

     % ldd a.out
         ilbc.so.1 => /usr/lib/libc.so.1.8
     

This executable should run without problem on a different machine.

Under Windows, the linker does not automatically add all needed OS libraries. These need to be added explicitly as follows:

     C:\> qpc -c test.pl
     C:\> qld -Sd test.qof -LD qpconsoles.lib user32.lib gdi32.lib comdlg32.lib
     

Windows notes:

  1. The -S and -W flags can be combined.
  2. If the -S option is used, the -LD option must also be used, together with the library references qpconsoles.lib, user32.lib, gdi32.lib, and comdlg32.lib.
  3. If the Prolog code has a foreign executable dependency on myforeignex, a static library myforeignexs.lib needs to be created. The trailing s is significant (see below); qld assumes this naming convention. Here is an example of the necessary sequence of commands to create a static executable myforeignex.exe:
                   C:\> cl /c /MD myforeignex.c
                   C:\> link /lib /OUT:myforeignexs.lib myforeignex.obj
                   C:\> qpc -c myprog.pl
                   C:\> qld -Sdvo myprog.exe myprog.qof -LD \
                        user32.lib comdlg32.lib qpconsoles.lib gdi32.lib
                   

    The above command produces an executable that uses the static version of the Runtime Kernel and has no DLL dependencies. Statically linked applications can still dynamically load foreign code DLLs, provided these DLLs do not call any of the Quintus Prolog C API functions.

    In order to distinguish static libraries from DLL import libraries in foreign dependencies, the following naming convention has been chosen. If the -S option is used, when processing a library dependency qld will first search for the library with an s appended to its name, for example libqps.lib for the Embedding Layer, and if not found it tries the original name.