Prev |  |

## 6. Prerequisites for building NUT on different OSes

This chapter aims to list packages with the tools needed on a freshly minimally deployed worker to build as many targets of NUT recipes as possible, mainly the diverse driver and documentation types.

NUT codebase generally should not depend on particular operating system or kernel technology and version, and with the operating systems listed below one can benefit from use of containers (jails, zones) to build and test against numerous OS distributions on one physical or virtual machine, e.g. to cover non-regression with older tool kits while taking advantage of new releases.

- For Linux systems, we have notes on Custom NUT CI farm build agents: LXC multi-arch containers (or `docs/ci-farm-lxc-setup.txt` in NUT sources for up-to-date information)
- After installing the build prerequisites needed on your platform as listed below, you might want to follow up with Building NUT for in-place upgrades or non-disruptive tests (or `INSTALL.nut.adoc` in NUT sources for up-to-date information)

Some of the below are alternatives, e.g. compiler toolkits (gcc vs. clang) or SSL implementations (OpenSSL vs. Mozilla NSS) — no problem installing both, at a disk space cost.

### Note

Some NUT branches may need additional or different software versions that are not yet included into `master` branch dependencies, e.g. the DMF (Dynamic Mapping Files) sub-project needs LUA 5.1 for build and run-time, and some Python modules for build, e.g. using OS packaging or custom call to `pip install pycparser`.

In case your system still provides a Python 2.x environment (and for some reason you want to use it instead of Python 3.x), but does not anymore provide a `pip` nor `pycparser` packages for it, you may need to use an external bootstrap first, e.g.:

    # Fetch get-pip.py for python 2.7
    :; curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py
    :; python2 get-pip.py
    :; python2 -m pip --version
    :; python2 -m pip install pycparser

More packages and/or system setup may be needed to actually run NUT with all features enabled; chapters below concern just with building it.

### 6.1. General call to Test the ability to configure and build

Check out from git, generate files and configure to tailor to your build environment, and build some tests:

    :; mkdir -p nut && cd nut && \
        git clone https://github.com/networkupstools/nut/ -b master .
    :; ./autogen.sh && \
        ./configure --with-doc=all --with-all --with-cgi && \
        make all && make check && make spellcheck

You can toggle some `configure` options to check different dependency variants, e.g. `--with-ssl=nss` vs. `--with-ssl=openssl`

For reproducible runs of various pre-sets of configuration during development, take a look at `ci_build.sh` script and different `BUILD_TYPE` (and other) environment variable settings that it supports. A minimal run with it is just to call the script, possibly using an alternate source code branch of interest, e.g.:

    :; mkdir -p nut && cd nut && \
       git clone https://github.com/networkupstools/nut/ -b fightwarn .
    :; ./ci_build.sh

### Note

To build older releases, such as "vanilla" NUT 2.7.4 and older, you may need to address some nuances:

- Ensure that `python` in `PATH` points to a python-2.x implementation (`master` branch is fixed to work with python 2 and 3)
- Ensure that `bash` is your user and maybe system shell (or ensure the generated `configure` script gets interpreted by it)
- Generally you may have better results with GNU Make newer than 3.81 than with other make implementations; however, builds are regularly tested by CI with Sun dmake and BSD make as well, so recipes should not expect GNU-only syntax and constructs to work
- Parallel builds should be okay in current development version and since NUT 2.8.0 (is a bug to log and fix, if not), but they may be failure-prone in 2.7.4 and earlier releases

For intensive rebuilds, `ccache` is recommended. Note that instructions below detail how to provide its directory with symlinks as `/usr/lib/ccache` which is not the default case in all OS distributions. Recent versions of the NUT `ci_build.sh` script allow to override the location by using the `CI_CCACHE_SYMLINKDIR` environment variable, which is cumbersome and only recommended for build agents with immutable system areas, etc.

### 6.2. Build prerequisites to make NUT from scratch on various Operating Systems

#### Debian, Ubuntu and derivatives

### Note

Documented according to NUT CI farm build agents and development workstation running Debian 10/11/12/13 (should at least partially apply as far back as Debian 7/8), Ubuntu 14.x-25.x, and Termux revisions circa 2023-2025. This section generally covers a very wide family of APT-based Debian-derived Linux operating system distributions.

Being a popular baseline among Linux distributions, Debian is an important build target. Related common operating systems include Ubuntu and customized distros for Raspberry Pi, Proxmox, as well as many others.

For some (newer) distributions, `apt` or other front-ends may be preferable to `apt-get`, but otherwise the commands are equivalent.

The package list below should largely apply to those as well, however note that some well-known package names tend to differ. A few of those are noted below.

### Note

While Debian distros I’ve seen (8 to 11) provide a "libusb-dev" for libusb-0.1 headers, the binary library package name is specifically versioned package by default of the current release (e.g. "libusb-0.1-4"), while names of both the library and development packages for libusb-1.0 must be determined with:

    :; apt-cache search 'libusb.*1\.0.*'

yielding e.g. "libusb-1.0-0-dev" (string name was seen with different actual package source versions on both Debian 8 "Jessie" and Debian 11 "Buster").

### FUN NOTE

For development on the road (or a native ARM build) you can use the Termux project on Android. It provides a sufficiently Debian-like operating environment for all intents and purposes, but you may have to use their `pkg` wrapper instead of `apt` tooling directly, and `ldd` may be in a package separate from `binutils`, but otherwise the Debian/Ubuntu oriented lists of packages below apply.

You would need at least a couple of gigabytes available on the internal phone storage though, especially if using `ccache` or setting up cross builds.

The Termux distribution as of this writing seems to lack cppunit packages but you can build it from https://www.freedesktop.org/wiki/Software/cppunit/ e.g. `--with-prefix=${HOME}/nut-deps/usr` and `make install` there. A custom `PKG_CONFIG_PATH=${HOME}/nut-deps/usr/lib/pkgconfig` would find it during NUT build.

Debian-like package installations commonly start with an update of metadata about recently published package revisions:

    :; apt-get update

    :; apt-get install \
        ccache time \
        git perl curl \
        make autoconf automake libltdl-dev libtool binutils \
        valgrind \
        cppcheck \
        pkg-config \
        gcc g++ clang

    # To debug eventual core dump files, or trace programs with an IDE like
    # NetBeans (perhaps remotely), you may want the GNU Debugger program:
    :; apt-get install \
        gdb

    # NOTE: Older Debian-like distributions may lack a "libtool-bin"
    :; apt-get install \
        libtool-bin

    # See comments below, python version and package naming depends on distro
    :; apt-get install \
        python

    # NOTE: For python, you may eventually have to specify a variant like this
    # (numbers depending on default or additional packages of your distro):
    #   :; apt-get install python2 python2.7 python-is-python2
    # and/or:
    #   :; apt-get install python3 python3.9
    # You can find a list of what is (pre-)installed with:
    #   :; dpkg -l | grep -Ei 'perl|python'
    #
    # For localization maintenance (currently in Python NUT-Monitor app),
    # provide an `msgfmt` implementation, e.g.:
    #   :; apt-get install gettext
    #
    # To install the Python NUT-Monitor app, you may need some modules.
    # Ideally, they would be packaged, named according to major Python version:
    #   :; apt-get install python3-pyqt5
    # or on newer (2025+) releases,
    #   :; apt-get install python3-pyqt6 pyqt6-dev-tools
    #
    # If not packaged for your distro:
    #   :; apt-get install pip
    # For Python3:
    #   :; python3 -m pip install PyQt5 configparser
    # or
    #   :; python3 -m pip install PyQt6 configparser

    # For spell-checking, highly recommended if you would propose pull requests:
    :; apt-get install \
        aspell aspell-en

    # For other doc types (man-page, PDF, HTML) generation - massive packages
    # (TEX, X11):
    :; apt-get install \
        asciidoc source-highlight python3-pygments dblatex

    # For CGI graph generation - massive packages (X11):
    :; apt-get install \
        libgd-dev

    # Debian 13 serves metadata needed for NUT to find where to install the
    # service unit files in a separate development package; earlier distro
    # releases did not seem to require it explicitly:
    :; apt-get install \
        systemd-dev \
        || true

    # Optionally for sd_notify integration:
    :; apt-get install \
        libsystemd-dev

    # NOTE: Some older Debian-like distributions, could ship "libcrypto-dev"
    # and/or "openssl-dev" instead of "libssl-dev" by its modern name
    # and may lack a libgpiod2 + libgpiod-dev altogether
    # For NIT tests of SSL support you would also want key store management tools.
    :; apt-get install \
        libcppunit-dev \
        libssl-dev openssl \
        libnss3-dev libnss3-tools \
        augeas-tools libaugeas-dev augeas-lenses \
        libusb-dev libusb-1.0-0-dev \
        libglib2.0-dev \
        libi2c-dev \
        libmodbus-dev \
        libsnmp-dev \
        libpowerman0-dev \
        libfreeipmi-dev libipmimonitoring-dev \
        libavahi-common-dev libavahi-core-dev libavahi-client-dev
    # For libneon, see below

    # NOTE: On Termux the -dev suffixes may be missing, so you would need e.g.
    :; pkg install libnss nss-utils

    # NOTE: Older Debian-like distributions may lack a "libgpiod-dev"
    # Others above are present as far back as Debian 7 at least
    :; apt-get install \
        libgpiod-dev

    # NOTE: Some distributions lack a lua*-dev and only offer the base package
    :; apt-get install lua5.1
    :; apt-get install lua5.1-dev || true

    :; apt-get install \
        bash dash ksh busybox

Alternatives that can depend on your system’s other packaging choices:

    :; apt-get install libneon27-dev
    # ... or
    :; apt-get install libneon27-gnutls-dev

Over time, Debian and Ubuntu had different packages and libraries providing the actual methods for I2C; if your system lacks the `libi2c` (and so fails to `./configure --with-all`), try adding the following packages:

    :; apt-get install build-essential git-core libi2c-dev i2c-tools lm-sensors

For cross-builds (note that not everything supports multilib approach, limiting standard package installations to one or another implementation; in that case local containers each with one ARCH may be a better choice, with `qemu-user-static` playing a role to "natively" run the other-ARCH complete environments):

    :; apt-get install \
        gcc-multilib g++-multilib \
        crossbuild-essential \
        gcc-10:armhf gcc-10-base:armhf \
        qemu-user-static

### Note

For Jenkins agents, also need to `apt-get install openjdk-21-jdk-headless` (or `apt-get install openjdk-17-jdk-headless` on Debian 12 and older). You may have to ensure that `/proc` is mounted in the target chroot (or do this from the running container).

#### CentOS 6 and 7, Fedora 43

CentOS is another popular baseline among Linux distributions, being a free derivative of the RedHat Linux, upon which many other distros are based as well. These systems typically use the RPM package manager, using directly `rpm` command, or `yum` or `dnf` front-ends depending on their generation.

In fact, most of the instructions directly apply to much newer distributions like Fedora 43.

For CI farm container setup, prepared root filesystem archives from http://download.proxmox.com/images/system/ worked sufficiently well. For Fedora, https://images.linuxcontainers.org/images/fedora/43/amd64/default nightly image was used.

##### Prepare CentOS repository mirrors

For CentOS 7 it seems that not all repositories are equally good; some of the software below is only served by EPEL (Extra Packages for Enterprise Linux), as detailed at:

- https://docs.fedoraproject.org/en-US/epel/
- https://www.redhat.com/en/blog/whats-epel-and-how-do-i-use-it
- https://pkgs.org/download/epel-release

You may have to specify a mirror as the `baseurl` in a `/etc/yum.repos.d/...` file (as the aged distributions become less served by mirrors), such as:

- https://www.mirrorservice.org/sites/dl.fedoraproject.org/pub/epel/7/x86_64/

      # e.g. for CentOS7 currently:
      :; yum install \
         https://download-ib01.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-7-14.noarch.rpm

      # And edit /etc/yum.repos.d/epel.repo to uncomment and set the baseurl=...
      # lines, and comment away the mirrorlist= lines (if yum hiccups otherwise)

For systemd support on CentOS 7 (no equivalent found for CentOS 6), you can use backports repository below:

    :; curl https://copr.fedorainfracloud.org/coprs/jsynacek/systemd-backports-for-centos-7
        > /etc/yum.repos.d/systemd-backports-for-centos-7.repo

For CentOS 6 (the oldest I could try) the situation is similar, with sites like https://www.getpagespeed.com/server-setup/how-to-fix-yum-after-centos-6-went-eol detailing how to replace `/etc/yum.repos.d/` contents (you can wholesale rename the existing directory and populate a new one with `curl` downloads from the article), and additional key trust for EPEL packages:

    :; yum install \
       https://dl.fedoraproject.org/pub/archive/epel/6/x86_64/epel-release-6-8.noarch.rpm

##### Set up CentOS packages for NUT

Instructions below apply to both CentOS 6 and 7 (a few nuances for 6 commented). For newer distributions, `dnf` may be preferable to `yum`, but otherwise the commands are equivalent.

General developer system helpers mentioned in Custom NUT CI farm build agents: LXC multi-arch containers (or `docs/ci-farm-lxc-setup.txt` in NUT sources for up-to-date information):

    :; yum update

    :; yum install \
        sudo vim mc p7zip pigz pbzip2 tar

To have SSH access to the build VM/Container, you may have to install and enable it:

    :; yum install \
        openssh-server openssh-clients

    # On CentOS 6/7:
    :; chkconfig sshd on
    :; service sshd start

    # If there are errors loading generated host keys, remove mentioned files
    # including the one with .pub extension and retry with:
    #:; service sshd restart

### Note

Below we request to install generic `python` per system defaults. You may request specifically `python2` or `python3` (or both): current NUT should be compatible with both (2.7+ at least).

### Note

On CentOS, `libusb` means 0.1.x (not available on modern Fedora), and `libusbx` means 1.x.x API version (latter is not available for CentOS 6).

### Note

On CentOS, it seems that development against libi2c/smbus is not supported. Neither the suitable devel packages were found, nor i2c-based drivers in distro packaging of NUT. Resolution and doc PRs are welcome.

    :; yum install \
        ccache time \
        file \
        git perl curl \
        make autoconf automake libtool-ltdl-devel libtool \
        valgrind \
        cppcheck \
        pkgconfig \
        gcc gcc-c++ clang

    # To debug eventual core dump files, or trace programs with an IDE like
    # NetBeans (perhaps remotely), you may want the GNU Debugger program:
    :; yum install \
        gdb

    # See comments below, python version and package naming depends on distro
    :; yum install \
        python

    # NOTE: For python, you may eventually have to specify a variant like this
    # (numbers depending on default or additional packages of your distro):
    #   :; yum install python-2.7.5
    # and/or:
    #   :; yum install python3 python3-3.6.8
    # You can find a list of what is (pre-)installed with:
    #   :; rpm -qa | grep -Ei 'perl|python'
    # Note that CentOS 6 includes python-2.6.x and does not serve newer versions
    # For Fedora 43, further packages can be installed to test more:
    #   :; yum install python3-qt5 python3-setuptools

    # For spell-checking, highly recommended if you would propose pull requests:
    :; yum install \
        aspell aspell-en

    # For other doc types (man-page, PDF, HTML) generation - massive packages
    # (TEX, X11):
    :; yum install \
        asciidoc source-highlight python-pygments dblatex

    # For PDF generation, you may need explicitly (at least on Fedora 43):
    :; yum install \
        texlive 'tex(upquote.sty)'

    # For CGI graph generation - massive packages (X11):
    :; yum install \
        gd-devel

    # Optionally for sd_notify integration (on CentOS 7+, not on 6):
    :; yum install \
        systemd-devel

    # NOTE: "libusbx" is the CentOS way of naming "libusb-1.0" (not in CentOS 6)
    # vs. the older "libusb" as the package with "libusb-0.1" (not in recent Fedora)
    :; yum install \
        libusb-devel

    :; yum install \
        libusbx-devel

    :; yum install \
        cppunit-devel \
        openssl-devel nss-devel \
        augeas augeas-devel \
        glib2-devel \
        i2c-tools \
        libmodbus-devel \
        net-snmp-devel \
        freeipmi-devel \
        avahi-devel \
        neon-devel

    # For SSL testing (at least in Fedora 43) tools come in separate packages:
    :; yum install \
        openssl nss-tools

    # Not in recent Fedora releases:
    :; yum install \
        powerman-devel

    # Not in CentOS, some present in Fedora:
    #?# is python-augeas needed? exists at least...
    #?# no (lib)i2c-devel ...
    #?# no (lib)ipmimonitoring-devel ... would "freeipmi-ipmidetectd"
    #?#     cut it at least for run-time?
    #?# no (lib)gpio(d)-devel - starts with CentOS 8 (or extra repositories
    #?#     for later minor releases of CentOS 7)

    # In Fedora:
    :; yum install \
        libi2c-devel \
        libgpiod-devel

    # Some NUT code related to lua may be currently limited to lua-5.1
    # or possibly 5.2; the former is default in CentOS 7 releases...
    :; yum install \
        lua-devel

    :; yum install \
        bash dash ksh

    # If available:
    :; yum install \
        bash-completion

    # In Fedora:
    :; yum install \
        busybox

### Note

`busybox` is not packaged for CentOS 7 release; a static binary can be downloaded if needed. For more details, see https://unix.stackexchange.com/questions/475584/cannot-install-busybox-on-centos

CentOS packaging for 64-bit systems delivers the directory for dispatching compiler symlinks as `/usr/lib64/ccache`. You can set it up same way as for other described environments by adding a symlink `/usr/lib/ccache`:

    :; ln -s ../lib64/ccache/ "$ALTROOT"/usr/lib/

### Note

For Jenkins agents, also need to install JDK 17 or newer, which is not available for CentOS 6 nor 7 directly (in distribution packaging).

In Fedora e.g.:

    :; yum install \
        java-21-openjdk-headless

Alternative packaging for older distros, such as Temurin from the Adoptium project, is possible (checked for at least CentOS 7), see their instructions for specific details. This may require updated library package versions as dependencies from the OS distribution, so you may also have to make sure that your `/etc/yum.repos.d/*` files (certainly `CentOS-Base.repo`, maybe also `CentOS-fasttrack.repo` and/or `CentOS-CR.repo`) to use e.g.

    baseurl=https://vault.centos.org/centos/$releasever/os/$basearch/

lines if the `mirrorlist` ones do not suffice to find living mirrors (WARNING: the `/os/` part of the URL would vary for different repository types).

#### Arch Linux

Update the lower-level OS and package databases:

    :; pacman -Syu

Install tools and prerequisites for NUT:

    :; pacman -S --needed \
        base-devel \
        autoconf automake libtool libltdl \
        clang gcc \
        ccache \
        git \
        vim python perl \
        pkgconf \
        cppcheck valgrind

    # To debug eventual core dump files, or trace programs with an IDE like
    # NetBeans (perhaps remotely), you may want the GNU Debugger program:
    :; pacman -S --needed \
        gdb

    # For spell-checking, highly recommended if you would propose pull requests:
    :; pacman -S --needed \
        aspell en-aspell

    # For man-page doc types generation:
    :; pacman -S --needed \
        asciidoc

    # For other doc types (PDF, HTML) generation - massive packages (TEX, X11):
    :; pacman -S --needed \
        source-highlight dblatex

    # For CGI graph generation - massive packages (X11):
    :; pacman -S --needed \
        gd

    # Optionally for sd_notify integration:
    :; pacman -S --needed \
        systemd

    :; pacman -S --needed \
        cppunit \
        openssl nss \
        augeas \
        libusb \
        glib2 \
        neon \
        net-snmp \
        freeipmi \
        avahi

    #?# no (lib)gpio(d)

    :; pacman -S --needed \
        lua51

    :; pacman -S --needed \
        bash dash busybox ksh93

Recommended for NUT CI farm integration (matching specific toolkit versions in a build matrix), and note the unusual location of `/usr/lib/ccache/bin/` for symlinks:

    :; gcc --version
    gcc (GCC) 12.2.0
    ...

    # Note: this distro delivers "gcc" et al as file names
    # so symlinks like this may erode after upgrades.
    # TODO: Rename and then link?..
    :; (cd /usr/bin \
        && for V in 12 12.2.0 ; do for T in gcc g++ cpp ; do \
            ln -fsr $T $T-$V ; \
        done; done)
    :; (cd /usr/lib/ccache/bin/ \
        && for V in 12 12.2.0 ; do for T in gcc g++ ; do \
            ln -fsr /usr/bin/ccache $T-$V ; \
        done; done)

    :; clang --version
    clang version 14.0.6
    ...

    :; (cd /usr/bin && ln -fs clang-14 clang++-14 && ln -fs clang-14 clang-cpp-14)
    :; (cd /usr/lib/ccache/bin/ \
        && for V in 14 ; do for T in clang clang++ ; do \
            ln -fsr /usr/bin/ccache $T-$V ; \
        done; done)

Also for CI build agents, a Java environment (JDK17+ since autumn 2024) is required:

    # Search for available Java versions:
    :; pacman -Ss | egrep 'jre|jdk'

    # Pick one:
    :; pacman -S --needed \
        jre17-openjdk-headless

    # If needed to change default implementation, consult:
    :; archlinux-java help

#### Slackware Linux 15

Another long-term presence in the Linux landscape, and sometimes the baseline for appliances, the Slackware project recently hit release 15 in 2022, averaging two years per major release.

It can be installed e.g. in a VM, using ISO images from the project site; see:

- http://www.slackware.com/ ⇒ http://www.slackware.com/getslack/ ⇒ https://mirrors.slackware.com/slackware/slackware-iso/slackware64-15.0-iso/
- https://slackware.nl/slackware/slackware64-current-iso/

You would have to first log in as `root` and run `cgdisk` to define partitioning for your virtual HDD, such as the common `/boot`, `swap` and `/` Linux layout, and run `setup` to install "everything".

Note that "out of the box" Slackware does not currently on networked package repositories and calculated dependency trees, so one has to know exactly what they want installed.

Third-party projects for package managers are also available, e.g. `slackpkg` ⇒ see also https://docs.slackware.com/slackware:slackpkg and https://slackpkg.org/stable/ :

    :; wget https://slackpkg.org/stable/slackpkg-15.0.10-noarch-1.txz && \
       installpkg slackpkg-15.0.10-noarch-1.txz

Uncomment a mirror from `/etc/slackpkg/mirrors` according to your location and other preferences (or use the top-listed default), and begin with:

    :; slackpkg update

Note that packages may be only installed or re-installed/upgraded as separate explicit operations, so the procedure to bring your system into needed shape is a bit cumbersome (and each command may by default be interactive with a choice menu), e.g.:

    :; for P in \
        bash mc vim sudo \
       ; do slackpkg info "$P" || slackpkg install $P || break ; done

For procedures below, this is automated via `root` profile to become a `slackpkg-install` command:

    :; grep "slackpkg-install" ~/.profile || {
        cat >> ~/.profile << 'EOF'
    slackpkg-install() {
        for P in "$@" ; do
            echo "=== $P:"
            slackpkg info "$P" || slackpkg install "$P" || break
        done
    }
    EOF
       }
    :; . ~/.profile

If something has a hiccup, it suggests to look for the right name, e.g.:

    :; slackpkg search python

For NUT dependencies and build tools:

    :; slackpkg update

    # Baseline toolkits:
    # Note there is no cppcheck, cppunit, valgrind...
    # Note clang compiler tools are part of llvm package
    :; slackpkg-install \
        ccache time \
        coreutils diffutils \
        git python3 perl curl \
        make autoconf automake libtool binutils \
        pkg-config \
        gcc llvm

    # To debug eventual core dump files, or trace programs with an IDE like
    # NetBeans (perhaps remotely), you may want the GNU Debugger program:
    :; slackpkg-install gdb

    # For spell-checking, highly recommended if you would propose pull requests:
    :; slackpkg-install aspell{,-en}

    # Note there is no direct "asciidoc" nor "a2x", just the competing project
    # "rubygem-asciidoctor" that NUT currently has no recipes for, so you can
    # not compile man/html/pdf docs here, per the default repository. See below
    # for tools from alternative repositories, which seem to work well. Man page
    # compilation would require docbook-xml resources; older versions are in
    # this package https://slackbuilds.org/repository/15.0/system/docbook-xml/
    # and recent ones are in not-installed part of main repository:
    :; slackpkg-install linuxdoc-tools

    # More on Python (for NUT-Monitor UI):
    :; slackpkg-install \
        python-pip qt5 gettext-tools gettext
    # FIXME: Consider qt6 since 2025

    # For CGI graph generation - massive packages (X11):
    :; slackpkg-install \
        gd

    # General dependencies:
    :; slackpkg-install \
        openssl openssl-solibs mozilla-nss \
        libusb \
        glib2 \
        net-snmp \
        neon

    # Shells:
    :; slackpkg-install \
        bash dash ksh93

Some more packages are available on the side, including Java (useful e.g. to make this environment into a fully fledged Jenkins worker). Other common NUT dependencies absent from primary Slackware repositories can be found and downloaded (seek `*.txz` package files, although a few are named `*.tgz`) from here, and passed to `installpkg`:

- http://www.slackware.com/~alien/slackbuilds/openjdk17/
- http://www.slackware.com/~alien/slackbuilds/asciidoc/
- http://www.slackware.com/~alien/slackbuilds/cppunit/
- http://www.slackware.com/alien/slackbuilds/lua/ (5.1 in "stable") and http://www.slackware.com/alien/slackbuilds/lua53/ (5.4 in "current" as of Slackware 15.1 candidate in the works) — note that LUA is not needed for the current NUT code base, but may become needed after import of features from forks

…and even the environment for Windows cross-builds, ancient compilers and modern toolkits to cover all bases:

- http://www.slackware.com/~alien/slackbuilds/MinGW-w64/
- http://www.slackware.com/~alien/slackbuilds/docker/
- http://www.slackware.com/~alien/slackbuilds/gcc34/
- http://www.slackware.com/~alien/slackbuilds/gcc5/

FWIW, another "more official" but older Java package seems to be at:

- http://www.slackware.com/~alien/slackbuilds/openjdk/
- https://slackbuilds.org/repository/15.0/development/jdk/

An example routine to install the latest instance of a package could be like this:

    :; wget -m -l1 http://www.slackware.com/~alien/slackbuilds/asciidoc/pkg/ && \
        find . -name '*.t?z'

    :; (cd ./www.slackware.com/~alien/slackbuilds/asciidoc/pkg/ && \
        installpkgasciidoc-8.1.0-noarch-2.tgz )

Note that some packages are further separated by Slackware version, e.g. with sub-directories for `15.0` and `current`:

    :; wget -r -l1 -nd -R gif,css,jpg,html,htm --remove-listing \
        http://www.slackware.com/~alien/slackbuilds/openjdk17/pkg64/15.0/

    :; installpkg openjdk17-17.0.12_7-x86_64-1alien.txz

Upon community members' recommendations, Sotirov’s SlackPack is also considered a reputable repository: https://sotirov-bg.net/slackpack/ and should cover most if not all of the dependencies required for NUT building (including PowerMan, IPMI etc.)

### Note

If setting up a CI farm agent with builds in RAM disk, keep in mind that default mount options for `/dev/shm` preclude script execution. Either set up the agent in a non-standard fashion (to use another work area), or if this is a dedicated machine — relax the mount options in `/etc/fstab`.

Here is an example with `noexec` which we must avoid for such use-case:

    :; mount | grep /dev/shm
    tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,inode64)

#### FreeBSD 12.2

### Note

As of 2024, this version is way beyond EOL — packages have been removed from mirrors. A discussion at https://forums.freebsd.org/threads/easy-upgrading-from-12-2-rel-in-2024.92695/ touches on upgrades in such situation. An alternate mirror (that worked to bump the system to `openjdk17`, as of this writing in Nov 2024) can be found at https://mirror.sg.gs/freebsd-pkg/FreeBSD:12:amd64/quarterly/ and written into `/etc/pkg/FreeBSD.conf` similarly to existing `url` entry.

Note that `PATH` for builds on BSD should include `/usr/local/...`:

    :; PATH=/usr/local/libexec/ccache:/usr/local/bin:/usr/bin:$PATH
    :; export PATH

### Note

You may want to reference `ccache` even before all that, as detailed below.

    :; pkg install \
        git perl5 curl \
        gmake autoconf automake autotools libltdl libtool \
        valgrind \
        cppcheck \
        pkgconf \
        gcc clang

    # To debug eventual core dump files, or trace programs with an IDE like
    # NetBeans (perhaps remotely), you may want the GNU Debugger program:
    :; pkg install \
        gdb

    # See comments below, python version and package naming depends on distro
    :; pkg install \
        python

    # NOTE: For python, you may eventually have to specify a variant like this
    # (numbers depending on default or additional packages of your distro):
    #   :; pkg install python2 python27
    # and/or:
    #   :; pkg install python3 python37
    # You can find a list of what is (pre-)installed with:
    #   :; pkg info | grep -Ei 'perl|python'

    # For spell-checking, highly recommended if you would propose pull requests:
    :; pkg install \
        aspell en-aspell

    # For other doc types (man-page, PDF, HTML) generation - massive packages
    # (TEX, X11):
    :; pkg install \
        asciidoc source-highlight textproc/py-pygments dblatex

    # For CGI graph generation - massive packages (X11):
    :; pkg install \
        libgd

    :; pkg install \
        cppunit \
        nss \
        augeas \
        libusb \
        glib \
        libmodbus \
        neon \
        net-snmp \
        powerman \
        freeipmi \
        avahi

    # NOTE: At least on FreeBSD 12, system-provided crypto exists and is used
    # by libnetsnmp, libneon, etc. - but is not marked as a package. Conversely,
    # the openssl-1.1.1k (as of this writing) can be installed as a package into
    # /usr/local/lib and then causes linking conflicts. The core system-provided
    # build of openssl does include headers and is useful for NUT build "as is".
    # ONLY INSTALL THIS PACKAGE IF REQUIRED (may get problems to rectify later):
    :; test -e /lib/libcrypto.so -a -e /usr/lib/libssl.so || \
       pkg install openssl

    :; pkg install \
        lua51

    :; pkg install \
        bash dash busybox ksh93

Recommended:

    :; pkg install ccache
    :; ccache-update-links

For compatibility with common setups on other operating systems, can symlink `/usr/local/libexec/ccache` as `/usr/lib/ccache` and possibly add dash-number suffixed symlinks to compiler tools (e.g. `gcc-10` beside `gcc10` installed by package).

### Note

For Jenkins agents, also need to `pkg install openjdk11` (17 or 21 required since autumn 2024) — and do note its further OS configuration suggestions for special filesystem mounts.

Due to BSD specific paths when not using an implementation of `pkg-config` or `pkgconf` (so guessing of flags is left to administrator — TBD in NUT `m4` scripts), better use this routine to test the config/build:

    :; ./configure --with-doc=all --with-all --with-cgi \
        --without-avahi --without-powerman --without-modbus \
        ### CPPFLAGS="-I/usr/local/include -I/usr/include" \
        ### LDFLAGS="-L/usr/local/lib -L/usr/lib"

Note the lack of `pkg-config` also precludes `libcppunit` tests, although they also tend to mis-compile/mis-link with GCC (while CLANG seems okay).

#### OpenBSD 6.5

Note that `PATH` for builds on BSD should include `/usr/local/...`:

    :; PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH
    :; export PATH

### Note

You may want to reference `ccache` even before all that, as detailed below.

OpenBSD delivers many versions of numerous packages, you should specify your pick interactively or as part of package name (e.g. `autoconf-2.69p2`).

### Note

For the purposes of builds with Jenkins CI agents, since summer 2022 it requires JDK11 which was first delivered with OpenBSD 6.5. Earlier iterations used OpenBSD 6.4 and version nuances in this document may still reflect that.

FIXME: Since autumn 2024, JDK17+ is required. Maybe time to EOL OpenBSD 6.x workers, or to SSH into them from a nearby machine’s Java agent?.. Alternately, consider https://github.com/adoptium/jdk17/blob/master/doc/building.md

During builds, you may have to tell system dispatcher scripts which version to use (which feels inconvenient, but on the up-side for CI — this system allows to test many versions of auto-tools in the same agent), e.g.:

    :; export AUTOCONF_VERSION=2.69 AUTOMAKE_VERSION=1.13

To use the `ci_build.sh` don’t forget `bash` which is not part of OpenBSD base installation. It is not required for "legacy" builds arranged by just `autogen.sh` and `configure` scripts.

### Note

The OpenBSD 6.5 `install65.iso` installation includes a set of packages that seems to exceed whatever is available on network mirrors; for example, the CD image included `clang` program while it is not available to `pkg_add`, at least not via http://ftp.netbsd.hu/mirrors/openbsd/6.5/packages/amd64/ mirror. The `gcc` version on CD image differed notably from that in the networked repository (4.2.x vs. 4.9.x).

You may have to echo a working base URL (part before "6.5/…" into the `/etc/installurl` file, since the old distribution is no longer served by default site.

Verify that the unprivileged account used for builds (e.g. `abuild`) has sufficient resource permissions, especially for "open files" and "max user processes", by running `ulimit -a`. You can ensure larger values if needed via `/etc/login.conf` e.g. add this new login class per example below (see https://man.openbsd.org/login.conf.5 and https://wiki.ircnow.org/index.php?n=Openbsd.Loginconf for more details), assign the login class to your CI and/or personal account with `usermod -L abuild $USER`, and run `cap_mkdb /etc/login.conf` and re-login that account to check that the change got applied:

    abuild:\
            :maxproc=infinity:\
            :datasize=infinity:\
            :openfiles=infinity:\
            :stacksize-cur=8M

Finally, as `root` add the packages:

    # Optionally, make the environment comfortable, e.g.:
    :; pkg_add sudo bash mc wget rsync

    :; pkg_add \
        git curl \
        gmake autoconf automake libltdl libtool \
        valgrind \
        cppcheck \
        pkgconf \
        gcc clang

    # To debug eventual core dump files, or trace programs with an IDE like
    # NetBeans (perhaps remotely), you may want the GNU Debugger program:
    :; pkg_add install \
        gdb

    # See comments below, python version and package naming depends on distro
    :; pkg_add \
        python

    # NOTE: For python, you may eventually have to specify a variant like this
    # (numbers depending on default or additional packages of your distro):
    #   :; pkg_add python-2.7.15p0 py-pip
    # and/or:
    #   :; pkg_add python-3.6.6p1 py3-pip
    # although you might succeed specifying shorter names and the packager
    # will offer a list of matching variants (as it does for "python" above).
    # NOTE: "perl" is not currently a package, but seemingly part of base OS.
    # You can find a list of what is (pre-)installed with:
    #   :; pkg_info | grep -Ei 'perl|python'

    # For spell-checking, highly recommended if you would propose pull requests:
    :; pkg_add \
        aspell

    # For other doc types (man-page, PDF, HTML) generation - massive packages
    # (TEX, X11):
    :; pkg_add \
        asciidoc source-highlight py-pygments dblatex \
        docbook2x docbook-to-man

    # For CGI graph generation - massive packages (X11):
    :; pkg_add \
        gd

    :; pkg_add \
        cppunit \
        openssl nss \
        augeas \
        libusb1 \
        glib2 \
        net-snmp \
        avahi

    # For netxml-ups driver the library should suffice; however for nut-scanner
    # you may currently require to add a `libneon.so` symlink (the package seems
    # to only deliver a numbered SO library name), e.g.:
    :; pkg_add neon && \
       if ! test -s /usr/local/lib/libneon.so ; then
        ln -s "`cd /usr/local/lib && ls -1 libneon.so.* | sort -n | tail -1`" \
            /usr/local/lib/libneon.so
       fi

    # Select a LUA-5.1 (or possibly 5.2?) version
    :; pkg_add \
        lua

    :; pkg_add \
        bash dash ksh93

    :; pkg_add \
        argp-standalone \
        freeipmi

Recommended:

    :; pkg_add ccache
    :; ( mkdir -p /usr/lib/ccache && cd /usr/lib/ccache && \
            for TOOL in cpp gcc g++ clang clang++ clang-cpp ; do \
                ln -s ../../local/bin/ccache "$TOOL" ; \
            done ; \
       )

    :; ( cd /usr/bin && for T in gcc g++ cpp ; \
        do ln -s "$T" "$T-4.2.1" ; done )
    :; ( cd /usr/lib/ccache && for T in gcc g++ cpp ; \
        do ln -s "$T" "$T-4.2.1" ; done )

    :; ( cd /usr/bin && for T in clang clang++ clang-cpp ; \
        do ln -s "$T" "$T-7.0.1" ; done )
    :; ( cd /usr/lib/ccache && for T in clang clang++ clang-cpp ; \
        do ln -s "$T" "$T-7.0.1" ; done )

For compatibility with common setups on other operating systems, can add dash-number suffixed symlinks to compiler tools (e.g. `gcc-4.2.1` beside `gcc` installed by package) into `/usr/lib/ccache`.

### Note

For Jenkins agents, also need to `pkg_add jdk` (if asked, pick version 11 or 17); can request `pkg_add jdk%11`. You would likely have to update the trusted CA store to connect to NUT CI, see e.g. (raw!) download from https://gist.github.com/galan/ec8b5f92dd325a97e2f66e524d28aaf8 but ensure that you run it with `bash` and it does `wget` the certificates (maybe with `--no-check-certificate` option if the OS does not trust current internet infrastructure either), and revise the suggested certificate files vs. https://letsencrypt.org/certificates/ and/or comments to that gist.

Due to BSD specific paths when not using an implementation of `pkg-config` or `pkgconf` (so guessing of flags is left to administrator — TBD in NUT `m4` scripts), better use this routine to test the config/build:

    :; ./configure --with-doc=all --with-all --with-cgi \
        --without-avahi --without-powerman --without-modbus \
        ### CPPFLAGS="-I/usr/local/include -I/usr/include"
        ### LDFLAGS="-L/usr/local/lib -L/usr/lib"

Note the lack of `pkg-config` also precludes `libcppunit` tests, although they also tend to mis-compile/mis-link with GCC (while CLANG seems okay).

#### NetBSD 9.2, 11.0 (Beta)

Instructions below assume that `pkgin` tool (pkg-src component to "install binary packages") is present on the system. Text below was prepared with a VM where "everything" was installed from the ISO image, including compilers and X11. It is possible that some packages provided this way differ from those served by `pkgin`, or on the contrary, that the list of suggested tool installation below would not include something a bare-minimum system would require to build NUT.

Note that `PATH` for builds on NetBSD should include `local` and `pkg`; the default after installation of the test system was:

    :; PATH="/sbin:/usr/sbin:/bin:/usr/bin:/usr/pkg/sbin:/usr/pkg/bin"
    :; PATH="$PATH:/usr/X11R7/bin:/usr/local/sbin:/usr/local/bin"
    :; export PATH

### Note

You may want to reference `ccache` even before all that, e.g. in the system-wide `/etc/profile` or build-user’s `~/.profile`, as detailed below:

    :; PATH="/usr/lib/ccache:$PATH"
    :; export PATH

To use the `ci_build.sh` don’t forget `bash` which may be not part of NetBSD base installation. It is not required for "legacy" builds arranged by just `autogen.sh` and `configure` scripts.

Also note that the `install-sh` helper added by autotools from OS-provided resources when generating the `configure` script may be old and its directory creation mode is not safe for parallel-`make` installations. If this happens, you can work around by `make MKDIRPROG="mkdir -p" install -j 8` for example.

### Note

Instructions below rely on `pkgin`, an `apt`/`yum`-like front-end tool for managing pkgsrc binary packages. It is available out of the box on the system this document describes, but if an e.g. older release lacks it, it can be added using the older tooling:

    :; CDN="http://cdn.NetBSD.org/pub/pkgsrc/packages/NetBSD"
    :; PKG_PATH="${CDN}/$(uname -p)/$(uname -r|cut -f '1 2' -d.)/All/"
    :; export PKG_PATH
    :; pkg_add pkgin

If you are using a test version that identifies like `11.0_BETA`, the `PKG_PATH` definition above may include that but the package repository might not serve the URL spelled as such. Trim it down to `11.0` manually then.

For more details, see https://www.pkgsrc.org/#index1h1 and https://www.librebyte.net/en/cli-en/pkgin-a-netbsd-package-manager/ (the latter also provides a nice cheat-sheet about `pkgin` operations).

### Note

On NetBSD 9.2 and 11 the `openpimi` and `net-snmp` packages complain that they require either OS ABI 9.0, or that `CHECK_OSABI=no` is set in a `pkg_install.conf`. Such file was not found in the test system, but can be created in `/etc/` and is honoured by `pkgin`:

    :; grep CHECK_OSABI /etc/pkg_install.conf || \
        ( echo CHECK_OSABI=no >> /etc/pkg_install.conf )

Some packages include the software version in the name (so several variants may be installed side by side), so instructions below vary slightly depending on the OS distribution version:

    :; pkgin install \
        git perl curl \
        mozilla-rootcerts mozilla-rootcerts-openssl \
        bmake gmake autoconf automake libltdl libtool \
        cppcheck \
        pkgconf \
        clang

    # NOTE: ccache is installed and links configured for it below

    # NetBSD 9.2:
    :; pkgin install \
        gcc7 gcc14

    # NetBSD 11:
    :; pkgin install \
        gcc15

    # See comments below, python version and package naming depends on distro
    # NetBSD 9.2:
    :; pkgin install \
        python27 python39 python312 python313

    # NetBSD 11 (to cover the max testing scope with both python generations):
    :; pkgin install python27 python314

    :; ( cd /usr/pkg/bin && ( ln -fs python2.7 python2 ; ln -fs python3.13 python3 ) )
    # You can find a list of what is (pre-)installed with:
    #   :; pkgin list | grep -Ei 'perl|python'

    # For localization maintenance (currently in Python NUT-Monitor app),
    # provide an `msgfmt` implementation, e.g.:
    #   :; pkgin install gettext
    #
    # To install the Python NUT-Monitor app, you may need some modules:
    # For Python2:
    #   :; pkgin install py27-gtk2
    # For Python3:
    # * NetBSD 9.2:
    #   :; pkgin install py312-qt5 py313-qt5
    # * NetBSD 11:
    #   :; pkgin install py314-qt6

    # For spell-checking, highly recommended if you would propose pull requests:
    :; pkgin install \
        aspell aspell-en

    # For man-page doc types, footprint on this platform is moderate:
    :; pkgin install \
        asciidoc

    # FIXME: Missing packages?
    # For other doc types (PDF, HTML) generation - massive packages (TEX, X11):
    # :; pkgin install \
    #    source-highlight py39-pygments dblatex

    # For CGI graph generation - massive packages (X11):
    :; pkgin install \
        gd openmp

    :; pkgin install \
        cppunit \
        openssl nss \
        augeas \
        libusb libusb1 \
        glib2 \
        neon \
        net-snmp \
        avahi

    # Select a LUA-5.1 (or possibly 5.2?) version
    :; pkgin install \
        lua51 # lua52

    :; pkgin install \
        bash dash ast-ksh oksh

### Note

There seems to be no FreeIPMI for NetBSD, but there’s OpenIPMI (can help someone implementing actual support for it):

    :; pkgin install \
        openipmi

It still seems to not work for NUT’s expectations of FreeIPMI (we have basic detection support for OpenIPMI but no code yet).

Recommended: For compatibility with common setups on other operating systems, can add dash-number suffixed symlinks to compiler tools (e.g. `gcc-7` beside the `gcc` installed by package) near the original binaries and into `/usr/lib/ccache`; use the numbers according to what you do have installed:

    :; ( cd /usr/pkg/bin && for TOOL in cpp gcc g++ ; do \
            for VER in "7" "14" ; do \
                ln -fs "../gcc${VER}/bin/${TOOL}" "${TOOL}-${VER}" ; \
            done ; \
         done )

    # Note that the one delivered binary is `clang-13` (in originally described
    # NetBSD 9.x installation; `clang-18` after an update in 2025 which auto-removed
    # the older version) and many (unnumbered) symlinks to it. For NUT CI style of
    # support for builds with many compilers, complete the known numbers:
    :; ( cd /usr/pkg/bin && for TOOL in clang-cpp clang++ ; do \
            for VER in "-18" ; do \
                ln -s clang"${VER}" "${TOOL}${VER}" ; \
            done ; \
         done )

    :; pkgin install ccache
    :; ( mkdir -p /usr/lib/ccache && cd /usr/lib/ccache && \
            for TOOL in cpp gcc g++ clang ; do \
                for VER in "" "-7" "-14" ; do \
                    ln -s ../../pkg/bin/ccache "${TOOL}${VER}" ; \
                done ; \
            done ; \
            for TOOL in clang clang++ clang-cpp ; do \
                for VER in "" "-18" ; do \
                    ln -s ../../pkg/bin/ccache "${TOOL}${VER}" ; \
                done ; \
            done ; \
       )

### Note

For Jenkins agents, also need to `pkgin install openjdk21` (will be in `JAVA_HOME=/usr/pkg/java/openjdk21`). Note that the location may be not exposed in `PATH` by default, so you may want to edit your system-wide `/etc/profile` or build user’s `~/.profile` with:

    JAVA_HOME="/usr/pkg/java/openjdk21"
    export JAVA_HOME
    PATH="${JAVA_HOME}/bin:${PATH}"
    export PATH

#### OpenIndiana as of releases 2021.10 to 2024.04

Note that due to IPS and `pkg(5)`, a version of python is part of baseline illumos-based OS; this may not be the case on some other illumos distributions which do not use IPS however. Currently they use python 3.7 or newer.

To build older NUT releases (2.7.4 and before), you may need to explicitly `pkg install python-27`.

Typical tooling would include:

    :; pkg install \
        git curl wget \
        gnu-make autoconf automake libltdl libtool \
        valgrind \
        pkg-config \
        gnu-binutils developer/linker

    # To debug eventual core dump files, or trace programs with an IDE like
    # NetBeans (perhaps remotely), you may want the GNU Debugger program:
    :; pkg install \
        gdb

    # NOTE: For python, some suitable version should be available since `pkg(5)`
    # tool is written in it. Similarly, many system tools are written in perl
    # so some version should be installed. You may specify additional variants
    # like this (numbers depending on default or additional packages of your
    # distro; recommended to group `pkg` calls with many packages at once to
    # save processing time for calculating a build strategy):
    #   :; pkg install runtime/python-27
    # and/or:
    #   :; pkg install runtime/python-37 runtime/python-35 runtime/python-39
    # Similarly for perl variants, e.g.:
    #   :; pkg install runtime/perl-522 runtime/perl-524 runtime/perl-534
    # You can find a list of what is available in remote repositories with:
    #   :; pkg info -r | grep -Ei 'perl|python'

    # For spell-checking, highly recommended if you would propose pull requests:
    :; pkg install \
        aspell text/aspell/en

    # For other doc types (man-page, PDF, HTML) generation - massive packages
    # (TEX, X11):
    :; pkg install \
        asciidoc libxslt \
        docbook/dtds docbook/dsssl docbook/xsl docbook docbook/sgml-common \
        pygments-39 \
        image/graphviz expect graphviz-tcl

    # For CGI graph generation - massive packages (X11):
    :; pkg install \
        gd

    :; pkg install \
        openssl library/mozilla-nss \
        library/augeas python/augeas \
        libusb-1 libusbugen system/library/usb/libusb \
        system/header/header-usb driver/usb/ugen \
        glib2 \
        libmodbus \
        library/neon \
        system/management/snmp/net-snmp \
        system/management/powerman \
        freeipmi \
        avahi

    # For tests with NSS, the certutil tool is needed:
    :; pkg install \
        system/mozilla-nss

    # With 2024.04, some packages were split for development vs. run-time
    # and/or based on architecture:
    :; pkg install \
        system/library/mozilla-nss/header-nss \
        library/nspr library/nspr/32

    :; pkg install \
        lua

    :; pkg install \
        dash bash shell/ksh93

    ### Maybe
    :; pkg install \
        gnu-coreutils

    ### Maybe - after it gets fixed for GCC builds/linkage
    :; pkg install \
        cppunit

For extra compiler coverage, we can install a large selection of versions, although to meet NUT CI farm expectations we also need to expose "numbered" filenames, as automated below:

    # NOTE: not all compiler versions may be served, some are obsoleted over time.
    # Check current distro repository offers with:
    :; pkg info -r '*clang*' '*gcc*'
    :; pkg search -r '*bin/g++*'
    :; pkg search -r '*bin/clang++*'

    :; pkg install \
        gcc-48 gcc-49 gcc-5 gcc-6 gcc-7 gcc-9 gcc-10 gcc-11 \
        clang-80 clang-90 \
        ccache

    # As of this writing, clang-13 refused to link (claiming issues with
    # --fuse-ld which was never specified) on OI; maybe later it will:
    #:; pkg install \
    #    developer/clang-13 runtime/clang-13

    # With OI 2024.04 there's also clang-18 available in the mix, and as of
    # 2025 packaging, clang-19 as well:
    :; pkg install \
        developer/clang-19 runtime/clang-19

    # Get clang-cpp-X visible in standard PATH (for CI to reference the right one),
    # and make sure other frontends are exposed with versions (not all OI distro
    # releases have such symlinks packaged right), e.g.:
    :; (cd /usr/bin && for X in 8 9 19 ; do for T in "" "++" "-cpp"; do \
        ln -fs "../clang/$X.0/bin/clang$T" "clang${T}-${X}" ; \
       done; done)

    # If /usr/lib/ccache/ symlinks to compilers do not appear after package
    # installation, or if you had to add links like above, call the service:
    :; svcadm restart ccache-update-symlinks

We can even include a `gcc-4.4.4-il` version (used to build the illumos OS ecosystems, at least until recently, which is a viable example of an old GCC baseline); but note that so far it conflicts with `libgd` builds at `./configure --with-cgi` stage (its binaries require newer ecosystem):

    :; pkg install \
        illumos-gcc@4.4.4

    # Make it visible in standard PATH
    :; (cd /usr/bin && for T in gcc g++ cpp ; do \
        ln -s ../../opt/gcc/4.4.4/bin/$T $T-4.4.4 ; \
       done)

    # If /usr/lib/ccache/ symlinks to these do not appear, call the service:
    :; svcadm restart ccache-update-symlinks

OI currently also does not build `cppunit`-based tests well, at least not with GCC (they segfault at run-time with `ostream` issues); a CLANG build works for that however.

It also lacks out-of-the-box Tex suite and `dblatex` in particular, which `asciidoc` needs to build PDF documents. It may be possible to add these from third-party repositories (e.g. SFE) and/or build from sources.

No pre-packaged `cppcheck` was found, either.

### Note

For Jenkins agents, also need to `pkg install runtime/java/openjdk17` for JRE/JDK 17. Java 17 or 21 is required to run Jenkins agents after autumn 2024. If updating from older releases, you may need to update default implementation, e.g.:

    :; pkg set-mediator -V 17 java

#### OmniOS CE (as of releases 151036 - 151052)

Being a minimal-footprint system, OmniOS CE provides very few packages out of the box. There are additional repositories supported by the project, as well as third-party repositories such as SFE. For some dependencies, it may happen that you would need to roll and install your own builds in accordance with that project’s design goals.

Note you may need not just the "Core" IPS package publisher, but also the "Extra" one. As of release 151052, it can be attached right in the installer; otherwise the `pkg (set-)publisher` commands can be used. See OmniOS CE web site for setup details.

    # Optionally, make the environment comfortable, e.g.:
    :; pkg install sudo bash application/mc wget rsync pigz pbzip2 p7zip top

    # NOTE: not all compiler versions may be served by all releases (e.g. OmniOS
    # did not deliver clang in Core nor Extra repositories for quite a while),
    # and some are obsoleted over time. While OmniOS 151036 lacked any clang,
    # LTS 151046 offered a range of clang 13 to 17, and current stable (151052)
    # includes also 18 and 19. Unlike OpenIndiana, OmniOS does not provide
    # implicit default (not-numbered) packages for neither clang nor gcc.
    # Check your distro repository offers with:
    :; pkg info -r '*clang*' '*gcc*'
    :; pkg search -r '*bin/g++*'
    :; pkg search -r '*bin/clang++*'

    # Then install a suitable one, e.g.:
    :; pkg install \
        developer/clang-17

    :; pkg install \
        developer/build/autoconf developer/build/automake \
        developer/build/libtool library/libtool/libltdl \
        build-essential ccache git developer/pkg-config \
        runtime/perl \
        glib \
        asciidoc \
        libgd

    # To debug eventual core dump files, or trace programs with an IDE like
    # NetBeans (perhaps remotely), you may want the GNU Debugger program:
    :; pkg install \
        gdb

    # May be or not be provided, depending on distro age:
    :; pkg install \
        net-snmp

    # For crypto-enabled builds:
    :; pkg install \
        openssl-3

    # By r151046, some packages were split for development vs. run-time;
    # to provide support for Mozilla NSS, you need libraries and headers:
    :; pkg install \
        system/library/mozilla-nss \
        system/library/mozilla-nss/header-nss \
        library/nspr library/nspr/header-nspr

    # NOTE: For python, some suitable version should be available since `pkg(5)`
    # tool is written in it. You may specify an additional variant like this
    # (numbers depending on default or additional packages of your distro):
    #   :; pkg install runtime/python-37
    # You can find a list of what is available in remote repositories with:
    #   :; pkg info -r | grep -Ei 'perl|python'

Your OmniOS version may lack a pre-packaged libusb, however the binary build from contemporary OpenIndiana can be used (copy the header files and the library+symlinks for all architectures you would need).

### Note

As of July 2022, a `libusb-1` package recipe was proposed for the `omnios-extra` repository (NUT itself and further dependencies may also appear there, per issue #1498), and is available as of release 151046 and later on:

    :; pkg install \
        libusb-1

You may need to set up `ccache` with the same `/usr/lib/ccache` dir used in other OS recipes. Assuming your Build Essentials pulled GCC 11 version, and ccache is under `/opt/ooce` namespace, that would be like:

    :; GCCVER=11
    :; mkdir -p /usr/lib/ccache
    :; cd /usr/lib/ccache
    :; ln -fs ../../../opt/ooce/bin/ccache gcc
    :; ln -fs ../../../opt/ooce/bin/ccache g++
    :; ln -fs ../../../opt/ooce/bin/ccache gcpp
    :; ln -fs ../../../opt/ooce/bin/ccache gcc-${GCCVER}
    :; ln -fs ../../../opt/ooce/bin/ccache g++-${GCCVER}
    :; ln -fs ../../../opt/ooce/bin/ccache gcpp-${GCCVER}

Given that many of the dependencies can get installed into that namespace, you may have to specify where `pkg-config` will look for them (note that library and binary paths can be architecture bitness-dependent; the `ci_build.sh` script should take care of this for many scenarios):

    :; ./configure PKG_CONFIG_PATH="/opt/ooce/lib/amd64/pkgconfig" --with-cgi

You may also have to fiddle with either `LD_LIBRARY_PATH`, `crle (-c)` or `./configure --with-something-libs` options to compensate for lack of `-R` linker options in the `pkg-config` information provided by that repository: by default the NUT programs can build with the information they get, but fail to find the needed shared objects at run-time. More about this situation is tracked at https://github.com/networkupstools/nut/issues/2782

Note also that the minimal footprint nature of OmniOS CE precludes building any large scope easily, so avoid docs and "all drivers" unless you provide whatever they need to happen.

### Note

For Jenkins agents, also need to `pkg install runtime/java/openjdk21` for JRE/JDK 17. Java 17 or 21 is required to run Jenkins agents after autumn 2024. If updating from older releases, you may need to update default implementation, e.g.:

    :; pkg set-mediator -V 21 java

#### Solaris 8

Builds for a platform as old as this are not currently covered by regular NUT CI farm runs, however since the very possibility of doing this was recently verified, some notes follow.

For context: Following a discussion in the mailing list starting at https://alioth-lists.debian.net/pipermail/nut-upsuser/2022-December/013051.html and followed up by GitHub issues and PR:

- https://github.com/networkupstools/nut/issues/1736
- https://github.com/networkupstools/nut/issues/1737 (about a possible but not yet confirmed platform problem)
- https://github.com/networkupstools/nut/pull/1738

…recent NUT codebase was successfully built and self-tested in a Solaris 8 x86 VM (a circa 2002 release), confirming the project’s adherence to the goal that if NUT ran on a platform earlier, so roughly anything POSIX-ish released this millennium and still running, it should still be possible — at least as far as our part of equation is concerned.

That said, platform shows its age vs. later standards (script interpreters and other tools involved), and base "complete install" lacked compilers, so part of the tested build platform setup involved third-party provided package repositories.

One helpful project was extensive notes about preparation of the Solaris 8 VM (and our further comments there), which pointed to the still active "tgcware" repository and contains scripts to help prepare the freshly installed system:

- https://github.com/mac-65/Solaris_8_x86_VM
- https://github.com/mac-65/Solaris_8_x86_VM/issues/1
- http://jupiterrise.com/tgcware/sunos5.8_x86/stable/

Note that scripts attached to the notes refer to older versions of the packages than what is currently published, so I ended up downloading everything from the repository into the VM and using shell wildcards to pick the packages to install (mind the package families with similar names when preparing such patterns).

After the OS, tools and feasible third-party dependencies were installed, certain environment customization was needed to prepare for NUT build in particular (originally detailed in GitHub issues linked above):

- For `CONFIG_SHELL`, system `dtksh` seems to support the syntax (unlike default `/bin/sh`), but for some reason segfaults during `configure` tests. Alternatively `/usr/tgcware/bin/bash` (4.4-ish) can be used successfully. System-provided bash 2.x is too old for these scripts.
- To run `ci_build.sh` CI/dev-testing helper script, either the shebang should be locally fixed to explicitly call `/usr/tgcware/bin/bash`, or the build environment’s `PATH` should point to this `bash` implementation as a first hit. If we want to primarily use OS-provided tools, this latter option may need a bit of creative setup; I made a symlink into the `/usr/lib/ccache` directory which has to be first anyway (before compilers).
- The system-provided default `grep` lacks the `-E` option which was preferred over generally obsoleted `egrep` since PR #1660— however pre-pending `/usr/xpg4/bin` early in the `PATH` fixes the problem.
- The builds of `gcc` in TGCWARE repository were picky about shared objects linking as needed to run them, so `LD_LIBRARY_PATH` had to refer to its library directories (generally this is frowned upon and should be a last resort).
- Due to lack of Python in that OS release, NUT augeas support had to be disabled when preparing the build from Git sources (generated files may be available as part of distribution tarballs however): `WITHOUT_NUT_AUGEAS=true; export WITHOUT_NUT_AUGEAS; ./autogen.sh`

Overall, the successful test build using the NUT standard CI helper script `ci_build.sh` had the following shell session settings:

    ### Common pre-sets from .profile or .bashrc (long lines wrapped for readability):
    ### bash-2.03$ echo $PATH
    ###   /usr/bin:/usr/dt/bin:/usr/openwin/bin:/bin:/usr/ucb:/usr/tgcware/bin:\
    ###   /usr/tgcware/gnu:/usr/tgcware/gcc42/bin:/usr/tgcware/i386-pc-solaris2.8/bin

    ### bash-2.03$ echo $LD_LIBRARY_PATH
    ###   /usr/lib:/usr/tgcware/lib:/usr/tgcware/gcc42/lib:\
    ###   /usr/tgcware/i386-pc-solaris2.8/lib

    ### Further tuning for the build itself:
    :; git clean -fffdddxxx
    :; CONFIG_SHELL=/usr/tgcware/bin/bash \
       WITHOUT_NUT_AUGEAS=true \
       PATH="/usr/xpg4/bin:$PATH" \
        /usr/tgcware/bin/bash ./ci_build.sh

#### MacOS with homebrew

Some CI tests happen on MacOS using a mix of their default xcode environment for compilers, and Homebrew community packaging for dependencies (including `bash` since the system one is too old for `ci_build.sh` script syntax).

See `.travis.yml` and `.circleci/config.yml` for practical details of the setup, and https://brew.sh if you want to install it on your MacOS system (note that its default packaged locations known as `HOMEBREW_PREFIX` differ depending on architecture — see https://docs.brew.sh/Installation for more details; find via `brew config | grep HOMEBREW_PREFIX: | awk '{print $2}'`).

### Note

The quickest pre-configuration for `ci_build.sh` integration with this non-default build system would be to add this line into your shell profile:

    eval "$(brew shellenv)"

### Note

Homebrew is not the only build/packaging system available for MacOS, so NUT scripts do not make any assumptions nor try to find a build system they were not told about (via `HOMEBREW_PREFIX` in this case).

Currently known dependencies for basic build include:

    # Optional for a quick spin:
    :; HOMEBREW_NO_AUTO_UPDATE=1; export HOMEBREW_NO_AUTO_UPDATE

    # Required:
    :; brew install ccache bash libtool binutils autoconf automake git m4 \
            pkg-config aspell asciidoc docbook-xsl cppunit gd \
            libusb glib neon net-snmp \
            nss openssl \
            libmodbus freeipmi powerman

    # To debug eventual core dump files, or trace programs with an IDE like
    # NetBeans (perhaps remotely), you may want the GNU Debugger program:
    :; brew install gdb

    # Recommended:
    :; brew install curl wget midnight-commander

### Note

For `asciidoc`/`a2x` to work, you should `export XML_CATALOG_FILES` with the location of packaged resources (`${HOMEBREW_PREFIX}/etc/xml/catalog`). On one test system, man page builds spewed warnings like `<unknown>:1: SyntaxWarning: invalid escape sequence '\S'` due to incompatibility of older asciidoc with new Python syntax requirements, but seemed to produce reasonable results otherwise.

Note that `ccache` is installed in a different location than expected by default in the `ci_build.sh` script, so if your system allows to add the symbolic link to `/opt/homebrew/opt/ccache/libexec` (`/usr/local/opt/ccache/libexec` on x86) as `/usr/lib/ccache`— please do so as the easiest way out.

Alternatively, to prepare building sessions with `ci_build.sh` you can:

    :; export CI_CCACHE_SYMLINKDIR="/opt/homebrew/opt/ccache/libexec"

    ### ...or for x86 builders:
    #:; export CI_CCACHE_SYMLINKDIR="/usr/local/opt/ccache/libexec"

### Note

For Jenkins agents, also need to `brew install --cask temurin@21` for JRE/JDK 21. Java 17 or 21 (an LTS) is required to run Jenkins agents after summer 2024.

The compiler is part of Apple’s XCode ecosystem. Just try to run `clang` in a GUI terminal, and a pop-up will appear offering to install it. Note that you would have to create symbolic links to version-numbered names of compilers, e.g. `clang-14` and `clang++-14` in both `/usr/local/bin` (pointing to `/bin/clang(++)` and in the `ccache` location prepared above (pointing to `../bin/ccache`), and repeat that in locations prepared by XCode installation such as `/Library/Developer/CommandLineTools/usr/bin/` and `/usr/local/Homebrew/Library/Homebrew/shims/mac/super/` just as `ln -s clang{,-14} ; ln -s clang++{,-14}`. Apparently `clang` is the only compiler available; various names of `gcc*` are links to the same binaries.

### Warning

Take care to NOT symlink a `clang-cpp(-14)` which is not a name recognized by XCode dispatcher program, so requests to it freeze.

On a machine dedicated to CI purposes, it may be wise to disable Spotlight search indexing with `sudo mdutil -a -i off`, disable active desktop themes, etc. (normally you would not even log in interactively).

For scratch workers (VMs) also consider going to System Preferences ⇒ Software Updates ⇒ Advanced, and un-checking all the boxes (disable the overheads of pulling in the updates you won’t remember in an hour anyway).

If you eventually find that the `kernel_task` consumes a lot of CPU, this is usually the system’s way of throttling (scheduling A LOT of high-priority no-op cycles to preempt any other workload). In this case please investigate cooling and hardware compatibility (especially in a VM), or find and follow community documentation about neutering `IOPlatformPluginFamily.kext` module (probably not on the bare-metal MacOS instance — find the cooling problem there instead).

- https://grafxflow.co.uk/blog/mac-os-x/delete-ioplatformpluginfamilykext-macos-big-sur

#### Windows builds

There have been several attempts to adjust NUT codebase to native builds for Windows, as well as there are many projects helping to produce portable programs.

Further TODO for Windows would include:

- MSVCRT (ubiquitous) vs. UCRT (more standards compliant, but since Windows 10) https://docs.microsoft.com/en-us/cpp/porting/upgrade-your-code-to-the-universal-crt?view=msvc-160
- libusb-0.1 vs. libusb-1.0

### Note

Native mingw, MSYS2, etc. builds on Windows are known to suffer from interaction with antivirus software which holds executable files open and so not writable by the linker. This may cause random steps in the `configure` script or later during the build to fail. If that happens to you, disable the antivirus completely or exempt at least the NUT build area from protection.

##### Windows with mingw

See `scripts/Windows/README.adoc` for original recommendations for the effort, including possibilities of cross-builds with mingw available in Linux.

Unfortunately these did not work for me at the time of testing, yielding some issues downloading mingw both in Windows and Linux environments. So I explored other downloads, as detailed below.

See also:

- https://winlibs.com/
- https://azrael.digipen.edu/~mmead/www/public/mingw/
- https://www.mingw-w64.org/downloads/

### Note

Seems the mingw installer has problems with current authentication and redirect on SourceForge. You can download and unpack 7z archives from https://sourceforge.net/projects/mingw-w64/files/mingw-w64/mingw-w64-release/ into e.g. `C:\Progra~1\mingw-w64\x86_64-8.1.0-release-posix-seh-rt_v6-rev0` location on your Windows system. Then for building further NUT dependencies see `scripts/Windows/README.adoc`.

##### Windows with MSYS2

The MSYS2 ecosystem is available at https://www.msys2.org/ and builds upon earlier work by MinGW-w64 (in turn a fork of MinGW.org (aka mingw-w32)) and Cygwin projects, to name a few related efforts. It also includes `pacman` similar to that in Arch Linux for easier dependency installation, and many packages are available "out of the box" this way.

The project is currently sponsored by Microsoft and seems to be supported by Visual Studio Code IDE for building and debugging projects, for more details see https://code.visualstudio.com/docs/cpp/config-mingw

Notable pages of the project include:

- https://www.msys2.org/ with current download link and first-installation instructions
- https://www.msys2.org/wiki/MSYS2-introduction/ for general overview
- https://packages.msys2.org/search?t=binpkg for search in package repository

After downloading and installing MSYS2 archive for the first time, they suggest to start by updating the base ecosystem (using their terminal):

    :; pacman -Syu

Wait for metadata and base package downloads, agree that all MSYS2 programs including your terminal would be closed/restarted, and wait for this stage to complete.

Run it again to refresh more of the ecosystem, now without restarting it:

    :; pacman -Syu

Finally, install tools and prerequisites for building NUT; note that some of the recommended package names are "umbrellas" for several implementations, and the `pacman` would ask you which (or "all") to install in those cases.

NUT build recipes and other scripts use symbolic links generously. Creation of these requires not only the use of NTFS, but also a granted run-time user privilege on Windows, as well as a setting for MSYS/CygWin `ln` implementation to actually create symlinks and not copy the files. Add this to your `~/.profile` in the MSYS2 environment, and change your account accordingly (or modify the MSYS2 shortcut to always "Run as Administrator" and ask for UAC upon launch as needed):

    ### This may require elevated privileges (Run as Administrator),
    ### or a Developer profile in Windows (can come via registry hacks),
    ### or a Group Policy setting:
    MSYS="winsymlinks:nativestrict"
    export MSYS

### Note

Suggestions below use `x86_64` generic variants where possible, and `clang` where available to try both build toolkits on the platform. If you want to build `i686` (32-bit) or alternate backends (e.g. `ucrt` instead of default `msvcrt`), poke the repository search to see what is available.

### Note

To build NUT with `ci_build.sh` (and generally — to help `configure` script find the dependencies listed below), start the terminal session with "MSYS2 MinGW x64" shortcut. Other options set up the environment variables for toolkits listed in their shortcut names, and so tend to prefer "wrong" flags and paths to dependencies (if you have several variants installed). The "MSYS2 MinGW UCRT x64" was also reported to work.

To avoid toolkit variant mismatches, you may require to use their specific builds preferentially:

    PATH="/mingw64/bin:$PATH"
    export PATH

…and also add these lines to the `~/.bashrc` file.

    # This covers most of the common FOSS development baseline, including
    # python, perl, autotools, gcc, clang, git, binutils, make, pkgconf...
    :; pacman -S --needed \
        base-devel mingw-w64-x86_64-toolchain \
        autoconf-wrapper automake-wrapper libtool mingw-w64-x86_64-libltdl \
        clang gcc \
        ccache mingw-w64-x86_64-ccache \
        git aspell aspell-en \
        vim python \
        mingw-w64-x86_64-python-pygments

    # PThreads come as an extra feature; note there are many variants,
    # see https://packages.msys2.org/search?t=binpkg&q=pthread
    :; pacman -S --needed \
        mingw-w64-x86_64-winpthreads-git \
        mingw-w64-clang-x86_64-winpthreads-git

    # Note that MSYS2 includes libusb-1.0 "natively"
    # The NUT codebase adjustments for Windows might at this moment expect older
    # ecosystem via https://github.com/mcuee/libusb-win32 -- subject to fix then.
    :; pacman -S --needed \
        mingw-w64-x86_64-libusb \
        mingw-w64-clang-x86_64-libusb

    # Seems that the older libusb-win32 (libusb-0.1) is also available as:
    :; pacman -S --needed \
        mingw-w64-x86_64-libusb-win32 \
        mingw-w64-clang-x86_64-libusb-win32

    # Alternately there is libusb-compat (libusb-1.0 codebase exposing the older
    # libusb-0.1 API) which SHOULD NOT be installed along with the real libusb-0.1:
    # :; pacman -S --needed mingw-w64-x86_64-libusb-compat-git \
    #        mingw-w64-clang-x86_64-libusb-compat-git

    # This also pulls *-devel of several other projects:
    :; pacman -S --needed \
        mingw-w64-x86_64-neon libneon-devel \
        mingw-w64-x86_64-glib2

    # Other dependencies:
    :; pacman -S --needed \
        mingw-w64-x86_64-libmodbus-git \
        mingw-w64-clang-x86_64-libmodbus-git \
        mingw-w64-x86_64-libgd \
        mingw-w64-clang-x86_64-libgd

    # For SSL support (note that OpenSSL is usually available
    # in the default MSYS2 footprint, but may get upgraded here):
    :; pacman -S --needed \
        mingw-w64-x86_64-openssl \
        mingw-w64-x86_64-nss

    # For C++ tests:
    :; pacman -S --needed \
        mingw-w64-x86_64-cppunit \
        mingw-w64-clang-x86_64-cppunit

    # More on Python (for NUT-Monitor UI):
    :; pacman -S --needed \
        mingw-w64-x86_64-python-pyqt5
    # FIXME: Consider qt6 since 2025

`ccache` wrapper scripts are available as e.g. `/mingw64/lib/ccache/bin/gcc` and lack a set for `clang` tools; easy-peasy fix with:

    :; cd /mingw64/lib/ccache/bin
    :; for T in clang clang++ clang-cpp ; do \
        sed "s/gcc/$T/" < gcc > "$T" ; chmod +x "$T" ; done

Note that default `ccache` seems quirky on Windows MSYS2, possibly due to mixing of the path separator characters and/or embedding and choking on the `C:` in path names. Overall it seems unable to create the cache files after it has created the cache directory tree (though you might have to pre-create the `${HOME}/.ccache` anyway, as NUT `ci_build.sh` script does. As found in experimentation, setting the `PATH` consistently for toolkits involved is very important.

- https://github.com/ccache/ccache/discussions/784
- https://sourceforge.net/p/msys2/tickets/253/

Notable packages not found in the repo:

- snmp (net-snmp, ucd-snmp) — instructions in `scripts/Windows/README.adoc` document now covers building it from source in MSYS2 MinGW x64 environment, essentially same as for Linux cross builds with proper `ARCH` and `PREFIX`
- libregex (C version, direct NUT `configure` script support was added by the Windows branch); MSYS2 however includes `libpcre` pulled by some of the dependencies above…
- augeas
- avahi
- powerman
- ipmi

Not installed above (yet?):

- https://packages.msys2.org/search?t=binpkg&q=serial — for these need to first check if termios is part of baseline

Note that `ccache` symlinks for MSYS2 are installed into `/usr/lib/ccache/bin` directory (not plain `/usr/lib/ccache` as elsewhere).

### Note

After you successfully build NUT (perhaps using `ci_build.sh`), if you install it into a prototype area by `make DESTDIR=... install` then you should add the third-party shared libraries involved, for that file set to be usable.

Something along these lines:

    :; find "$DESTDIR" -name '*.exe' -type f  | while read F ; do ldd "$F" \
       | grep ' /mingw64/' ; done  | awk '{print $3}' | sort | uniq \
       | while read LIB ; do cp -pf "$LIB" "$DESTDIR/mingw64/bin/" ; done

Keep in mind that a similar trick (or links to `*.dll`— and symlinks are problematic on that platform) may be needed in other directories, such as `sbin` and `cgi-bin`:

    :; ( cd "$DESTDIR/mingw64/bin/" && ln *.dll ../sbin && ln *.dll ../cgi-bin )

Prev |  |
| Home |