Fix mistakes in cptest asserts
[oweals/dinit.git] / BUILD.txt
1 Building Dinit
2 =-=-=-=-=-=-=-
3
4 Building Dinit should be a straight-forward process. It requires GNU make and a C++11 compiler
5 (GCC version 4.9 and later, or Clang ~5.0 and later, should be fine)
6
7 On the directly supported operating systems - Linux, OpenBSD, FreeBSD and Darwin (macOS) - a
8 suitable build configuration is provided and will be used automatically if no manual configuration
9 is supplied. For other systems, or to fine tune or correct the configuration, create and edit the
10 "mconfig" file (start by copying one for a particular OS from the "configs" directory) to choose
11 appropriate values for the configuration variables defined within. In particular:
12
13   CXX : should be set to the name of the C++ compiler (and link driver)
14   CXXOPTS :  are options passed to the compiler during compilation (see note for GCC below)
15   LDFLAGS :  are any extra flags required for linking; should not normally be needed
16              (FreeBSD requires -lrt).
17
18 Note that the "eg++" or "clang++" package must be installed on OpenBSD as the default "g++"
19 compiler is too old. Clang is part of the base system in recent releases.
20
21 Then, change into the "src" directory, and run "make" (or "gmake" if the system make is not
22 GNU make, such as on most BSD systems):
23
24     cd src
25     make
26
27 If everything goes smoothly this will build dinit, dinitctl, and optionally the shutdown
28 utility. Use "make install" to install; you can specify an alternate installation by
29 setting the "DESTDIR" variable, eg "make DESTDIR=/tmp/temporary-install-path install".
30
31
32 Recommended Compiler options
33 =-=-=-=-=-=-=-=-=-=-=-=-=-=-
34
35 Dinit should generally build fine with no additional options, other than:
36  -std=c++11 :  may be required to select correct C++ standard.
37  -D_GLIBCXX_USE_CXX11_ABI=1 :   see "Special note for GCC/Libstdc++", below. Not needed for
38                                 most modern systems.
39
40 Recommended options, supported by at least GCC and Clang, are:
41  -Os       : optimise for size
42  -fno-rtti : disable RTTI (run-time type information), it is not required by Dinit.
43              However, on some platforms such as Mac OS (and historically FreeBSD, IIRC), this
44              prevents exceptions working correctly.
45  -fno-plt  : enables better code generation for non-static builds, but may cause unit test
46              failures on some older versions of FreeBSD (11.2-RELEASE-p4 with clang++ 6.0.0).
47  -flto     : perform link-time optimisation (option required at compile and link).
48
49 Consult compiler documentation for further information on the above options.
50
51
52 Other configuration variables
53 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=
54
55 There are a number of other variables you can set in the mconfig file which affect the build:
56
57 SBINDIR=...
58     Where the "/sbin" directory is. Executables will be installed here.
59 MANDIR=...
60     Where the "man" directory is. Man pages will be installed here.
61 SYSCONTROLSOCKET=...
62     Default full path to the control socket, for when Dinit runs as system service manager.
63 BUILD_SHUTDOWN=yes|no
64     Whether to build the "shutdown" (and "halt" etc) utilities. These are only useful
65     if dinit is the system init (i.e. the PID 1 process). You probably don't want this
66     unless building for Linux.
67 SHUTDOWN_PREFIX=...
68     Name prefix for "shutdown", "halt" and "reboot" commands (if they are built). This affects
69     both the output, and what command dinit will execute as part of system shutdown.
70     If you want to install Dinit alongside another init system with its own shutdown/halt/reboot
71     commands, set this (for eg. to "dinit-").
72 USE_UTMPX=1|0
73     Whether to build support for manipulating the utmp/utmpx database via the related POSIX
74     functions. This may be required (along with appropriate service configuration) for utilities
75     like "who" to work correctly (the service configuration items "inittab-id" and "inittab-line"
76     have no effect if this is disabled). If not set to any value, support is enabled for certain
77     systems automatically and disabled for all others.
78 SANITIZE_OPTS=...
79     Any options to enable run-time sanitizers or additional safety checks. This will be used
80     only when building tests. It can safely be left blank.
81
82
83 Running test suite
84 =-=-=-=-=-=-=-=-=-
85
86 Build the "check" target in order to run the test suite:
87
88     make check
89
90 The standard mconfig options enable various sanitizers during build of the tests. On Linux you may
91 see an error such as the following:
92
93     make[3]: Leaving directory '/home/davmac/workspace/dinit/src/tests/cptests'
94     ./tests
95     ==25332==ERROR: AddressSanitizer failed to allocate 0xdfff0001000 (15392894357504) bytes at
96     address 2008fff7000 (errno: 12)
97     ==25332==ReserveShadowMemoryRange failed while trying to map 0xdfff0001000 bytes. Perhaps
98     you're using ulimit -v
99     make[2]: *** [Makefile:12: run-tests] Aborted
100
101 If you get this, either disable the address sanitizer or make sure you have overcommit enabled:
102
103     echo 1 > /proc/sys/vm/overcommit_memory 
104
105 Any test failures will abort the test suite run immediately.
106
107 To run the integration tests:
108
109     make check-igr
110     
111 (The integration tests are more fragile than the unit tests, but give a better indication that
112 Dinit will actually work correctly on your system).
113
114 In addition to the standard test suite, there is experimental support for fuzzing the control
115 protocol handling using LLVM/clang's fuzzer (libFuzzer). Change to the `src/tests/cptests`
116 directory and build the "fuzz" target:
117
118     make fuzz
119
120 Then create a "corpus" directory and run the fuzzer:
121
122     mkdir corpus
123     ./fuzz corpus
124
125 This will auto-generate test data as it finds input which triggers new execution paths. Check
126 libFuzzer documentation for further details.
127
128
129 Special note for GCC/Libstdc++
130 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
131
132 (Note: the issue discussed here has apparently been resolved in recent GCC versions).
133
134 GCC 5.x onwards includes a "dual ABI" in its standard library implementation, aka Libstdc++.
135 Compiling against the newer (C++11 and later) ABI can be achieved by adding
136 -D_GLIBCXX_USE_CXX11_ABI=1 to the compiler command line; this uses a non-standard language
137 extension to differently mangle symbol names in order to link against the new ABI versions.
138
139 (Some systems may be configured to build with the new ABI by default, and in that case you
140 build against the old ABI using D_GLIBCXX_USE_CXX11_ABI=1).
141
142 This is problematic for several reasons. First, it prevents linking against the new ABI with
143 other compilers that do not understand the language extension (LLVM i.e. clang++ does so
144 in recent versions, so this is perhaps no longer much of a problem in practice). Secondly,
145 some aspects of library behavior are ABI-dependent but cannot be changed using the ABI
146 macro; in particular, exceptions thrown as a result of failed I/O operations are, in GCC
147 versions 5.x and 6.x, always "old ABI" exceptions which cannot be caught by code compiled
148 against the new ABI, and in GCC version 7.x they are always "new ABI" exceptions which cannot
149 be caught by code compiled against the old ABI. Since the one library object now supposedly
150 houses both ABIs, this means that at least one of the two ABIs is always broken.
151
152 A blog post describing the dual ABI mechanism can be found here:
153
154     https://developers.redhat.com/blog/2015/02/05/gcc5-and-the-c11-abi/
155
156 The bug regarding the issue with catching other-ABI exceptions is here:
157
158     https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66145
159
160 Since Dinit is affected by this bug, the unfortunate possibility exists to break Dinit by
161 upgrading GCC. If you have libstdc++ corresponding to GCC 5.x or 6.x, you *must* build with
162 the old ABI, but Dinit will be broken if you upgrade to GCC 7. If you have libstdc++ from
163 GCC 7, you *must* build with the new ABI. If the wrong ABI is used, Dinit may still run
164 successfully but any attempt to load a non-existing service, for example, will cause Dinit
165 to crash.