123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- Building Dinit
- =-=-=-=-=-=-=-
- Building Dinit should be a straight-forward process. It requires GNU make and a C++11 compiler
- (GCC version 4.9 and later, or Clang ~5.0 and later, should be fine)
- On the directly supported operating systems - Linux, OpenBSD, FreeBSD and Darwin (macOS) - a
- suitable build configuration is provided and should be used automatically. For other systems,
- or to fine tune or correct the configuration, create and edit the "mconfig" file (start by
- copying one for a particular OS from the "configs" directory) to choose appropriate values for
- the configuration variables defined within. In particular:
- CXX : should be set to the name of the C++ compiler (and link driver)
- CXXOPTS : are options passed to the compiler during compilation (see note for GCC below)
- LDFLAGS : are any extra flags required for linking; should not normally be needed
- (FreeBSD requires -lrt).
- Note that the "eg++" or "clang++" package must be installed on OpenBSD as the default "g++"
- compiler is too old. Clang is part of the base system in recent releases.
- Then, change into the "src" directory, and run "make" (or "gmake" if the system make is not
- GNU make, such as on most BSD systems):
- cd src
- make
- If everything goes smoothly this will build dinit, dinitctl, and optionally the shutdown
- utility. Use "make install" to install; you can specify an alternate installation by
- setting the "DESTDIR" variable, eg "make DESTDIR=/tmp/temporary-install-path install".
- Other configuration variables
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- There are a number of other variables you can set in the mconfig file which affect the build:
- SBINDIR=...
- Where the "/sbin" directory is. Executables will be installed here.
- MANDIR=...
- Where the "man" directory is. Man pages will be installed here.
- SYSCONTROLSOCKET=...
- Default full path to the control socket, for when Dinit runs as system service manager.
- BUILD_SHUTDOWN=yes|no
- 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.
- USE_UTMPX=1|0
- Whether to build support for manipulating the utmp/utmpx database via the related POSIX
- functions. If not set to any value, support is enabled for certain systems automatically
- and disabled for all others.
- SANITIZE_OPTS=...
- Any options to enable run-time sanitizers or additional safety checks. This will be used
- only when building tests. It can safely be left blank.
- Running test suite
- =-=-=-=-=-=-=-=-=-
- Build the "check" target in order to run the test suite:
- make check
- The standard mconfig options enable various sanitizers during build of the tests. On Linux you may
- see an error such as the following:
- make[3]: Leaving directory '/home/davmac/workspace/dinit/src/tests/cptests'
- ./tests
- ==25332==ERROR: AddressSanitizer failed to allocate 0xdfff0001000 (15392894357504) bytes at
- address 2008fff7000 (errno: 12)
- ==25332==ReserveShadowMemoryRange failed while trying to map 0xdfff0001000 bytes. Perhaps
- you're using ulimit -v
- make[2]: *** [Makefile:12: run-tests] Aborted
- If you get this, either disable the address sanitizer or make sure you have overcommit enabled:
- echo 1 > /proc/sys/vm/overcommit_memory
- Any test failures will abort the test suite run immediately.
- In addition to the standard test suite, there is experimental support for fuzzing the control
- protocol handling using LLVM/clang's fuzzer (libFuzzer). Change to the `src/tests/cptests`
- directory and build the "fuzz" target:
- make fuzz
- Then 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.
- Special note for GCC/Libstdc++
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- (Note: the issue discussed here has apparently been resolved in recent GCC versions).
- GCC 5.x onwards includes a "dual ABI" in its standard library implementation, aka Libstdc++.
- Compiling against the newer (C++11 and later) ABI can be achieved by adding
- -D_GLIBCXX_USE_CXX11_ABI=1 to the compiler command line; this uses a non-standard language
- extension to differently mangle symbol names in order to link against the new ABI versions.
- (Some systems may be configured to build with the new ABI by default, and in that case you
- build against the old ABI using D_GLIBCXX_USE_CXX11_ABI=1).
- This is problematic for several reasons. First, it prevents linking against the new ABI with
- other compilers that do not understand the language extension (LLVM i.e. clang++ does so
- in recent versions, so this is perhaps no longer much of a problem in practice). Secondly,
- some aspects of library behavior are ABI-dependent but cannot be changed using the ABI
- macro; in particular, exceptions thrown as a result of failed I/O operations are, in GCC
- versions 5.x and 6.x, always "old ABI" exceptions which cannot be caught by code compiled
- against the new ABI, and in GCC version 7.x they are always "new ABI" exceptions which cannot
- be caught by code compiled against the old ABI. Since the one library object now supposedly
- houses both ABIs, this means that at least one of the two ABIs is always broken.
- A blog post describing the dual ABI mechanism can be found here:
- https://developers.redhat.com/blog/2015/02/05/gcc5-and-the-c11-abi/
- The bug regarding the issue with catching other-ABI exceptions is here:
- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66145
- Since Dinit is affected by this bug, the unfortunate possibility exists to break Dinit by
- upgrading GCC. If you have libstdc++ corresponding to GCC 5.x or 6.x, you *must* build with
- the old ABI, but Dinit will be broken if you upgrade to GCC 7. If you have libstdc++ from
- GCC 7, you *must* build with the new ABI. If the wrong ABI is used, Dinit may still run
- successfully but any attempt to load a non-existing service, for example, will cause Dinit
- to crash.
|