## 15.1 Installing packs

As of version 9.1.22, SWI-Prolog supports three models for managing packs: shared packages are added to the user or system environment, while project specific packages are added to a particular project only. Finally, project specific packages can be managed as git submodules. These three approaches are discussed in more detail below.

Using pack_install/2 we can install a package either for the current user or globally for all users.

Shared packages

System-wide installations is satisfactory as long as all projects can use the same version of a pack, the packs required by all projects do not conflict, and redistribution of the projects is not a primary concern. For example, if you frequently require RocksDB for several projects you are working on, installing the `rocksdb` pack as user is appropriate.

The shared model is similar to e.g., Python's pip installer. Python resolves dealing with packages for a specific project using virtual environments, where each virtual environment provides a selection of packages. A Python virtual environment may be activated for the current shell, which modifies the shell's environment variables.

Project specific packages

Alternatively, SWI-Prolog allows packs to be installed as part of a project. This approach is also found with npm, the Node.js package manager. Using project-specific packs with SWI-Prolog requires calling attach_packs/2 before loading any library from a pack. To use (only) packs from the local sub directory `packs`, add this directive to the code that uses it:

    :- attach_packs(packs, [replace(true)]).

Packs can be installed into the `packs` directory directly using pack_install/2 with the `pack_directory(Dir)` option or using the `pack` app as

    swipl pack install --dir=packs <pack>

The preferred way is to use pack_install_local/3. This predicate takes a closure to collect the desired packages, creates an installation plan and executes this. This ensures a set of compatible packs at their latest available version or explicitly specified versions. Typically, one would create a file `packs.pl` according to the example below to install the packages required by a project. By using such a file it is easy to replicate a suitable set of installed packs for anyone who wishes to use your application.

    :- module(packs, []).
    :- use_module(library(prolog_pack)).
    :- attach_packs(packs, [replace(true)]).

    :- initialization(install, main).

    pack(scasp, [commit('HEAD')]).
    pack(environ, []).
    pack(date_time, []).

    install :-
        pack_install_local(pack, packs, []).

Here, the attach_packs/2 must be the same as used by the project. The first argument of pack_install_local/2 refers to pack/2 , generating a list of target packages and options for each package. The options for each pack are defined by pack_install/2. They typically refer to the download location and required version. Given the above, we can install the packages we need for a project using

    swipl packs.pl

Using GIT submodules

Alternative to the above, if the desired packs are all available as git repository, we can add packs to our git managed projects by adding the packs as git submodules to our project. For example, we add a pack to the `packs` directory as

    mkdir packs
    git submodule add https://github.com/SWI-Prolog/sCASP.git packs/scasp
    git submodule add https://github.com/fnogatz/tap.git tap

As above, we can must make our project use the local packs by calling pack_attach/2. After fetching all submodules we can build the foreign components and/or run the tests of the attached packs using the steps below

    ?- attach_packs(packs, [replace(true)]).
    ?- pack_rebuild.

Using git submodules gives full control of the pack versions you are using. It also makes you responsible of adding dependencies and taking care of version dependencies between packs. Finally, it limits you to using git based packages.