Meson build system for Dinit
=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Buidling Dinit via Meson
=-=-=-=-=-=-=-=-=-=-=-=-

Building Dinit is possible via two build systems: Meson and Make (makefiles).
This file contains instructions for building Dinit using Meson.
Bulding dinit via Meson requires Meson 0.56.0 or later and a C++11 compiler
(GCC version 4.9 or later, or Clang ~5.0 or later, should be fine).


<!> Special notes about building Dinit via Meson
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Please keep in mind:

1. The Meson build system for Dinit is an experimental way to build Dinit. 
   It may not work flawlessly in all cases. Please report bugs at
   https://github.com/davmac314/dinit/issues.
2. The primary build system is based on "make" (it requires GNU Make). It is documented in
   the file BUILD. It is currently recommended as it is less likely to cause issues. However,
   the Meson-based build has been proven to work for straight-forward builds that follow this
   guide. 

The meson-based build system has the following limitations:
1. Sanitizers cannot be enabled only for tests, as they are by default in a Make-based build.
2. Test output from unit tests is inhibited. The logs must be inspected manually after test
   execution.


Short version
=-=-=-=-=-=-=

Run "meson setup builddir && meson compile -C builddir". Your system type will
hopefully be detected automatically and appropriate configuration chosen, and Dinit
will be built. Skip to "Installation".

If this fails, if you want to run the tests, or if you are cross-compiling, read the "long
version" instructions.


Long version
=-=-=-=-=-=-

In general Meson will correctly determine the configuration required to build Dinit automatically.

First prepare the "build directory":

    meson setup builddir/

This command configures a "build directory" in "builddir/". You can choose another name if
desired, but don't use a directory that is part of the Dinit source tree such as build/ or src/.

The "meson setup" command will prepare to build Dinit including the dinit daemon, dinitctl utility
and the shutdown/reboot/soft-reboot/halt utilities by default. Tests will not be built. If you wish to change
the build options, see the next section. 

Once "meson setup" has completed successfully, you can compile Dinit with:

     meson compile -C builddir



Custom build options
=-=-=-=-=-=-=-=-=-=-

Dinit should generally build with no additional options, however if desired or necessary custom
options can be passed via the "meson setup" command line:

     meson setup -Doption=value builddir/

It is also possible to modify the original "meson_options.txt" file and set values there.

Custom options:
 shutdown-prefix           : Name prefix for "shutdown", "halt" and "reboot"
                             commands (if they are built).
                             This affects both the output, and what command dinit
                             will execute as part of system shutdown. If you want
                             to install Dinit alongside another init system with
                             its own shutdown/halt/reboot commands, set
                             this (for eg. to "dinit-").
                             Available values : any string
                             Default value : (empty)

 build-shutdown            : Whether to build the "shutdown" (and "halt" etc) utilities.
                             These are only useful if dinit is the system init
                             (i.e. the PID 1 process). You probably don't want
                             this unless building for Linux.
                             Available values : enabled, disabled, auto
                             Default value : auto

 dinit-control-socket-path : Default full path to the control socket, for when
                             Dinit runs as system service manager.
                             Available values : any filesystem path
                             Default value : /run/dinitctl

 unit-tests                : Build and run unit tests. See "Running the test suite", below.
                             Available values: true, false
                             Default value : false

 igr-tests                 : Build and run integration tests. See "Running the test suite", below.
                             Available values : true, false
                             Default value : false
 
 fuzzer                    : Build Dinit's fuzzer tests (using LLVM's Libfuzzer). See "Running
                             fuzzer", below.
                             Available values : true, false
                             Default value : false

 use-utmpx                 : Whether to build support for manipulating the
                             utmp/utmpx database via the related POSIX functions.
                             This may be required (along with appropriate service
                             configuration) for utilities like "who" to work
                             correctly (the service configuration items "inittab-id"
                             and "inittab-line" have no effect if this is disabled).
                             If not set to any value, support is enabled for certain
                             systems automatically and disabled for all others.
                             Available values : enabled, disabled, auto
                             Default value : auto

 use-initgroups            : Whether to initialize supplementary groups for run-as services. The C
                             API for this is not in POSIX, but is in practice supported on just
                             about every relevant system, so it is enabled by default. If it is
                             not supported on yours, you can explicitly disable it.
                             Available values : true, false
                             Default value : true

 dinit-sbindir             : Default full path to the dinit executables. Note that Dinit doesn't
                             use Meson's "sbindir" option; see "Why we use another option for
                             sbindir?", below.
                             Available values : any filesystem path
                             Default value : /sbin
                             
 man-pages                 : Build Dinit's man pages.
                             Available values : true, false
                             Default value : true

 default-auto-restart      : When to automatically restart services.
                             This controls the default value for the "restart" service setting;
                             see the dinit-service(5) man page for details.
                             Available : ALWAYS, ON_FAILURE, NEVER
                             Default value : ALWAYS

 default-start-timeout     : Default start-timeout for services. 
                             Specifies the time in seconds allowed for the service to start. If
                             the service takes longer than this, service startup will be cancelled
                             (service processes will be signalled to cause termination). The
                             default if unspecified is 60 seconds. (The value can be overridden
                             for individual services via the service description).
                             Available values : any positive integer
                             Default value : 60

 default-stop-timeout      : Default stop-timeout for services by default.
                             Specifies the time in seconds allowed for the service to stop. If the
                             service takes longer than this, its process group is sent a SIGKILL
                             signal which should cause it to terminate immediately. The default if
                             unspecified is 10 seconds. (The value can be overridden for
                             individual services via the service description).
                             Available values : any positive integer
                             Default value : 10
                             
 support-cgroups           : Enable Cgroups support.
                             Available values : enabled, disabled, auto
                             Default value : auto

 build-shutdown            : Whether to build the shutdown/reboot/halt utilities.
                             Available values : enabled, disabled, auto
                             Default value : auto


Running the test suite
=-=-=-=-=-=-=-=-=-=-=-

Enable the "unit-tests" option to run the unit tests:

     meson setup -Dunit-tests=true builddir/
     
In Dinit's make build system -fsanitize is usually enabled for unit tests. The meson build system
doesn't support this, but you can opt to enable sanitizers for the entire build (including Dinit
binaries) if you choose:

     meson setup -Db_sanitize='address,undefined' builddir/

Enable "igr-tests" to run the integration tests:

     meson setup -Digr-tests=true builddir/

(The integration tests are more fragile than the unit tests, but give a
better indication that Dinit will actually work correctly on your system).

Finally, compile Dinit and run tests:

     meson compile -C builddir
     meson test -C builddir

The test status will be reported. The test logs will be available in
"builddir/meson-logs/testlog.txt".


Installation
=-=-=-=-=-=-

You can install Dinit via this command:

     meson install -C builddir

If you want to install to an alternate root (eg for packaging purposes),
specify that root via DESTDIR:

     DESTDIR=/tmp/temporary-install-path meson install -C builddir

The dinit executable will be put in "dinit-sbindir" option value (by default /sbin)
(or rather, in $DESTDIR/sbin), which may not be on the path for normal users.
Consider making a symbolic link to /usr/sbin/dinit.


Running the fuzzer
=-=-=-=-=-=-=-=-=-

In addition to the standard test suite, there is experimental support for
fuzzing the control protocol handling using LLVM/clang's fuzzer (libFuzzer).
Enable the "fuzzer" option to build the fuzzer:

    meson setup -Dfuzzer=true builddir

Then change current directory to builddir/src/tests/cptests/, create a "corpus" directory and run
the fuzzer:

    mkdir corpus
    ./fuzz corpus

This will auto-generate test data as it finds input which triggers new execution paths. Check
libFuzzer documentation for further details.


Why do we use another option for sbindir?
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

Old versions of Meson force "sbindir" to be prefixed by the "prefix" property (eg /usr, resulting
in /usr/sbin). For Dinit it is normal to use /sbin as the destination for executables, so the
Meson build system for Dinit uses "dinit-sbindir" instead of the default "sbindir". (The
underlying issue has been fixed in Meson 0.62.0, but for now Dinit continues to use the alternate
setting to retain backwards compatibility with earlier versions of Meson).


Some notes
=-=-=-=-=-

1. Dinit uses a "custom" buildtype with "'optimization=s', 'debug=false'"
   (-Os, no debug) by default.
2. To build with debug symbols, use "meson setup -Ddebug=true builddir" or
   a buildtype with "debug=true"
3. To enable LTO, use "meson setup -Db_lto=true builddir".
