---+ Creating a pack that uses C or C++ code This page describes the basics for creating packages that contain C or C++ code, also known as _foreign_ code. ---++ Runtime installation Foreign code must be compiled into a SWI-Prolog extension, a loadable library. These things are supported by virtually any modern operating system under different names, e.g., DLL in Windows and _|shared object|_ in Unix. A package may include such an extension. The package system can see this extension iff - It is placed in a subdirectory lib/ in the package, where is the Prolog architecture as available through the Prolog flag =arch=. For example: == ?- current_prolog_flag(arch, Arch). Arch = 'x86_64-linux'. == - The file uses the extension for such objects for the target platform. This extension is also available as a Prolog flag: == ?- current_prolog_flag(shared_object_extension, Ext). Ext = so. == Provided that the above installation guidelines are followed, Prolog code can include the extension using the directive use_foreign_library/1 as below. Note that =sqlite4pl= is the example name of the extension. The search path =foreign= searches the lib/ directories of installed packages. The extension must be omitted because it is platform dependent. == :- use_foreign_library(foreign(sqlite4pl)). == ---++ Binary extensions Binary packages may include the lib/ subdirectory in the package and suitable precompiled extensions for the target architectures. Note that how well this works depends on the binary compatibility of the platform as well as the mechanism used by the platform to resolve dependencies between Prolog and the extension. In particular: $ Windows : Distributing DLLs should typically provide a fair deal of portability in terms of different Prolog and Windows versions. $ MacOS : Here, portability is poor. Provided shared objects (*|.dylib|* files) only work of the same version of SWI-Prolog is installed in the same absolute location. $ Linux : Linux ELF objects (*|.so|* files) resolve symbols against already loaded symbols, which makes the extension independent from the location of SWI-Prolog and the version. The downside is that Linux shared object that depend on many system features are often not binary compatible due to different versions of dependencies. ---++ Source extensions Alternatively, or in addition, the extensions may be provided as sources. The advantage thereof is that the above mentioned version dependencies do not apply. The disadvantage is that the user needs a suitable setup for running the C development tools and installed development libraries for dependencies. Here are some examples: $ Windows : Requires [[MinGW][http://www.mingw.org]] installed in a =mingw= folder on the same drive as where SWI-Prolog is installed. $ MacOS : Requires [[Macports][http://www.macports.org/]] installed. $ Linux : Requires the development tools installed. The package names for this vary from distribution to distribution, but typically this is smooth process and we assume that programmers using a Linux system have these tools installed. ---++ The build process The build process consists of several steps, described below. Of these steps, only (3) is obligatory. In many cases, using configure can be omitted because these programs are called with a fair deal of information provided through the environment (see below). 1. If there is a file =configure.in= and no =configure=, run - autoconf - autoheader to create =configure= 2. If there is a file =configure= (distributed or created by the previous step), run - configure 3. If there is a file =Makefile= (distributed or created by the previous steps), run - make all - make check - make install *Note* Ideally, if there is a suitable binary for the platform, pack_install/1 should not try to rebuild it. It is not clear how to verify this. ---+++ Build environment The configuration and installation steps are executed by pack_install/1 and provide the following environment variables: $ PATH : Available system path. The SWI-Prolog binary directory is prepended. $ SWIPL : Absolute path to the running SWI-Prolog instance. $ SWIPLVERSION : SWI-Prolog version as the integer 10000* + 100* + $ SWIARCH : SWI-Prolog architecture identifier (see above). $ PACKSODIR : (Relative) path to the directory where the extension must be installed. Note that the directory may not exist. $ SWISOLIB : Extensions must link to this library. Normally this is =|-lswipl|= on (X)COFF systems (Windows, MacOS) and empty on ELF systems (Linux). $ CC : C-compiler to use. Taken from the CC environment or the =c_cc= Prolog flag. $ LD : Linker to use. Taken from the LD environment or the =c_cc= Prolog flag. $ CFLAGS : Flags to pass to the compiler. Default is the flag =c_cflags=, followed by -I, where is the directory holding =|SWI-Prolog.h|=, followed by =|-D__SWI_PROLOG__|= and the value of the =CFLAGS= environment variable. $ LDSOFLAGS : Flags to pass to the linker to link an extension. Default is the flag =c_ldflags=, following by =|-shared|= and the value of the =LDFLAGS= environment variable. $ SOEXT : File name extension to use for extensions. Does _not_ include the "=|.|=". $ TMP, TEMP, HOME, USER : The variables are passed from the environment if they exist The environment can be changed by providing clauses for the multifile predicate prolog_pack:environment/2. Answers of this predicate may provided additional environment variables. Answers for the above mentioned variables replace the above described value. ---+++ Windows MinGW builds The infrastructure assumes using [[MinGW][http://www.mingw.org]] and MSYS for building foreign packages on Windows. If pack_install/1 detects a foreign pack on Windows, it performs the following steps to prepare MinGW: 1. If gcc.exe and make.exe are in %PATH%, use them. 2. Else, try to find :/MinGW, where is first the drive on which Prolog is installed, followed by *C* and *D*. 3. If (2) succeeded, add /msys//bin to %PATH% to make make.exe available.