The ci_build.sh script
======================

This script was originally introduced (following ZeroMQ/ZProject example)
to automate CI builds, by automating certain scenarios driven by exported
environment variables to set particular `configure` options and `make`
some targets (chosen by the `BUILD_TYPE` envvar). It can also be used
locally to avoid much typing to re-run those scenarios during development.

Developers can directly use the scripts involved in CI builds to fix
existing code on their workstations or to ensure support for new
compilers and C standard revisions, e.g. save a local file like this
to call the common script with pre-sets:

----
$ cat _fightwarn-gcc10-gnu17.sh
#!/bin/sh

BUILD_TYPE=default-all-errors \
CFLAGS="-Wall -Wextra -Werror -pedantic -std=gnu17" \
CXXFLAGS="-Wall -Wextra -Werror -std=gnu++17" \
CC=gcc-10 CXX=g++-10 \
    ./ci_build.sh
----

...and then execute it to prepare a workspace, after which you can go
fixing bugs file-by-file running a `make` after each save to confirm
your solutions and uncover the next issue to address :-)

Helpfully, the NUT CI farm build logs report the configuration used for
each executed stage, so if some build combination fails -- you can just
scroll to the end of that section and copy-paste the way to reproduce
an issue locally (on an OS similar to that build case).

Note that while spelling out sets of warnings can help in a quest to
fix certain bugs during development (if only by removing noise from
classes of warnings not relevant to the issue one is working on), there
is a reasonable set of warnings which NUT codebase actively tries to
be clean about (and checks in CI), detailed in the next section.

For the `ci_build.sh` usage like above, one can instead pass the setting
via `BUILD_WARNOPT=...`, and require that all emitted warnings are fatal
for their build, e.g.:

----
$ cat _fightwarn-clang9-gnu11.sh
#!/bin/sh

BUILD_TYPE=default-all-errors \
BUILD_WARNOPT=hard BUILD_WARNFATAL=yes \
CFLAGS="-std=gnu11" \
CXXFLAGS="-std=gnu++11" \
CC=clang-9 CXX=clang++-9 CPP=clang-cpp \
    ./ci_build.sh
----

Finally, for refactoring effort geared particularly for fighting the
warnings which exist in current codebase, the script contains some
presets (which would evolve along with codebase quality improvements)
as `BUILD_TYPE=fightwarn-gcc`, `BUILD_TYPE=fightwarn-clang` or plain
`BUILD_TYPE=fightwarn`:

    :; BUILD_TYPE=fightwarn-clang ./ci_build.sh

As a rule of thumb, new contributions must not emit any warnings when
built in GNU99 mode with a `minimal` "difficulty" level of warnings.
Technically they must survive the part of test matrix across the several
platforms tested by NUT CI and marked in project settings as required
to pass, to be accepted for a pull request merge.

Developers aiming to post successful pull requests to improve NUT can
pass the `--enable-warnings` option to the `configure` script in local
builds to see how that behaves and ensure that at least in some set-up
their contribution is viable. Note that different compiler versions and
vendors (gcc/clang/...), building against different OS and third-party
dependencies, with different CPU architectures and different language
specification revisions, might all complain about different issues --
and catching this in as diverse range of set-ups as possible is why we
have CI tests.

It can be beneficial for serial developers to set up a local BuildBot,
Travis or a Jenkins instance with a matrix test job, to test their local
git repository branches with whatever systems they have available.

* https://github.com/networkupstools/nut/issues/823

While `autoconf` tries its best to provide portable shell code, sometimes
there are builds of system shell that just fail under stress. If you are
seeing random failures of `./configure` script in different spots with
the same inputs, try telling `./ci_build.sh` to loop configuring until
success (instead of quickly failing), and/or tell `./configure` to use
another shell at least for the system call-outs, with options like these:

    :; SHELL=/bin/bash CONFIG_SHELL=/bin/bash CI_SHELL_IS_FLAKY=true \
       ./ci_build.sh

Caching!
--------

The `ci_build.sh` can make use of a persistent cache directory, e.g. to speed
up repetitive runs of the `configure` script on developer or CI machines when
our `*.m4` and `*.ac` script sources and the machine remain the same.

It can be stored outside of the build area(s), under `${CI_CACHE_NUT_BASEDIR}`
(default: `${HOME}/.cache/nut-ci`) if `DO_USE_NUTCI_CACHE=yes` as provided
by caller (e.g. via `~/.profile` of a developer) or guessed from environment
variables typical for CI runs.

If something acts up, or the build environment changes invisibly to the
script, an `export DO_CLEAN_NUTCI_CACHE_BEFORE=yes` (or a more targeted
`DO_CLEAN_AUTOCONF_CACHE_BEFORE`, since NIT uses similar logic and general
toggle to retain generated test certificates) should fix that.

You can also always nuke the `${CI_CACHE_NUT_BASEDIR}` directory, or the
`AUTOCONF_*` subdirectories and stale lock files under it.
It would likely be needed from time to time anyway, as there is now
no automated clean-up of no longer relevant caches.
