We recommend using GIT for developing SWI-Prolog packages. To start a 
new package, invent a name and verify that the name is not yet in use at 
The pack 
landing page. Create a directory with this name, a sub-directory prolog 
and a the metadata file pack.pl that contains at least the 
name and version of the pack. Below is a simple example. See
section 15.5.1 for 
all possible metadata fields.
name(hello).
version('1.0.0').
title('Hello world').
keywords([demo]).
author( 'Bob Programmer, 'bob123@programmer.me. ).
download('https://github/bob123/hello.git').
Now, add the Prolog libraries provided to the prolog 
directory. While doing so, please pay attention to the points below. If 
your are looking for examples of well structured libraries, please look 
at the system libraries.
prolog directory.library(File). Thus, make sure the name is fairly unique 
and the module name is typically the same as the base name of 
the file.private 
is not a good idea because the private directory of each 
pack using this would be available as library(Pack/private). 
Use e.g., pack_<name> for the module names of the 
private files.Once the pack is ready for a very first test, we can make it accessible using the command below. On non-Windows systems, this makes the pack accessible using a symbolic link from your personal pack directory to this directory.
swipl pack install .
After this command the new libraries should be available when you 
start a new SWI-Prolog process. Another way to make the pack accessible 
is by using the pack search path (see
file_search_path/2). 
The command (from the pack directory) is
swipl -p pack=..
A pack must have a file pack.pl in its root directory. 
The file contains Prolog terms. Defined terms are below. The argument 
types are types registered with must_be/2 
and described in the running text.
[a-zA-Z9-0_]+author, but the contact cannot be empty. May be 
repeated.@(Token,Version). 
A pack implicitly provides @(PackName,PackVersion). The 
supplied tokens operate in the same name space as packages and 
thus the same care must be taken to select a name. Multiple of these 
claims may be present.provides. The dependency may be further refined by 
writing Token Cmp Version, where Cmp is one of 
Prolog's standard numerical comparison operators. See cmp_versions/3. 
This metadata is also used to state requirements on Prolog. See
section 15.5.1.1. 
Multiple requirements are expressed with multiple claims.requires.true, add the library for the package as autoload 
library. This implies that the exported predicates may be used without 
explicitly importing the library. Use with care.
The file pack.pl may contain requires(Requirement) 
statements. Normally, Requirement is a pack or token, 
optionally with a version requirement. The requirement prolog 
is reserved for requirements on the Prolog version while
prolog:Feature may be used to demand specific 
features. Feature matching is described with
require_prolog_version/2. 
Multiple requirements on Prolog must all be true. Below are some 
examples
requires(prolog >= '9.2'). % 9.2.0 or later requires(prolog:threads). % flag threads = true requires(prolog:library(socket)). % library(socket) exists requires(prolog:bounded(false)). % flag bounded = false
Many packs include C or C++ resources. Such packs include the C or 
C++ resources in a subdirectory of the pack. There are no restrictions 
for naming this subdirectory or structuring the source files in this 
directory. The build process must create native modules in the 
directory lib/<arch>, where <arch> 
is the architecture as obtained by the Prolog flag arch.
The build process identifies control files that tell the package 
manager which build tool to use. The package manager populates the 
process environment with variables that provide details about the 
running Prolog instance. This environment is saved in a file buildenv.sh 
in the pack root or build directory. By
sourcing this file, the user may run the build tools by hand 
for debugging purposes.
The build process consists of five steps that are described below
conan. It is executed if 
either conanfile.txt or conanfile.py is found 
in the root directory of the pack.CMakeLists.txt 
(cmake), configure, configure.in (autoconf), configure.ac 
or Makefile.am (automake) are found. The program to 
manage them is in parenthesis.Makefile or
makefile is expected and Unix make is used to build 
the process.make check.make install.
While running the above tools, the environment is populated. The 
names of the variables provided depends on the pack_version(Version) 
metadata. We give the names for version 2, with the names for 
version 1 in parenthesis if this differs from the version 2 
name.
PATHSWIPLSWIPL_PACK_VERSIONSWIPL_VERSION (SWIPLVERSION)SWIPL_HOME_DIR (SWIHOME)SWIPL_ARCH (SWIARCH)SWIPL_MODULE_DIR (PACKSODIR)lib/$SWIARCH.SWIPL_MODULE_LIB (SWISOLIB)SWIPL_LIB (SWILIB)-lswipl)SWIPL_INCLUDE_DIRSSWI-Prolog.h, SWI-Stream.h and
SWI-cpp2.h.SWIPL_LIBRARIES_DIRlibswiplSWIPL_CC (CC)SWIPL_CXX (CXX)SWIPL_LD (LD)SWIPL_CFLAGS (CFLAGS)-ISWIPL-INCLUDE-DIR.SWIPL_MODULE_LDFLAGS (LDSOFLAGS)SWIPL_MODULE_EXT (SOEXT).so or .dll)SWIPL_PREFIX (PREFIX)
If the package requires some C code to be compiled that has no 
dependencies and needs no configuration it is probably easiest to use a 
simple Unix make file. We assume pack_version(2). Here is a 
simple Makefile. We assume the pack contains a file
c/environ.c that contains the C source. Following the GNU 
guidelines, the Makefile must define the following targets:
distclean 
target is used by pack_rebuild/1.
MODULE= $(SWIPL_MODULE_DIR)/environ.$(SOEXT)
CFLAGS= $(SWIPL_CFLAGS)
all:    $(MODULE)
OBJ=c/environ.o
$(MODULE): $(OBJ)
        mkdir -p $(SWIPL_MODULE_DIR)
        $(SWIPL_LD) $(SWIPL_MODULE_LDFLAGS) -o $@ $(OBJ) $(SWIPL_MODULE_LIB)
check::
        $(SWIPL) -g run_tests -t halt test/test_environ.pl
install::
clean:
        rm -f $(OBJ)
distclean: clean
        rm -f $(MODULE)
As described in section 
15.4, a pack is distributed either as an archive file or as a GIT 
repository. We strongly encourage using a GIT repository as that gives 
good version and provenance support. Packs may be published by hand by 
making the archive or git repository available from a globally 
accessible place on the internet and installing the pack from this 
location. This process is streamlined, notably for GIT packs using pack_publish/2 
and the
app pack. To publish a pack a local GIT repository 
that has publicly accessible origin,
version(Version) in pack.plswipl pack publish .
This will
download(URL) metadata or the GIT remote information.Similarly, a pack can be published from a public archive using the command below. When using an archive, never change the content of the archive but, instead, create a new archive with a new version.
swipl pack publish URL
If the package is more complicated, a simple Makefile typically does not suffice. In this case we have two options. One is to use the GNU autoconf or automake. However, cmake is getting more popular and provides much better support for non-POSIX platforms, e.g., Windows. This section discusses building the same package as section 15.5.2.1 using cmake.
To use cmake, add the content below as the file
CMakeLists.txt to the root directory of the pack. 
SWI-Prolog ships with a cmake include file named
swipl.cmake that deals with most of the configuration 
issues. Comments in the file below explain the various steps of the 
process.
cmake_minimum_required(VERSION 3.10)
project(swipl-pack-environ)
# Include swipl.cmake from the running SWI-Prolog's home
list(INSERT CMAKE_MODULE_PATH 0 $ENV{SWIPL_HOME_DIR}/cmake)
include(swipl)
# Create the library as a CMake module
add_library(environ MODULE c/environ.c)
# Link the library to SWI-Prolog.  This also removes the `lib` prefix
# from the target on systems that define a common library file prefix
target_link_swipl(environ)
# Install the foreign target. `${swipl_module_dir}` contains the
# directory for installing modules for this architecture.
install(TARGETS environ
        DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/${swipl_module_dir})
# Run  tests.  This  is  executed   before    the   pack  is  installed.
# swipl_test(name) runs Prolog with the command line below.
#
#    swipl -p foreign=${CMAKE_CURRENT_SOURCE_DIR}/${swipl_module_dir} \
#          -p library=${CMAKE_CURRENT_SOURCE_DIR}/prolog \
#          --on-error=status \
#          -g test_${name} \
#          -t halt \
#          ${CMAKE_CURRENT_SOURCE_DIR}/test/test_${name}.pl
#
# This  implies  that  a  test  `name`  must    be  defined  in  a  file
# `test/test_${name}.pl`, which exports a  predicate `test_${name}`. The
# test succeeds if this predicate  succeeds   and  no error messages are
# printed.
enable_testing()
swipl_add_test(environ)
If a package needs a revision to fix bugs or add functionality it needs to be updated. First, we create a development environment using
buildenv.sh that contains the environment variables for 
building the pack.
?- pack_install(.).
Next, we can edit the pack sources and rebuild it the chosen build 
tools after running source buildenv.sh to set the 
appropriate environment variables. After validating that the pack works 
as expected follow the instructions in section 
15.5.2.2 to publish the new version.