I n s t a l l i n g  S - n a i l / S - m a i l x
================================================

1.  Compilation
1.1 What if configuration fails?
1.2 What if building fails?
1.3 What if tests fail?
1.4 How can i enable debugging?
2.  Notes on building the latest release

1. Compilation
--------------

System specific notes can be found in the next section.
All (optional) features are documented (and adjustable) in make.rc.
Adjustments may also take place, and are usually done, from the command
line, overriding those made in make.rc (if any).

Without any adjustments all non-experimental features will be enabled,
except some which provide redundant functionality (e.g., OPT_SPAMC is
disabled because the generic OPT_SPAM_FILTER can do the same).
None of the features are "require"d by default, so that configuration
won't fail shall any of them not be available or usable.
The generated configuration is tracked: changes will be recognized
and cause automatic cleanups and rebuilds as necessary.
Experts could find it valuable to adjust some settings in config.h.

  $ make tangerine  # equals "$ make config build test install"
  $ make citron     # equals "$ make config build install"
  $ make distclean  # *Completely* cleanup working directory

With adjustments:

  $ make OPT_POP3=no OPT_SMTP=require tangerine
  $ make OPT_CROSS_BUILD=y VAL_PREFIX=/some/nasty/prefix citron

With utility program and feature adjustments:

  $ make awk=/usr/bin/nawk OPT_SOCKETS=no DESTDIR=./zzz tangerine

If OPT_DOTLOCK has been enabled then the minimal privilege-separated
SETUID (to VAL_PRIVSEP_USER, default "root") helper program will be build
and installed, and therefore the installation process needs to have the
appropriate privileges.  In this case it may be useful to separate the
configuration / building and the installation tasks and give the last
step higher privileges via super(1), sudo(1), su(1) or a similar
mechanism, e.g.:

  $ make VAL_PREFIX=/usr config && make MAKEJOBS='-j 4' &&
    super make DESTDIR=./xy install

would create a "s-nail" binary and install a "s-nail" manual etc.  under
the prefix "/usr" but rooted under "[./]xy", i.e., the binary would be
installed as "[./]xy/usr/bin/s-nail".
Out-of-tree compilation is supported; to use it, create the target
directory of desire, change into it and run the make-emerge.sh script
shipped with S-nail, then proceed as with normal in-tree building.
The following make(1) targets exists, the default being `build':

- tangerine   Shorthand for "$ make config build test install": create
              or check and update configuration, build, test and install.
              The variable $DESTDIR will be honoured (see make.rc),
              but not be tracked in the configuration.
              In order to parallelize the `build' step pass a $MAKEJOBS
              variable, as shown below.
- citron      Shorthand for "$ make config build install".
              `build' parallelization via $MAKEJOBS, as shown below.
- all         Shorthand for "$ make config build".
              `build' parallelization via $MAKEJOBS, as shown below.

- config      Only create or check and update the configuration.
- build       Only build (using the existing configuration).
              This can be parallelized, either by a corresponding make(1)
              invocation when the target is run by itself, or by setting
              the $MAKEJOBS variable otherwise, e.g., "MAKEJOBS='-j 4'".
              $MAKEJOBS is not tracked in the configuration.
- install     Only install using the built files of the existing
              configuration.
              The variable $DESTDIR will be honoured (see make.rc),
              but not be tracked in the configuration.

              S-nail will create an uninstall shell script
              (VAL_UAGENT-uninstall.sh), but which will *not* be installed
              if $DESTDIR is set non-empty -- within $DESTDIR, that is.
              Copy or move it manually from the S-nail root directory ./
              into $DESTDIR as necessary.

- clean       Remove anything which can be rebuild.
- distclean   Remove anything which can be rebuild or reconfigured.

- test        Run cc-test.sh in --check-only mode on the built binary.

Setting the make(1) variable $VERBOSE to an arbitrary value during
`config' time, as in "$ make VERBOSE=xy tangerine", will change the
output of the `all', `install' etc. targets to a more verbose one.

If some libraries are missing that you know are installed on your
system, or if other errors occur due to missing files but which you know
exist, please ensure that the environment variable $C_INCLUDE_PATH
includes the necessary "include/" paths and the environment variable
$LD_LIBRARY_PATH includes the necessary "lib/"rary paths.

The S-nail make system will inspect these two environment variables and
*automatically* convert them to cc(1) (c99(1)) -I and -L options (since
these environment variables are, different to the command line options,
not part of the POSIX standard).
To set these environment variables, the following can be done in
a Bourne / Korn / POSIX compatible shell:

  $ C_INCLUDE_PATH="${C_INCLUDE_PATH}:/usr/local/include"
  $ LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/usr/local/lib"
  $ export C_INCLUDE_PATH LD_LIBRARY_PATH
  $ make tangerine

Other than the standard paths /usr/{bin,include,lib} and /usr/local/[.]
should possibly be placed first instead, presuming that they are meant
to override things which usually exist in standard locations.
If all else fails you can also forcefully pass in include directives and
library paths by passing prefilled $INCS and $LIBS variables:

  $ make INCS=-I/mypath/include LIBS="-L/mypath/lib -lmylib" tangerine

There are also some predefined configuration sets available, ment to be
used instead of doing manual adjustments.

- CONFIG=NULL, CONFIG=NULLI
  Anything that can be turned off is off.  MIME cannot.
  The latter adds and "require"s iconv(3).

- CONFIG=MINIMAL
  Possibly what people want who need nothing but a MIME-capable mailx(1)
  and don't regret improved usability for the rare interactive use
  occasions.  Adds documentation strings, the built-in line editor (MLE)
  with history support and key bindings, error tracking, basic colour
  support and IDNA addresses, as well as generic spam filter support.

  "Require"s iconv(3), regex(3) and the dotlock helper.

- CONFIG=NETSEND
  Sending messages directly to the mail provider via the SMTP protocol,
  instead of requiring a local mail-transfer-agent (MTA) who does.

  Adds SSL/TLS, SMTP, GSSAPI and .netrc file parsing on top of MINIMAL.

  "Require"s iconv(3), SSL/TLS, SMTP (sockets) and the dotlock helper.

- CONFIG=MAXIMAL
  Like MINIMAL, but turns on all (other) options, also obsolete or
  redundant ones, but none of them required.

1.1 What if configuration fails?
--------------------------------

The configuration process creates some files named "mk-config.*":

- mk-config.log  output generated by the configuration compile tests.
- mk-config.lst  configuration (chosen option, programs, paths).
                 (Removing this file reenables configuration even after
                 a screwed up configuration, e.g., due to power failure.)
- mk-config.h    C program header produced according to mk-config.lst.
- mk-config.ev   A set of sh(1) variables for reproducible compile runs.
- mk-config.inc  List of C header include paths, as compiler directives.
- mk-config.lib  List of used library information, as compiler directives.

Of special interest is mk-config.log since the error usually manifests
here in textual output.  Maybe that makes it obvious what can be done
(header files could not be found because of missing entries in
$C_INCLUDE_PATH, libraries could not be linked because of incomplete
$LD_LIBRARY_PATH, etc.).

Otherwise it is getting complicated, and it would be appreciated if you
would contact the mailing-list!

If you hit an actual bug in the configuration system, and "make
distclean" will not help you out, please "reset" the state by doing
a simple "$ rm mk-*".

1.2 What if building fails?
---------------------------

Even worse!  This should not happen if configuration succeeded!  It
would be very kind and highly appreciated if you would report this
to the mailing-list.

1.3 What if tests fail?
-----------------------

That would be a disaster.  Please contact the mailing-list!
If you have used OPT_AUTOCC (the default) and a non-debug target, you
could try to reconfigure with an additional cc_maxopt=1 on the command
line and report whether that turns the green testing light on.

Otherwise you could run the cc-test.sh script in --mae-test mode and
invoke the failing tests (testing echoes the actual test names in
brackets): this will produce output files of the form mae-test-TESTXY.
It would be nice if these outputs could be send to the mailing-list;
possibly stored altogether in a compressed tar(1) file.  For example:

  $ ./cc-test.sh --mae-test ./s-nail t_behave_localopts t_behave_mbox
  $ tar -czf badtests.tar.gz mae-test-*
  $ rm mae-test-*

Thank you!

1.4 How can i enable debugging?
-------------------------------

Please ensure OPT_DEBUG=yes is enabled during compilation, as in

  $ make CONFIG=MAXIMAL OPT_DEBUG=yes

If OPT_AUTOCC is enabled then the build system should automatically
adjust the compiler flags accordingly, please see make.rc for more.
There is also a `devel'opment target which does most of this by itself:

  $ make devel

OPT_DEBUG (`devel') will enable memory bound debug canaries and
Not-Yet-Dead function graph listings etc.  Whereas the latter will try
to write its listing into a file named after your favourite MUA in
your $TMPDIR (or "/tmp" or "./", in order), falling back to STDERR shall
creation of the file not be possible (we won't overwrite an existing
file), the debug facilities in general make their appearance on the
standard error channel; because this can be a quite long output, then,
it is possibly a good idea to redirect it to a file:

  $ s-nail -dvv 2> error.log

Should you really discover any problems with S-nail it would be very
useful for development if you would contact the mailing-list!
Thank you!

2. Notes on building the latest release
---------------------------------------

- All systems:
  * I have turned off -Wstrict-overflow warnings unless we are debug
    enabled (talking about OPT_AUTOCC=yes here).
  * There are warnings on unused returns from some I/O functions.
    These will vanish after the large v15 I/O and MIME rewrite.
  * Some "XYZ may be used uninitialized" warnings are logically false.

- All 32-bit systems:
  * There _may_ be warnings about format strings, like, e.g.,
      auxlily.c:1610:10: warning: format '%lu' expects type 'long
      unsigned int', but argument 3 has type 'size_t'
    The codebase is ISO C89 which has no %z printf(3) format.
    However we try hard to detect the real type size and define the
    "PRI[du]Z" macros which end up with the correct size, which is
    also compile-time asserted (see the "MCTA(sizeof(size_t) == XZ)"
    statements in nail.h).

    By forcing ISO C99 mode when compiling these warnings vanish, e.g.,
    with gcc(1) and clang(1): with OPT_AUTOCC pass
    "EXTRA_CFLAGS=-std=c99", otherwise ensure -std=c99 in $CFLAGS.

Development and/or regular tests:

. AlpineLinux <https://www.alpinelinux.org/> (3.7, edge; x86-64).
. ArchLinux <https://www.archlinux.org/> (weekly updated; x86-64).
. CRUX Linux <https://www.crux.nu/> (3.3; x86-64).
. FreeBSD <https://www.freebsd.org/> (11.1; x86).
. OpenBSD <https://www.openbsd.org/> (6.2; x86).

Occasional tests:

. Solaris <http://opencsw.org/>
  @ First of all: thanks to OpenCSW.org for offering SSH access to
    their Solaris build cluster!
  * In order to be able to run the tests you will need a cksum(1) that
    supports CRC-32 (POSIX).  We look into /opt/csw/gnu/cksum, but if
    that cannot be found you have to adjust the $cksum variable (see
    above) to something that works.
  * With OPT_AUTOCC: we try to use Sun cc(1) whenever we find it.
    If your gcc(1) installation is doing alright you have to turn
    OPT_AUTOCC off and use $CC, $CFLAGS and $LDFLAGS.
  * Some notes collected on earlier trials:
    + We may forcefully disable stack protectors on SunOS/gcc because of
      linking errors seen in earlier tests.
    + If you get the compiler / system header installation error
        Undefined                       first referenced
         symbol                             in file
        __builtin_stdarg_start              auxlily.o
      then you have to overwrite this symbol with __builtin_va_start,
      e.g., in conjunction with OPT_AUTOCC add this:
       EXTRA_CFLAGS='-D__builtin_stdarg_start=__builtin_va_start'
  - The OpenCSW build cluster consists of SunOS 5.9 - 5.11 machines
    under SPARC and i386.  And it looked good on 2017-09-15.
. Void Linux <https://www.voidlinux.eu/> (x86; not in 2017 FIXME)

# s-ts-mode
