Pages

Thursday, June 29, 2017

GNU - Build Automation

Solaris 11.3 includes many modern packages, among them some essential GNU build automation ones. The problem is that the pace of update of these third-party packages is much faster than what get updated through support repository, needless to say the public release repository. In order to better keep up with this third-party pace, there's no other better alternative than to get the sources and build ourselves what's needed, in the hope (and unfortunately sometimes it's no more than just a hope) that the sources and the build tools are compatible and available to Solaris.

But included in the above issue are the build tools themselves. For instance, some of the GNU build automation tools packaged in Solaris 11.3 are already rather outdated, among them: autoconf which requires M4 and automake which requires autoconf. To successfully build many other software it's highly recommended to build and install more up-to-date versions of this build automation tools themselves. I'd suggest doing so at least for the following GNU build automation tools (➝ means "depends on", thus begin refreshing this tools in the reverse order show below):
 

For instance: Solaris 11.3 packages automake-19 (v1.9.6), automake-110 (v.1.10) and automake-111 (v.1.11.2), but neither of these are good enough for building more recent third-party software versions. Other software, such as Firefox, requires (?) autoconf version 2.13, but Solaris 11.3 furnishes only version 2.68.

According to the more traditional conventions adopted by Solaris, these extra software are supposed to be located under /opt which indeed is the safest location instead of /usr/sfw or /usr/gnu because we don't want to mess with the built-in strategies of Solaris itself already trying to cope with GNU somehow. Hence, the best practice for manual additions is to focus on pointing to /opt which includes specifying --prefix=/opt/... to the GNU build automation tools (typically the configure script) or something equivalent to any other build automation tool.

NOTE
It's also required to install IPS packages for the GNU Compiler Collection (developer/gcc) and many other GNU tools (pkg search -o pkg.shortfmri '*:set:pkg.fmri:*gnu*'), even if you (plan to) have Developer Studio (developer/developerstudo-125) installed as well.
NOTE
The GCC version supplied with Solaris 11.3 only covers the full standards of C89 and C++03. All other standards have only partial support, hence to get more solid results always make these explicit, typically through the environment variables CFLAGS="-std=c89" and CXXFLAGS="-std=c++03" or their equivalent. But you should prefer using the respective GNU extensions to these flags, gnu89 and gnu++03, unless you're really, really, after a strict portability at the expense of sacrificing any platform specific quality and optimization goodies. With the build automation tools the general approach is to adjust to platform specifics on the bases of specific defines (-D at command-line and #ifdef / #ifndef at the source code).

If true full C++11 support is required, you'll have to attempt building a more recent version of GCC. Not even Developer Studio truly fully supports C++11 as it relies on GCC under the hood by typically linking in libgcc_s.so.1. One proof of this limitation is that locales aren't fully supported.
NOTE
Since Solaris 11.4 Beta the GCC version has bumped to 5.5.0 theoretically supporting the full standards of C11 and C++11. But some C++11 features seem still missing such as the previously mentioned locales issue. Hence, to some extent, you may benefit from setting the environment variables CFLAGS="-std=c11" and CXXFLAGS="-std=c++11" or their equivalent. But again may prefer to use the respective GNU extensions to these flags, gnu11 and gnu++11.

The general work-flow for installing from the GNU build automation tools is:
  • Get the tarball (typically a .tar.bz2 or .tar.xz)
  • Set up a dedicated and delegated ZFS infrastructure 
  • Extract the tarball and take an initial snapshot (@source)
  • Clone the @source to a build-target specific dataset 
  • Take a snapshot (@start) from the recent clone.
  • Set up the temporary environment variables for the build-target
  • Configure the automated build and take a snapshot (@config)
    (in case of errors, instead of a snapshot, do a rollback to @start)
  • Perform the build and take a snapshot (@build)
    (in case of errors, instead of a snapshot, do a rollback to @config)
  • Pre-create the /opt/... destination as a VARSHARE ZFS dataset
    (take a snapshot @release of the /opt/.../build-target)
  • Perform the installation (as root) and take a snapshot of /opt/...
  • Optionally, create a package or a compressed tarball from the results
  • Set up the necessary permanent environment variables

As for the directory name under /opt a suggestion is:
name-version/build-target
For instance:
sqlite-3.19.3/gnu64
This way it's possible to gather under a main directory (basename) multiple build-targets to select from, such as: gnu32, gnu64, sun32, sun64 and so on...

NOTE
In case of third-party software to be located under /opt, the choice of rpool/VARSHARE as the root to the underlying ZFS dataset is just a simplification. The rpool/VARSHARE suites well for certain system software that shouldn't be impacted by boot environment issues. The best idea for third-party software would be to have another dedicated ZFS pool, much in the same way as it as good idea to have another dedicated ZFS pool for rooting /export instead of the default rpool/export.

Now let me show a full example where I build a 64-bits M4:
 
$ DS=rpool/export/home/.../software$ zfs create -p $DS/M4/m4-1.4.18
$ cd ~/software/M4
$ gtar xf /tmp/m4-1.4.18.tar.xz

$ M4=$DS/M4/m4-1.4.18
$ zfs set readonly=on $M4
$ zfs snapshot $M4@source
$ zfs clone $M4@source $M4-gnu64
$ zfs snapshot $M4-gnu64@start

$ zfs get -o property,value readonly,compressratio,dedup $M4
PROPERTY       VALUE
readonly       on
compressratio  1.99x
dedup          on


$ zfs list -r -t all -o name $DS/M4 
NAME
rpool/export/home/.../software/M4
rpool/export/home/.../software/M4/m4-1.4.18
rpool/export/home/.../software/M4/m4-1.4.18@source
rpool/export/home/.../software/M4/m4-1.4.18-gnu64
rpool/export/home/.../software/M4/m4-1.4.18-gnu64@start


$ ll -o m4-1.4.18-gnu64
...
-rw-r--r-- ... TODO
-rw-r--r-- ... THANKS
-rw-r--r-- ... README
-rw-r--r-- ... c-boxes.el
-rw-r--r-- ... BACKLOG
-rw-r--r-- ... AUTHORS
-rw-r--r-- ... acinclude.m4
-rw-r--r-- ... INSTALL
-rw-r--r-- ... COPYING
-r-xr-xr-x ... bootstrap
-rw-r--r-- ... maint.mk
-rw-r--r-- ... configure.ac
-rw-r--r-- ... Makefile.am
-rw-r--r-- ... ChangeLog-2014
-rw-r--r-- ... aclocal.m4
-rw-r--r-- ... Makefile.in
-rw-r--r-- ... GNUmakefile
-rw-r--r-- ... cfg.mk
-rw-r--r-- ... NEWS
-rwxr-xr-x ... configure
drwxr-xr-x ... m4
drwxr-xr-x ... examples
drwxr-xr-x ... tests
drwxr-xr-x ... src
drwxr-xr-x ... lib
drwxr-xr-x ... doc
drwxr-xr-x ... checks
-rw-r--r-- ... ChangeLog
drwxr-xr-x ... build-aux


Now I set up the temporary environment variables for the build-target. Note that I gather what's necessary on a non-executable file, setenv-build-target, and then just "source" it to integrate the values in the current session (in my particuar case I just opted to specify one more flag for the minimum architecture of core2 but this is not important for this post):

$ cat setenv-gnu64
export CONFIG_SHELL=/bin/bash

export CC=/usr/bin/gcc
export CFLAGS="-m64 -march=core2 -std=gnu89"

export CXX=/usr/bin/g++
export CXXFLAGS="-m64 -march=core2 -std=gnu++03"


PKG=/usr/gnu
if [[ -d "$PKG" ]] ;
then
  CFG=$PKG/bin
  ! [[ "$PATH" =~ "$PKG" ]] && \
    export PATH=$CFG:$PATH
fi


$ source setenv-gnu64

But wait! While reading through the above README and INSTALL files, I've found that M4 has an optional dependency that would be very interesting to pre-install: libsigsegv. At the time of this writing the current version is 2.11, Solaris 11.3 offers version 2.6, but M4 version 1.4.18 recommends a version no less than 2.9. To address this issue, I temporarily stop the M4 building work-flow and then I set to repeat all the steps above but this time for libsigsegv (by the way, naturally the target-build must match!). But before returning to M4 I need to complete the building steps of libsigsegv as follows:

$ pwd
~/software/libsigsegv/libsigsegv-2.11-gnu64

$ ./configure --prefix=/opt/libsigsegv-2.11/gnu64

Build Tools:
checking for a BSD-compatible install... /usr/bin/ginstall -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /usr/bin/gmkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for gcc... /usr/bin/gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether /usr/bin/gcc accepts -g... yes
checking for /usr/bin/gcc option to accept ISO C89... none needed
checking whether /usr/bin/gcc understands -c and -o together... yes
checking for style of include used by make... GNU
checking dependency style of /usr/bin/gcc... none
checking how to run the C preprocessor... /usr/bin/gcc -E
checking build system type... i386-pc-solaris2.11
checking host system type... i386-pc-solaris2.11
checking host platform... i386-pc-solaris2.11
checking how to print strings... print -r
checking for a sed that does not truncate output... /usr/bin/gsed
checking for grep that handles long lines and -e... /usr/bin/ggrep
checking for egrep... /usr/bin/ggrep -E
checking for fgrep... /usr/bin/ggrep -F
checking for ld used by /usr/bin/gcc... /usr/bin/ld
checking if the linker (/usr/bin/ld) is GNU ld... no
checking for BSD- or MS-compatible name lister (nm)... /usr/bin/nm -p
checking the name lister (/usr/bin/nm -p) interface... BSD nm
checking whether ln -s works... yes
checking the maximum length of command line arguments... 786240
checking how to convert i386-pc-solaris2.11 file names to i386-pc-solaris2.11 format... func_convert_file_noop
checking how to convert i386-pc-solaris2.11 file names to toolchain format... func_convert_file_noop
checking for /usr/bin/ld option to reload object files... -r
checking for objdump... no
checking how to recognize dependent libraries... pass_all
checking for dlltool... no
checking how to associate runtime and link libraries... print -r --
checking for ar... ar
checking for archiver @FILE support... no
checking for strip... strip
checking for ranlib... ranlib
checking command to parse /usr/bin/nm -p output from /usr/bin/gcc object... failed
checking for sysroot... no
checking for a working dd... /usr/bin/dd
checking how to truncate binary pipes... /usr/bin/dd bs=4096 count=1
checking for mt... mt
checking if mt is a manifest tool... no
checking for ANSI C header files... yes
checking for sys/types.h... yes
checking for sys/stat.h... yes
checking for stdlib.h... yes
checking for string.h... yes
checking for memory.h... yes
checking for strings.h... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for unistd.h... yes
checking for dlfcn.h... yes
checking for objdir... .libs
checking if /usr/bin/gcc supports -fno-rtti -fno-exceptions... no
checking for /usr/bin/gcc option to produce PIC... -fPIC -DPIC
checking if /usr/bin/gcc PIC flag -fPIC -DPIC works... yes
checking if /usr/bin/gcc static flag -static works... no
checking if /usr/bin/gcc supports -c -o file.o... yes
checking if /usr/bin/gcc supports -c -o file.o... (cached) yes
checking whether the /usr/bin/gcc linker (/usr/bin/ld -64) supports shared libraries... yes
checking dynamic linker characteristics... solaris2.11 ld.so
checking how to hardcode library paths into programs... immediate
checking whether stripping libraries is possible... no
checking if libtool supports shared libraries... yes
checking whether to build shared libraries... no
checking whether to build static libraries... yes


Optional Platform Environment:
checking sys/signal.h usability... yes
checking sys/signal.h presence... yes
checking for sys/signal.h... yes
checking for unistd.h... (cached) yes
checking for getpagesize... yes
checking for sysconf(_SC_PAGESIZE)... yes
checking for PAGESIZE in limits.h... no
checking for mmap with MAP_ANON... yes
checking for mmap with MAP_ANONYMOUS... yes
checking for mmap of /dev/zero... yes
checking whether a fault handler according to POSIX works... yes
checking whether a fault handler according to Linux/i386 works... no
checking whether a fault handler according to old Linux/i386 works... no
checking whether a fault handler according to Linux/m68k works... no
checking whether a fault handler according to Linux/PowerPC works... no
checking whether a fault handler according to Linux/HPPA works... no
checking whether a fault handler according to BSD works... no
checking whether a fault handler according to IRIX works... no
checking whether a fault handler according to HP-UX HPPA works... no
checking whether a fault handler according to OSF/1 Alpha works... no
checking whether a fault handler according to NetBSD Alpha works... no
checking whether a fault handler according to AIX works... no
checking whether a fault handler according to MacOSX/Darwin7 PowerPC works... no
checking whether a fault handler according to MacOSX/Darwin5 PowerPC works... no
checking whether a fault handler according to Hurd works... no
checking ucontext.h usability... yes
checking ucontext.h presence... yes
checking for ucontext.h... yes
checking for the fault handler specifics... fault-solaris-i386.h
checking if the system supports catching SIGSEGV... yes
checking for stack direction... grows down
checking for prmap_t in sys/procfs.h... yes
checking for mquery... no
checking for mincore... yes
checking for getrlimit... yes
checking for setrlimit... yes
checking for sigaltstack... yes
checking for stack_t... yes
checking for working sigaltstack... yes
checking for correct stack_t interpretation... yes
checking whether a signal handler can be left through longjmp... no
checking whether a signal handler can be left through longjmp and sigaltstack... no
checking whether a signal handler can be left through longjmp and setcontext... yes
checking whether a signal handler can be left through siglongjmp... yes
checking whether a signal handler can be left through siglongjmp and sigaltstack... yes
checking whether a signal handler can be left through siglongjmp and setcontext... yes
checking if the system supports catching stack overflow... yes
checking for uintptr_t... yes


Build Parameters:
checking whether to activate relocatable installation... no

Output Substitution:
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: creating src/Makefile
config.status: creating src/sigsegv.h
config.status: creating tests/Makefile
config.status: creating config.h
config.status: executing depfiles commands
config.status: executing libtool commands 


Now please type 'make' to compile. 
Good luck.

AFAIAC (as far as I am concerned) the configuration result is reasonably acceptable and no message got me worried, so I go on as planned (and always use gmake, not make because Solaris' make although very good isn't the one expected which is if fact GNU make know in Solaris as gmake).

$ zfs snapshot $SIGSEGV-gnu64@config

$ gmake
...
Now please type 'make check' to run a quick test suite. Hope it works.
...

$ gmake check
...
PASS: sigsegv1
PASS: sigsegv2
PASS: sigsegv3
PASS: stackoverflow1
PASS: stackoverflow2
==================================
Testsuite summary for

==================================
# TOTAL: 5
# PASS:  5
# SKIP:  0
# XFAIL: 0
# FAIL:  0
# XPASS: 0
# ERROR: 0

==================================

...
Now please type 'make install' to install the package.
...


$ zfs snapshot $SIGSEGV-gnu64@build

$ zfs list -r -t all -oname $DS/libsigsegv
NAME
.../software/libsigsegv
.../software/libsigsegv/libsigsegv-2.11
.../software/libsigsegv/libsigsegv-2.11@source
.../software/libsigsegv/libsigsegv-2.11-gnu64
.../software/libsigsegv/libsigsegv-2.11-gnu64@start
.../software/libsigsegv/libsigsegv-2.11-gnu64@config
.../software/libsigsegv/libsigsegv-2.11-gnu64@build



Now, as root, perform the installation, which will occur under /opt:

# X=libsigsegv-2.11
# zfs create -o mountpoint=/opt/$X rpool/VARSHARE/$X
# zfs create rpool/VARSHARE/$X/gnu64
# zfs list -o name -r rpool/VARSHARE |grep $X
rpool/VARSHARE/libsigsegv-2.11
rpool/VARSHARE/libsigsegv-2.11/gnu64


# cd /home/.../software/libsigsegv/$X-gnu64

# source ../setenv-gnu64
# gmake install
...
Now use the package; ...
...

# zfs snapshot rpool/VARSHARE/$X/gnu64@release
# zfs list -o name -r -t all rpool/VARSHARE |grep $X
rpool/VARSHARE/libsigsegv-2.11
rpool/VARSHARE/libsigsegv-2.11/gnu64

rpool/VARSHARE/libsigsegv-2.11/gnu64@release

# ll -oR /opt/$X/*
/opt/libsigsegv-2.11/gnu64:
...
drwxr-xr-x   2 ... lib
drwxr-xr-x   2 ... include
 

/opt/libsigsegv-2.11/gnu64/lib:
...
-rwxr-xr-x   1 root ... libsigsegv.la
-rw-r--r--   1 root ... libsigsegv.a

/opt/libsigsegv-2.11/gnu64/include:
...
-rw-r--r--   1 root ... sigsegv.h



NOTE
Non-Solaris people, which isn't used to roles may prefer the convenience of using sudo instead of "su -", but I don't. Furthermore, in this context, sudo doesn't offer any advantage and may even get in the way unless virtually unrestricted in which case it could be even more dangerous and error-prone.

Now I can resume the build automation for M4:

$ cd ~/software/M4/m4-1.4.18-gnu64
$ ./configure \
  --prefix=/opt/m4-1.4.18/gnu64 \
  --with-libsigsegv-prefix=/opt/libsigsegv-2.11/gnu64 \
  --with-syscmd-shell=/bin/bash

NOTE
If setenv-gnu64 didn't setup /usr/gnu/bin a pitfall would be revealed regarding grep. And that's and example why we should always review messages and logs:

checking whether C symbols are prefixed with underscore at the linker level... 
grep: illegal option -- E
Usage: grep [-c|-l|-q] -bhinsvw pattern file . . .


This would require me to start over the "configure" step:
$ zfs rollback $DS/M4/m4-1.4.18-gnu64@start

The problem is that the configure script does non-trivial usage of grep and expects a GNU grep, not a Solaris grep. In Solaris, GNU grep called ggrep or the /usr/gnu/bin should come before /usr/bin in PATH.  Sometimes, resolving this issue may not be an easy task because it may be difficult to evaluate the impacts of a chosen approach, tough it should be quite reasonable to put /usr/gnu/bin ahead in PATH as we are using GNU tools anyway... I would suggest try what's reasonable and observe and take action as needed and as possible. Nevertheless, comparing the output of both approaches one can be surprised:

## When /usr/gnu/bin comes ahead in PATH
21 checking for grep that handles long lines and -e... /usr/gnu/bin/grep
22 checking for egrep... /usr/gnu/bin/grep -E


## Otherwise, the usual Solaris without GNU paths
21 checking for grep that handles long lines and -e... /usr/bin/ggrep
22 checking for egrep... /usr/bin/ggrep -E


In both cases the detection is correct and adjusted accordingly. The problem is that throughout the ordinary code in the configure script, the correct detection is not being taken into account, that is, it's hard-coding grep when it shouldn't! That's a bug due to taking for granted that a GNU grep is always available and is exactly spelled 'grep'!

$ diff solaris gnu
< checking for a BSD-compatible install... /usr/bin/ginstall -c
> checking for a BSD-compatible install... /usr/gnu/bin/install -c

< checking for a thread-safe mkdir -p... /usr/bin/gmkdir -p
> checking for a thread-safe mkdir -p... /usr/gnu/bin/mkdir -p

< checking for grep that handles long lines and -e... /usr/bin/ggrep
< checking for egrep... /usr/bin/ggrep -E
> checking for grep that handles long lines and -e... /usr/gnu/bin/grep
> checking for egrep... /usr/gnu/bin/grep -E

< configure: autobuild timestamp... 20170630T011243Z
> configure: autobuild timestamp... 20170630T014822Z

< checking for a sed that does not truncate output... /usr/bin/gsed
> checking for a sed that does not truncate output... /usr/gnu/bin/sed


Once the issue is corrected the configuration can proceed:

checking for a BSD-compatible install... /usr/gnu/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /usr/gnu/bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking whether make supports nested variables... (cached) yes
checking for gcc... /usr/bin/gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether /usr/bin/gcc accepts -g... yes
checking for /usr/bin/gcc option to accept ISO C89... none needed
checking whether /usr/bin/gcc understands -c and -o together... yes
checking for style of include used by make... GNU
checking dependency style of /usr/bin/gcc... gcc3
checking how to run the C preprocessor... /usr/bin/gcc -E
checking for grep that handles long lines and -e... /usr/gnu/bin/grep
checking for egrep... /usr/gnu/bin/grep -E
checking for ANSI C header files... yes
checking for sys/types.h... yes
checking for sys/stat.h... yes
checking for stdlib.h... yes
checking for string.h... yes
checking for memory.h... yes
checking for strings.h... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for unistd.h... yes
checking minix/config.h usability... no
checking minix/config.h presence... no
checking for minix/config.h... no
checking whether it is safe to define __EXTENSIONS__... yes
checking whether _XOPEN_SOURCE should be defined... no
checking for Minix Amsterdam compiler... no
checking for ar... ar
checking the archiver (ar) interface... ar
checking for ar... (cached) ar
checking for ranlib... ranlib
checking build system type... i386-pc-solaris2.11
checking host system type... i386-pc-solaris2.11
checking for _LARGEFILE_SOURCE value needed for large files... no
checking for special C compiler options needed for large files... no
checking for _FILE_OFFSET_BITS value needed for large files... no
checking for /usr/bin/gcc option to accept ISO C99... unsupported
checking for /usr/bin/gcc option to accept ISO C89... (cached) none needed
checking for /usr/bin/gcc option to accept ISO Standard C... (cached) none needed
configure: autobuild project... GNU M4
configure: autobuild revision... 1.4.18
configure: autobuild hostname... desktop-01
configure: autobuild timestamp... 20170630T014822Z
checking for unsigned long long int... yes
checking for long long int... yes
checking for unsigned long long int... (cached) yes
checking for size_t... yes
checking for working alloca.h... yes
checking for alloca... yes
checking whether <wchar.h> uses 'inline' correctly... yes
checking for btowc... yes
checking for setrlimit... yes
checking for sigaltstack... yes
checking for canonicalize_file_name... yes
checking for getcwd... yes
checking for readlink... yes
checking for realpath... yes
checking for _set_invalid_parameter_handler... no
checking for fcntl... yes
checking for symlink... yes
checking for mempcpy... no
checking for fpurge... no
checking for __fpurge... yes
checking for __freadahead... no
checking for __freading... yes
checking for getdtablesize... yes
checking for getprogname... yes
checking for getexecname... yes
checking for gettimeofday... yes
checking for lstat... yes
checking for mbsinit... yes
checking for mbrtowc... yes
checking for mprotect... yes
checking for mkstemp... yes
checking for nl_langinfo... yes
checking for pipe2... no
checking for isblank... yes
checking for iswctype... yes
checking for link... yes
checking for secure_getenv... no
checking for getuid... yes
checking for geteuid... yes
checking for getgid... yes
checking for getegid... yes
checking for sigaction... yes
checking for siginterrupt... yes
checking for snprintf... yes
checking for strndup... yes
checking for pipe... yes
checking for vasnprintf... no
checking for wcrtomb... yes
checking for iswcntrl... yes
checking for newlocale... no
checking for setenv... yes
checking for sleep... yes
checking for strdup... yes
checking for wctob... yes
checking for nl_langinfo and CODESET... yes
checking for a traditional french locale... none
checking for ucontext.h... yes
checking for unistd.h... (cached) yes
checking for sys/param.h... yes
checking for sys/socket.h... yes
checking for stdio_ext.h... yes
checking for sys/stat.h... (cached) yes
checking for getopt.h... yes
checking for sys/time.h... yes
checking for langinfo.h... yes
checking for limits.h... yes
checking for xlocale.h... no
checking for math.h... yes
checking for sys/mman.h... yes
checking for malloc.h... yes
checking for sys/cdefs.h... no
checking for spawn.h... yes
checking for wchar.h... yes
checking for stdint.h... (cached) yes
checking for sys/wait.h... yes
checking for features.h... no
checking for wctype.h... yes
checking for dirent.h... yes
checking for inttypes.h... (cached) yes
checking for working C stack overflow detection... yes
checking for correct stack_t interpretation... yes
checking for precise C stack overflow detection... yes
checking for ld used by /usr/bin/gcc... /usr/bin/ld
checking if the linker (/usr/bin/ld) is GNU ld... no
checking for shared library run path origin... done
checking for 64-bit host... no
checking for libsigsegv... yes
checking how to link with libsigsegv... /opt/libsigsegv-2.11/gnu64/lib/libsigsegv.a -lc
checking whether // is distinct from /... no
checking whether realpath works... yes
checking if environ is properly declared... no
checking whether the preprocessor supports include_next... yes
checking whether system header files limit the line length... no
checking for complete errno.h... yes
checking whether strerror_r is declared... yes
checking for strerror_r... yes
checking whether strerror_r returns char *... no
checking for mode_t... yes
checking for sig_atomic_t... yes
checking for working fcntl.h... no (bad O_NOATIME)
checking for pid_t... yes
checking whether frexp() can be used without linking with libm... yes
checking whether alarm is declared... yes
checking whether long double and double are the same... no
checking whether stdin defaults to large file offsets... yes
checking whether fseeko is declared... yes
checking for fseeko... yes
checking whether fflush works on input streams... yes
checking whether stat file-mode macros are broken... no
checking for nlink_t... yes
checking whether ftello is declared... yes
checking for ftello... yes
checking whether ftello works... yes
checking whether getdtablesize is declared... yes
checking for getopt.h... (cached) yes
checking for getopt_long_only... yes
checking whether getopt is POSIX compatible... yes
checking for working GNU getopt function... no
checking whether getenv is declared... yes
checking for C/C++ restrict keyword... __restrict
checking for struct timeval... yes
checking for wide-enough struct timeval.tv_sec member... yes
checking where to find the exponent in a 'double'... word 1 bit 20
checking where to find the exponent in a 'float'... word 0 bit 23
checking whether byte ordering is bigendian... no
checking whether limits.h has ULLONG_WIDTH etc.... no
checking whether getc_unlocked is declared... yes
checking whether we are using the GNU C Library >= 2.1 or uClibc... no
checking for wchar_t... yes
checking for max_align_t... no
checking whether NULL can be used in arbitrary expressions... yes
checking for multithread API to use... none
checking whether lstat correctly handles trailing slash... yes
checking for a sed that does not truncate output... /usr/gnu/bin/sed
checking whether malloc, realloc, calloc are POSIX compliant... yes
checking for stdlib.h... (cached) yes
checking for GNU libc compatible malloc... yes
checking for mbstate_t... yes
checking for a traditional japanese locale... none
checking for a transitional chinese locale... none
checking for a french Unicode locale... fr_FR.UTF-8
checking for mmap... yes
checking for MAP_ANONYMOUS... yes
checking whether memchr works... yes
checking whether <limits.h> defines MIN and MAX... no
checking whether <sys/param.h> defines MIN and MAX... no
checking for promoted mode_t type... mode_t
checking for library containing posix_spawn... none required
checking for posix_spawn... yes
checking whether posix_spawn works... yes
checking whether posix_spawnattr_setschedpolicy is supported... yes
checking whether posix_spawnattr_setschedparam is supported... yes
checking for sigset_t... yes
checking for SIGPIPE... yes
checking for inline... inline
checking for uid_t in sys/types.h... yes
checking whether C symbols are prefixed with underscore at the linker level... no
checking whether snprintf returns a byte count as in C99... yes
checking whether snprintf is declared... yes
checking for stdbool.h that conforms to C99... yes
checking for _Bool... yes
checking for wint_t... yes
checking whether wint_t is too small... no
checking whether stdint.h conforms to C99... no
checking sys/inttypes.h usability... yes
checking sys/inttypes.h presence... yes
checking for sys/inttypes.h... yes
checking sys/bitypes.h usability... no
checking sys/bitypes.h presence... no
checking for sys/bitypes.h... no
checking for bit size of ptrdiff_t... 64
checking for bit size of size_t... 64
checking for bit size of sig_atomic_t... 32
checking for bit size of wchar_t... 32
checking for bit size of wint_t... 32
checking whether sig_atomic_t is signed... yes
checking whether wchar_t is signed... yes
checking whether wint_t is signed... yes
checking for ptrdiff_t integer literal suffix... l
checking for size_t integer literal suffix... ul
checking for sig_atomic_t integer literal suffix...
checking for wchar_t integer literal suffix...
checking for wint_t integer literal suffix...
checking whether strerror(0) succeeds... yes
checking whether strndup is declared... yes
checking whether strnlen is declared... yes
checking whether strsignal is declared... yes
checking whether sys_siglist is declared... no
checking whether strstr works... yes
checking whether ldexp() can be used without linking with libm... yes
checking for struct timespec in <time.h>... yes
checking whether clearerr_unlocked is declared... no
checking whether feof_unlocked is declared... no
checking whether ferror_unlocked is declared... no
checking whether fflush_unlocked is declared... no
checking whether fgets_unlocked is declared... no
checking whether fputc_unlocked is declared... no
checking whether fputs_unlocked is declared... no
checking whether fread_unlocked is declared... no
checking whether fwrite_unlocked is declared... no
checking whether getchar_unlocked is declared... yes
checking whether putc_unlocked is declared... yes
checking whether putchar_unlocked is declared... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for intmax_t... yes
checking for snprintf... (cached) yes
checking for strnlen... yes
checking for wcslen... yes
checking for wcsnlen... yes
checking for mbrtowc... (cached) yes
checking for wcrtomb... (cached) yes
checking whether _snprintf is declared... no
checking whether printf supports size specifiers as in C99... yes
checking whether printf supports 'long double' arguments... yes
checking whether printf supports infinite 'double' arguments... no
checking whether printf supports infinite 'long double' arguments... no
checking whether printf supports the 'a' and 'A' directives... no
checking whether printf supports the 'F' directive... yes
checking whether printf supports the 'n' directive... yes
checking whether printf supports the 'ls' directive... no
checking whether printf supports the grouping flag... yes
checking whether printf supports the left-adjust flag correctly... yes
checking whether printf supports the zero flag correctly... no
checking whether printf supports large precisions... yes
checking whether printf survives out-of-memory conditions... yes
checking whether to use C++... no
checking whether ungetc works on arbitrary bytes... yes
checking whether getcwd (NULL, 0) allocates memory for result... yes
checking for getcwd with POSIX signature... yes
checking for inttypes.h... (cached) yes
checking whether the inttypes.h PRIxNN macros are broken... no
checking for LC_MESSAGES... yes
checking for CFPreferencesCopyAppValue... no
checking for CFLocaleCopyCurrent... no
checking whether setenv is declared... yes
checking search.h usability... yes
checking search.h presence... yes
checking for search.h... yes
checking for tsearch... yes
checking whether strdup is declared... yes
checking whether unsetenv is declared... yes
checking for alloca as a compiler built-in... yes
checking whether to enable assertions... yes
checking whether btowc(0) is correct... yes
checking whether btowc(EOF) is correct... guessing yes
checking for __builtin_expect... yes
checking whether sigaltstack is declared... yes
checking for stack_t... yes
checking whether // is distinct from /... (cached) no
checking whether dup2 works... yes
checking for error_at_line... no
checking whether fflush works on input streams... (cached) yes
checking whether fcntl handles F_DUPFD correctly... yes
checking whether fcntl understands F_DUPFD_CLOEXEC... yes
checking whether fflush works on input streams... (cached) yes
checking whether conversion from 'int' to 'long double' works... yes
checking whether fopen recognizes a trailing slash... yes
checking for __fpending... yes
checking whether __fpending is declared... yes
checking whether fpurge is declared... no
checking whether frexp works... yes
checking whether frexpl is declared... yes
checking whether frexpl() can be used without linking with libm... no
checking for fseeko... (cached) yes
checking whether fflush works on input streams... (cached) yes
checking for ftello... (cached) yes
checking whether ftello works... (cached) yes
checking whether getdtablesize works... yes
checking whether program_invocation_name is declared... no
checking whether program_invocation_short_name is declared... no
checking whether __argv is declared... no
checking whether __progname is defined in default libraries... yes
checking whether gettimeofday clobbers localtime buffer... no
checking for gettimeofday with POSIX signature... yes
checking whether isnan(double) can be used without linking with libm... yes
checking whether isnan(float) can be used without linking with libm... yes
checking whether isnan(float) works... yes
checking whether isnan(long double) can be used without linking with libm... yes
checking whether isnanl works... yes
checking whether langinfo.h defines CODESET... yes
checking whether langinfo.h defines T_FMT_AMPM... yes
checking whether langinfo.h defines ERA... yes
checking whether langinfo.h defines YESEXPR... yes
checking for libsigsegv... (cached) yes
checking how to link with libsigsegv... /opt/libsigsegv-2.11/gnu64/lib/libsigsegv.a -lc
checking whether locale.h conforms to POSIX:2001... yes
checking whether struct lconv is properly defined... yes
checking whether lseek detects pipes... yes
checking whether NAN macro works... yes
checking whether HUGE_VAL works... yes
checking whether mbrtowc handles incomplete characters... guessing yes
checking whether mbrtowc works as well as mbtowc... guessing yes
checking whether mbrtowc handles a NULL pwc argument... yes
checking whether mbrtowc handles a NULL string argument... yes
checking whether mbrtowc has a correct return value... yes
checking whether mbrtowc returns 0 when parsing a NUL character... guessing yes
checking whether mbrtowc works on empty input... yes
checking whether the C locale is free of encoding errors... yes
checking whether mbrtowc handles incomplete characters... (cached) guessing yes
checking whether mbrtowc works as well as mbtowc... (cached) guessing yes
checking for mkdtemp... yes
checking for working mkstemp... yes
checking whether YESEXPR works... yes
checking for obstacks that work with any size object... no
checking whether open recognizes a trailing slash... yes
checking whether posix_spawn_file_actions_addclose works... no
checking whether posix_spawn_file_actions_adddup2 works... no
checking whether posix_spawn_file_actions_addopen works... no
checking whether frexp works... (cached) yes
checking whether ldexp can be used without linking with libm... (cached) yes
checking whether frexpl() can be used without linking with libm... (cached) no
checking whether ldexpl() can be used without linking with libm... no
checking whether program_invocation_name is declared... (cached) no
checking whether program_invocation_short_name is declared... (cached) no
checking for raise... yes
checking for sigprocmask... yes
checking for rawmemchr... no
checking whether readlink signature is correct... yes
checking whether readlink handles trailing slash correctly... yes
checking for working re_compile_pattern... no
checking libintl.h usability... yes
checking libintl.h presence... yes
checking for libintl.h... yes
checking whether isblank is declared... yes
checking whether rename honors trailing slash on destination... no
checking whether rename honors trailing slash on source... yes
checking whether rename manages hard links correctly... yes
checking whether rename manages existing destinations correctly... yes
checking whether rmdir works... yes
checking for __secure_getenv... no
checking for issetugid... yes
checking for struct sigaction.sa_sigaction... yes
checking for volatile sig_atomic_t... yes
checking for sighandler_t... no
checking for signbit macro... no
checking for signbit compiler built-ins... yes
checking for sigprocmask... (cached) yes
checking for stdint.h... (cached) yes
checking for SIZE_MAX... yes
checking for snprintf... (cached) yes
checking whether snprintf respects a size of 1... yes
checking whether printf supports POSIX/XSI format strings with positions... yes
checking for posix_spawnattr_t... yes
checking for posix_spawn_file_actions_t... yes
checking for ssize_t... yes
checking whether stat handles trailing slashes on directories... yes
checking whether stat handles trailing slashes on files... yes
checking for va_copy... yes
checking for max_align_t... (cached) no
checking whether NULL can be used in arbitrary expressions... (cached) yes
checking which flavor of printf attribute matches inttypes macros... system
checking for strchrnul... yes
checking whether strchrnul works... yes
checking for working strerror function... yes
checking for working strndup... yes
checking for working strnlen... yes
checking for strsignal... yes
checking whether strsignal always returns a string... no
checking whether _sys_siglist is declared... yes
checking whether strstr works in linear time... no
checking whether strstr works... (cached) yes
checking whether strtod obeys C99... no
checking for nlink_t... (cached) yes
checking for ptrdiff_t... yes
checking for vasprintf... yes
checking for vasprintf... (cached) yes
checking for nl_langinfo... (cached) yes
checking for ptrdiff_t... (cached) yes
checking for waitid... yes
checking whether mbrtowc handles incomplete characters... (cached) guessing yes
checking whether mbrtowc works as well as mbtowc... (cached) guessing yes
checking whether wcrtomb return value is correct... no
checking whether iswcntrl works... yes
checking for towlower... yes
checking for wctype_t... yes
checking for wctrans_t... yes
checking for stdint.h... (cached) yes
checking for a traditional french locale... (cached) none
checking for a french Unicode locale... (cached) fr_FR.UTF-8
checking for a traditional french locale... (cached) none
checking for a turkish Unicode locale... none
checking for closedir... yes
checking for dirfd... yes
checking whether dirfd is declared... yes
checking whether dirfd is a macro... no
checking whether dup works... yes
checking whether fdopen sets errno... yes
checking for flexible array member... yes
checking for getpagesize... yes
checking whether getpagesize is declared... yes
checking whether INT32_MAX < INTMAX_MAX... yes
checking whether INT64_MAX == LONG_MAX... yes
checking whether UINT32_MAX < UINTMAX_MAX... yes
checking whether UINT64_MAX == ULONG_MAX... yes
checking where to find the exponent in a 'double'... (cached) word 1 bit 20
checking where to find the exponent in a 'float'... (cached) word 0 bit 23
checking where to find the exponent in a 'long double'... word 2 bit 0
checking whether link obeys POSIX... no
checking for setlocale... yes
checking for uselocale... no
checking for a traditional french locale... (cached) none
checking for a french Unicode locale... (cached) fr_FR.UTF-8
checking for a traditional japanese locale... (cached) none
checking for a transitional chinese locale... (cached) none
checking for a french Unicode locale... (cached) fr_FR.UTF-8
checking for mmap... (cached) yes
checking for MAP_ANONYMOUS... yes
checking for mmap... (cached) yes
checking for MAP_ANONYMOUS... yes
checking for a traditional french locale... (cached) none
checking for a french Unicode locale... (cached) fr_FR.UTF-8
checking for opendir... yes
checking for putenv compatible with GNU and SVID... no
checking whether _putenv is declared... no
checking for mmap... (cached) yes
checking for MAP_ANONYMOUS... yes
checking for mmap... (cached) yes
checking for MAP_ANONYMOUS... yes
checking for readdir... yes
checking whether setenv validates arguments... yes
checking for a traditional french locale... (cached) none
checking for a french Unicode locale... (cached) fr_FR.UTF-8
checking for a traditional japanese locale... (cached) none
checking for a transitional chinese locale... (cached) none
checking whether sleep is declared... yes
checking for working sleep... yes
checking for working stdalign.h... yes
checking for mmap... (cached) yes
checking for MAP_ANONYMOUS... yes
checking for mmap... (cached) yes
checking for MAP_ANONYMOUS... yes
checking whether symlink handles trailing slash correctly... yes
checking for unsetenv... yes
checking for unsetenv() return type... int
checking whether unsetenv obeys POSIX... no
checking for a traditional french locale... (cached) none
checking for a french Unicode locale... (cached) fr_FR.UTF-8
checking for a traditional japanese locale... (cached) none
checking for a transitional chinese locale... (cached) none
checking whether wctob works... guessing yes
checking whether wctob is declared... yes
checking whether an open file can be renamed... yes
checking if changeword is wanted... no
checking which shell to use for syscmd... /bin/bash
checking if malloc debugging is wanted... no
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: creating doc/Makefile
config.status: creating lib/Makefile
config.status: creating src/Makefile
config.status: creating tests/Makefile
config.status: creating checks/Makefile
config.status: creating examples/Makefile
config.status: creating lib/config.h
config.status: executing depfiles commands
config.status: executing stamp-h commands


$ zfs snapshot $DS/M4/m4-1.4.18-gnu64@config

$ gmake
... 

$ gmake check
...
===================================
Testsuite summary for GNU M4 1.4.18
===================================

# TOTAL: 170
# PASS:  155
# SKIP:  15
# XFAIL: 0
# FAIL:  0
# XPASS: 0
# ERROR: 0

===================================


$ zfs snapshot $DS/M4/m4-1.4.18-gnu64@build

# X=m4-1.4.18
# zfs create -o mountpoint=/opt/$X rpool/VARSHARE/$X
# zfs create rpool/VARSHARE/$X/gnu64
# zfs list -o name -r rpool/VARSHARE |grep $X
rpool/VARSHARE/m4-1.4.18
rpool/VARSHARE/m4-1.4.18/gnu64


# cd /home/.../software/M4/$X-gnu64

# source ../setenv-gnu64
# gmake install
...

# zfs snapshot rpool/VARSHARE/$X/gnu64@release
# zfs list -o name -r -t all rpool/VARSHARE |grep $X
rpool/VARSHARE/m4-1.4.18
rpool/VARSHARE/m4-1.4.18/gnu64

rpool/VARSHARE/m4-1.4.18/gnu64@release

# ll -oR /opt/$X/*
/opt/m4-1.4.18/gnu64:
...
drwxr-xr-x 2 root ... lib
drwxr-xr-x 2 root ... bin
drwxr-xr-x 4 root ... share

/opt/m4-1.4.18/gnu64/lib:
...
-rw-r--r-- 1 root ... charset.alias

/opt/m4-1.4.18/gnu64/bin:
...
-rwxr-xr-x 1 root ... m4

/opt/m4-1.4.18/gnu64/share:
...
drwxr-xr-x 2 root ... info
drwxr-xr-x 3 root ... man

/opt/m4-1.4.18/gnu64/share/info:
...
-rw-r--r-- 1 root ... m4.info
-rw-r--r-- 1 root ... m4.info-1
-rw-r--r-- 1 root ... m4.info-2
-rw-r--r-- 1 root ... dir

/opt/m4-1.4.18/gnu64/share/man:
...
drwxr-xr-x 2 root ... man1

/opt/m4-1.4.18/gnu64/share/man/man1:
...
-rw-r--r-- 1 root ... m4.1


# file /opt/m4-1.4.18/gnu64/bin/m4
/opt/m4-1.4.18/gnu64/bin/m4: ELF 64-bit LSB executable AMD64
...

That's it, finally!
This was a very very long post due to some listings.
But I believe it were necessary to a pristine understanding of the basics.