]> git.ipfire.org Git - thirdparty/systemd.git/blob - meson.build
Merge pull request #32121 from CodethinkLabs/basic-mkosi-integration-tests
[thirdparty/systemd.git] / meson.build
1 # SPDX-License-Identifier: LGPL-2.1-or-later
2
3 project('systemd', 'c',
4 version : files('meson.version'),
5 license : 'LGPLv2+',
6 default_options: [
7 'c_std=gnu11',
8 'prefix=/usr',
9 'sysconfdir=/etc',
10 'localstatedir=/var',
11 'warning_level=2',
12 ],
13 meson_version : '>= 0.60.0',
14 )
15
16 libsystemd_version = '0.38.0'
17 libudev_version = '1.7.8'
18
19 conf = configuration_data()
20 conf.set_quoted('PROJECT_URL', 'https://systemd.io/')
21 conf.set('PROJECT_VERSION', meson.project_version().split('~')[0],
22 description : 'Numerical project version (used where a simple number is expected)')
23 conf.set_quoted('PROJECT_VERSION_FULL', meson.project_version(), description : 'Full project version')
24
25 # This is to be used instead of meson.source_root(), as the latter will return
26 # the wrong result when systemd is being built as a meson subproject
27 project_source_root = meson.current_source_dir()
28 project_build_root = meson.current_build_dir()
29 relative_source_path = run_command('realpath',
30 '--relative-to=@0@'.format(project_build_root),
31 project_source_root,
32 check : true).stdout().strip()
33 conf.set_quoted('RELATIVE_SOURCE_PATH', relative_source_path)
34
35 conf.set10('BUILD_MODE_DEVELOPER', get_option('mode') == 'developer',
36 description : 'tailor build to development or release builds')
37
38 feature = get_option('log-message-verification')
39 if feature.auto()
40 have = conf.get('BUILD_MODE_DEVELOPER') == 1
41 else
42 have = feature.enabled()
43 endif
44 conf.set10('LOG_MESSAGE_VERIFICATION', have)
45
46 want_ossfuzz = get_option('oss-fuzz')
47 want_libfuzzer = get_option('llvm-fuzz')
48 if want_ossfuzz and want_libfuzzer
49 error('only one of oss-fuzz or llvm-fuzz can be specified')
50 endif
51
52 fuzzer_build = want_ossfuzz or want_libfuzzer
53
54 # If we're building *not* for actual fuzzing, allow input samples of any size
55 # (for testing and for reproduction of issues discovered with previously-higher
56 # limits).
57 conf.set10('FUZZ_USE_SIZE_LIMIT', fuzzer_build)
58
59 # We'll set this to '1' for EFI builds in a different place.
60 conf.set10('SD_BOOT', false)
61
62 # Create a title-less summary section early, so it ends up first in the output.
63 # More items are added later after they have been detected.
64 summary({'build mode' : get_option('mode')})
65
66 #####################################################################
67
68 # Try to install the git pre-commit hook
69 git_setup_sh = find_program('tools/git-setup.sh', required : false)
70 if git_setup_sh.found()
71 git_hook = run_command(git_setup_sh, check : false)
72 if git_hook.returncode() == 0
73 message(git_hook.stdout().strip())
74 endif
75 endif
76
77 #####################################################################
78
79 fs = import('fs')
80 if get_option('split-bin') == 'auto'
81 split_bin = not fs.is_symlink('/usr/sbin')
82 else
83 split_bin = get_option('split-bin') == 'true'
84 endif
85 conf.set10('HAVE_SPLIT_BIN', split_bin,
86 description : 'bin and sbin directories are separate')
87
88 have_standalone_binaries = get_option('standalone-binaries')
89
90 sysvinit_path = get_option('sysvinit-path')
91 sysvrcnd_path = get_option('sysvrcnd-path')
92 conf.set10('HAVE_SYSV_COMPAT', sysvinit_path != '' and sysvrcnd_path != '',
93 description : 'SysV init scripts and rcN.d links are supported')
94 conf.set10('CREATE_LOG_DIRS', get_option('create-log-dirs'))
95
96 if get_option('hibernate') and not get_option('initrd')
97 error('hibernate depends on initrd')
98 endif
99
100 conf.set10('BUMP_PROC_SYS_FS_FILE_MAX', get_option('bump-proc-sys-fs-file-max'))
101 conf.set10('BUMP_PROC_SYS_FS_NR_OPEN', get_option('bump-proc-sys-fs-nr-open'))
102 conf.set('HIGH_RLIMIT_NOFILE', 512*1024)
103
104 # Meson ignores the preceding arguments when joining paths if an absolute
105 # component is encountered, so this should canonicalize various paths when they
106 # are absolute or relative.
107 prefixdir = get_option('prefix')
108 if not prefixdir.startswith('/')
109 error('Prefix is not absolute: "@0@"'.format(prefixdir))
110 endif
111
112 prefixdir_noslash = '/' + prefixdir.strip('/')
113 bindir = prefixdir / get_option('bindir')
114 sbindir = prefixdir / (split_bin ? 'sbin' : 'bin')
115 sbin_to_bin = split_bin ? '../bin/' : ''
116 libdir = prefixdir / get_option('libdir')
117 sysconfdir = prefixdir / get_option('sysconfdir')
118 includedir = prefixdir / get_option('includedir')
119 datadir = prefixdir / get_option('datadir')
120 localstatedir = '/' / get_option('localstatedir')
121
122 libexecdir = prefixdir / 'lib/systemd'
123 pkglibdir = libdir / 'systemd'
124
125 install_sysconfdir = get_option('install-sysconfdir') != 'false'
126 install_sysconfdir_samples = get_option('install-sysconfdir') == 'true'
127 # Dirs of external packages
128 pkgconfigdatadir = get_option('pkgconfigdatadir') != '' ? get_option('pkgconfigdatadir') : datadir / 'pkgconfig'
129 pkgconfiglibdir = get_option('pkgconfiglibdir') != '' ? get_option('pkgconfiglibdir') : libdir / 'pkgconfig'
130 polkitpolicydir = datadir / 'polkit-1/actions'
131 polkitrulesdir = datadir / 'polkit-1/rules.d'
132 polkitpkladir = localstatedir / 'lib/polkit-1/localauthority/10-vendor.d'
133 xinitrcdir = get_option('xinitrcdir') != '' ? get_option('xinitrcdir') : sysconfdir / 'X11/xinit/xinitrc.d'
134 rpmmacrosdir = get_option('rpmmacrosdir')
135 if rpmmacrosdir != 'no'
136 rpmmacrosdir = prefixdir / rpmmacrosdir
137 endif
138 modprobedir = prefixdir / 'lib/modprobe.d'
139
140 # Our own paths
141 pkgdatadir = datadir / 'systemd'
142 environmentdir = prefixdir / 'lib/environment.d'
143 pkgsysconfdir = sysconfdir / 'systemd'
144 userunitdir = prefixdir / 'lib/systemd/user'
145 userpresetdir = prefixdir / 'lib/systemd/user-preset'
146 tmpfilesdir = prefixdir / 'lib/tmpfiles.d'
147 usertmpfilesdir = prefixdir / 'share/user-tmpfiles.d'
148 sysusersdir = prefixdir / 'lib/sysusers.d'
149 sysctldir = prefixdir / 'lib/sysctl.d'
150 binfmtdir = prefixdir / 'lib/binfmt.d'
151 modulesloaddir = prefixdir / 'lib/modules-load.d'
152 networkdir = prefixdir / 'lib/systemd/network'
153 systemgeneratordir = libexecdir / 'system-generators'
154 usergeneratordir = prefixdir / 'lib/systemd/user-generators'
155 systemenvgeneratordir = prefixdir / 'lib/systemd/system-environment-generators'
156 userenvgeneratordir = prefixdir / 'lib/systemd/user-environment-generators'
157 systemshutdowndir = libexecdir / 'system-shutdown'
158 systemsleepdir = libexecdir / 'system-sleep'
159 systemunitdir = prefixdir / 'lib/systemd/system'
160 systempresetdir = prefixdir / 'lib/systemd/system-preset'
161 udevlibexecdir = prefixdir / 'lib/udev'
162 udevrulesdir = udevlibexecdir / 'rules.d'
163 udevhwdbdir = udevlibexecdir / 'hwdb.d'
164 catalogdir = prefixdir / 'lib/systemd/catalog'
165 kerneldir = prefixdir / 'lib/kernel'
166 kernelinstalldir = kerneldir / 'install.d'
167 factorydir = datadir / 'factory'
168 bootlibdir = prefixdir / 'lib/systemd/boot/efi'
169 testsdir = prefixdir / 'lib/systemd/tests'
170 unittestsdir = testsdir / 'unit-tests'
171 testdata_dir = testsdir / 'testdata'
172 systemdstatedir = localstatedir / 'lib/systemd'
173 catalogstatedir = systemdstatedir / 'catalog'
174 randomseeddir = localstatedir / 'lib/systemd'
175 profiledir = libexecdir / 'portable' / 'profile'
176 repartdefinitionsdir = libexecdir / 'repart/definitions'
177 ntpservicelistdir = prefixdir / 'lib/systemd/ntp-units.d'
178 credstoredir = prefixdir / 'lib/credstore'
179 pcrlockdir = prefixdir / 'lib/pcrlock.d'
180 mimepackagesdir = prefixdir / 'share/mime/packages'
181
182 configfiledir = get_option('configfiledir')
183 if configfiledir == ''
184 configfiledir= sysconfdir
185 endif
186 pkgconfigfiledir = configfiledir / 'systemd'
187
188 docdir = get_option('docdir')
189 if docdir == ''
190 docdir = datadir / 'doc/systemd'
191 endif
192
193 pamlibdir = get_option('pamlibdir')
194 if pamlibdir == ''
195 pamlibdir = libdir / 'security'
196 endif
197
198 pamconfdir = get_option('pamconfdir')
199 if pamconfdir == ''
200 pamconfdir = prefixdir / 'lib/pam.d'
201 endif
202
203 sshconfdir = get_option('sshconfdir')
204 if sshconfdir == ''
205 sshconfdir = sysconfdir / 'ssh/ssh_config.d'
206 endif
207
208 sshdconfdir = get_option('sshdconfdir')
209 if sshdconfdir == ''
210 sshdconfdir = sysconfdir / 'ssh/sshd_config.d'
211 endif
212
213 sshdprivsepdir = get_option('sshdprivsepdir')
214 conf.set10('CREATE_SSHDPRIVSEPDIR', sshdprivsepdir != 'no' and not sshdprivsepdir.startswith('/usr/'))
215 conf.set('SSHDPRIVSEPDIR', sshdprivsepdir, description : 'SSH privilege separation directory')
216
217 libcryptsetup_plugins_dir = get_option('libcryptsetup-plugins-dir')
218 if libcryptsetup_plugins_dir == ''
219 libcryptsetup_plugins_dir = libdir / 'cryptsetup'
220 endif
221
222 memory_accounting_default = get_option('memory-accounting-default')
223 status_unit_format_default = get_option('status-unit-format-default')
224 if status_unit_format_default == 'auto'
225 status_unit_format_default = conf.get('BUILD_MODE_DEVELOPER') == 1 ? 'name' : 'description'
226 endif
227
228 conf.set_quoted('BINDIR', bindir)
229 conf.set_quoted('BINFMT_DIR', binfmtdir)
230 conf.set_quoted('BOOTLIBDIR', bootlibdir)
231 conf.set_quoted('CATALOG_DATABASE', catalogstatedir / 'database')
232 conf.set_quoted('CERTIFICATE_ROOT', get_option('certificate-root'))
233 conf.set_quoted('DOC_DIR', docdir)
234 conf.set_quoted('DOCUMENT_ROOT', pkgdatadir / 'gatewayd')
235 conf.set_quoted('ENVIRONMENT_DIR', environmentdir)
236 conf.set_quoted('INCLUDE_DIR', includedir)
237 conf.set_quoted('LIBDIR', libdir)
238 conf.set_quoted('LIBEXECDIR', libexecdir)
239 conf.set_quoted('KERNEL_INSTALL_DIR', kernelinstalldir)
240 conf.set_quoted('MODPROBE_DIR', modprobedir)
241 conf.set_quoted('MODULESLOAD_DIR', modulesloaddir)
242 conf.set_quoted('PKGSYSCONFDIR', pkgsysconfdir)
243 conf.set_quoted('POLKIT_AGENT_BINARY_PATH', bindir / 'pkttyagent')
244 conf.set_quoted('PREFIX', prefixdir)
245 conf.set_quoted('PREFIX_NOSLASH', prefixdir_noslash)
246 conf.set_quoted('RANDOM_SEED', randomseeddir / 'random-seed')
247 conf.set_quoted('RANDOM_SEED_DIR', randomseeddir)
248 conf.set_quoted('RC_LOCAL_PATH', get_option('rc-local'))
249 conf.set_quoted('SSHCONFDIR', sshconfdir)
250 conf.set_quoted('SSHDCONFDIR', sshdconfdir)
251 conf.set_quoted('SYSCONF_DIR', sysconfdir)
252 conf.set_quoted('SYSCTL_DIR', sysctldir)
253 conf.set_quoted('SYSTEMCTL_BINARY_PATH', bindir / 'systemctl')
254 conf.set_quoted('SYSTEMD_BINARY_PATH', libexecdir / 'systemd')
255 conf.set_quoted('SYSTEMD_EXECUTOR_BINARY_PATH', libexecdir / 'systemd-executor')
256 conf.set_quoted('SYSTEMD_CATALOG_DIR', catalogdir)
257 conf.set_quoted('SYSTEMD_CGROUPS_AGENT_PATH', libexecdir / 'systemd-cgroups-agent')
258 conf.set_quoted('SYSTEMD_CRYPTSETUP_PATH', bindir / 'systemd-cryptsetup')
259 conf.set_quoted('SYSTEMD_EXPORT_PATH', libexecdir / 'systemd-export')
260 conf.set_quoted('SYSTEMD_FSCK_PATH', libexecdir / 'systemd-fsck')
261 conf.set_quoted('SYSTEMD_GROWFS_PATH', libexecdir / 'systemd-growfs')
262 conf.set_quoted('SYSTEMD_HOMEWORK_PATH', libexecdir / 'systemd-homework')
263 conf.set_quoted('SYSTEMD_IMPORT_FS_PATH', libexecdir / 'systemd-import-fs')
264 conf.set_quoted('SYSTEMD_IMPORT_PATH', libexecdir / 'systemd-import')
265 conf.set_quoted('SYSTEMD_INTEGRITYSETUP_PATH', libexecdir / 'systemd-integritysetup')
266 conf.set_quoted('SYSTEMD_KBD_MODEL_MAP', pkgdatadir / 'kbd-model-map')
267 conf.set_quoted('SYSTEMD_LANGUAGE_FALLBACK_MAP', pkgdatadir / 'language-fallback-map')
268 conf.set_quoted('SYSTEMD_MAKEFS_PATH', libexecdir / 'systemd-makefs')
269 conf.set_quoted('SYSTEMD_PULL_PATH', libexecdir / 'systemd-pull')
270 conf.set_quoted('SYSTEMD_SHUTDOWN_BINARY_PATH', libexecdir / 'systemd-shutdown')
271 conf.set_quoted('SYSTEMD_TEST_DATA', testdata_dir)
272 conf.set_quoted('SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH', bindir / 'systemd-tty-ask-password-agent')
273 conf.set_quoted('SYSTEMD_UPDATE_HELPER_PATH', libexecdir / 'systemd-update-helper')
274 conf.set_quoted('SYSTEMD_USERWORK_PATH', libexecdir / 'systemd-userwork')
275 conf.set_quoted('SYSTEMD_MOUNTWORK_PATH', libexecdir / 'systemd-mountwork')
276 conf.set_quoted('SYSTEMD_NSRESOURCEWORK_PATH', libexecdir / 'systemd-nsresourcework')
277 conf.set_quoted('SYSTEMD_VERITYSETUP_PATH', libexecdir / 'systemd-veritysetup')
278 conf.set_quoted('SYSTEM_CONFIG_UNIT_DIR', pkgsysconfdir / 'system')
279 conf.set_quoted('SYSTEM_DATA_UNIT_DIR', systemunitdir)
280 conf.set_quoted('SYSTEM_ENV_GENERATOR_DIR', systemenvgeneratordir)
281 conf.set_quoted('SYSTEM_GENERATOR_DIR', systemgeneratordir)
282 conf.set_quoted('SYSTEM_PRESET_DIR', systempresetdir)
283 conf.set_quoted('SYSTEM_SHUTDOWN_PATH', systemshutdowndir)
284 conf.set_quoted('SYSTEM_SLEEP_PATH', systemsleepdir)
285 conf.set_quoted('SYSTEM_SYSVINIT_PATH', sysvinit_path)
286 conf.set_quoted('SYSTEM_SYSVRCND_PATH', sysvrcnd_path)
287 conf.set_quoted('SYSUSERS_DIR', sysusersdir)
288 conf.set_quoted('TMPFILES_DIR', tmpfilesdir)
289 conf.set_quoted('USER_TMPFILES_DIR', usertmpfilesdir)
290 conf.set_quoted('UDEVLIBEXECDIR', udevlibexecdir)
291 conf.set_quoted('UDEV_HWDB_DIR', udevhwdbdir)
292 conf.set_quoted('UDEV_RULES_DIR', udevrulesdir)
293 conf.set_quoted('USER_CONFIG_UNIT_DIR', pkgsysconfdir / 'user')
294 conf.set_quoted('USER_DATA_UNIT_DIR', userunitdir)
295 conf.set_quoted('USER_ENV_GENERATOR_DIR', userenvgeneratordir)
296 conf.set_quoted('USER_GENERATOR_DIR', usergeneratordir)
297 conf.set_quoted('USER_KEYRING_PATH', pkgsysconfdir / 'import-pubring.gpg')
298 conf.set_quoted('USER_PRESET_DIR', userpresetdir)
299 conf.set_quoted('VENDOR_KEYRING_PATH', libexecdir / 'import-pubring.gpg')
300
301 conf.set('ANSI_OK_COLOR', 'ANSI_' + get_option('ok-color').underscorify().to_upper())
302 conf.set10('ENABLE_URLIFY', get_option('urlify'))
303 conf.set10('ENABLE_FEXECVE', get_option('fexecve'))
304 conf.set10('MEMORY_ACCOUNTING_DEFAULT', memory_accounting_default)
305 conf.set('STATUS_UNIT_FORMAT_DEFAULT', 'STATUS_UNIT_FORMAT_' + status_unit_format_default.to_upper())
306 conf.set_quoted('STATUS_UNIT_FORMAT_DEFAULT_STR', status_unit_format_default)
307
308 conf.set('DEFAULT_TIMEOUT_SEC', get_option('default-timeout-sec'))
309 conf.set('DEFAULT_USER_TIMEOUT_SEC', get_option('default-user-timeout-sec'))
310 conf.set('UPDATE_HELPER_USER_TIMEOUT_SEC', get_option('update-helper-user-timeout-sec'))
311
312 conf.set10('ENABLE_FIRST_BOOT_FULL_PRESET', get_option('first-boot-full-preset'))
313
314 #####################################################################
315
316 cc = meson.get_compiler('c')
317 userspace_c_args = []
318 userspace_c_ld_args = []
319 meson_build_sh = find_program('tools/meson-build.sh')
320
321 want_tests = get_option('tests')
322 slow_tests = want_tests != 'false' and get_option('slow-tests')
323 fuzz_tests = want_tests != 'false' and get_option('fuzz-tests')
324 install_tests = want_tests != 'false' and get_option('install-tests')
325
326 if add_languages('cpp', native : false, required : fuzzer_build)
327 # Used only for tests
328 cxx = meson.get_compiler('cpp')
329 cxx_cmd = ' '.join(cxx.cmd_array())
330 else
331 cxx_cmd = ''
332 endif
333
334 if want_libfuzzer
335 fuzzing_engine = meson.get_compiler('cpp').find_library('Fuzzer', required : false)
336 if fuzzing_engine.found()
337 userspace_c_args += '-fsanitize-coverage=trace-pc-guard,trace-cmp'
338 elif cc.has_argument('-fsanitize=fuzzer-no-link')
339 userspace_c_args += '-fsanitize=fuzzer-no-link'
340 else
341 error('Looks like neither libFuzzer nor -fsanitize=fuzzer-no-link is supported')
342 endif
343 elif want_ossfuzz
344 fuzzing_engine = meson.get_compiler('cpp').find_library('FuzzingEngine')
345 endif
346
347 # Those generate many false positives, and we do not want to change the code to
348 # avoid them.
349 basic_disabled_warnings = [
350 '-Wno-missing-field-initializers',
351 '-Wno-unused-parameter',
352 '-Wno-nonnull-compare',
353 ]
354
355 possible_common_cc_flags = [
356 '-Warray-bounds', # clang
357 '-Warray-bounds=2',
358 '-Wdate-time',
359 '-Wendif-labels',
360 '-Werror=format=2',
361 '-Werror=format-signedness',
362 '-Werror=implicit-function-declaration',
363 '-Werror=implicit-int',
364 '-Werror=incompatible-pointer-types',
365 '-Werror=int-conversion',
366 '-Werror=missing-declarations',
367 '-Werror=missing-prototypes',
368 '-Werror=overflow',
369 '-Werror=override-init',
370 '-Werror=return-type',
371 '-Werror=shift-count-overflow',
372 '-Werror=shift-overflow=2',
373 '-Werror=strict-flex-arrays',
374 '-Werror=undef',
375 '-Wfloat-equal',
376 # gperf prevents us from enabling this because it does not emit fallthrough
377 # attribute with clang.
378 #'-Wimplicit-fallthrough',
379 '-Wimplicit-fallthrough=5',
380 '-Winit-self',
381 '-Wlogical-op',
382 '-Wmissing-include-dirs',
383 '-Wmissing-noreturn',
384 '-Wnested-externs',
385 '-Wold-style-definition',
386 '-Wpointer-arith',
387 '-Wredundant-decls',
388 '-Wshadow',
389 '-Wstrict-aliasing=2',
390 '-Wstrict-prototypes',
391 '-Wsuggest-attribute=noreturn',
392 '-Wunused-function',
393 '-Wwrite-strings',
394 '-Wzero-length-bounds',
395
396 # negative arguments are correctly detected starting with meson 0.46.
397 '-Wno-error=#warnings', # clang
398 '-Wno-string-plus-int', # clang
399
400 '-fdiagnostics-show-option',
401 '-fno-common',
402 '-fstack-protector',
403 '-fstack-protector-strong',
404 '-fstrict-flex-arrays',
405 '--param=ssp-buffer-size=4',
406 ]
407
408 possible_common_link_flags = [
409 '-fstack-protector',
410 ]
411
412 c_args = get_option('c_args')
413
414 # Our json library does not support -ffinite-math-only, which is enabled by -Ofast or -ffast-math.
415 if (('-Ofast' in c_args or '-ffast-math' in c_args or '-ffinite-math-only' in c_args) and '-fno-finite-math-only' not in c_args)
416 error('-Ofast, -ffast-math, or -ffinite-math-only is specified in c_args.')
417 endif
418
419 # Disable -Wmaybe-uninitialized when compiling with -Os/-O1/-O3/etc. There are
420 # too many false positives with gcc >= 8. Effectively, we only test with -O0
421 # and -O2; this should be enough to catch most important cases without too much
422 # busywork. See https://github.com/systemd/systemd/pull/19226.
423 if cc.get_id() == 'gcc' and (not '02'.contains(get_option('optimization')) or
424 cc.version().version_compare('<10') or
425 '-Os' in c_args or
426 '-O1' in c_args or
427 '-O3' in c_args or
428 '-Og' in c_args)
429 possible_common_cc_flags += '-Wno-maybe-uninitialized'
430 endif
431
432 # Disable -Wno-unused-result with gcc, see
433 # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425.
434 if cc.get_id() == 'gcc'
435 possible_common_cc_flags += '-Wno-unused-result'
436 endif
437
438 # --as-needed and --no-undefined are provided by meson by default,
439 # run 'meson configure' to see what is enabled
440 possible_link_flags = [
441 '-Wl,--fatal-warnings',
442 '-Wl,-z,now',
443 '-Wl,-z,relro',
444 ]
445
446 if get_option('b_sanitize') == 'none'
447 possible_link_flags += '-Wl,--warn-common'
448 endif
449
450 if cc.get_id() == 'clang'
451 possible_common_cc_flags += [
452 '-Wno-typedef-redefinition',
453 '-Wno-gnu-variable-sized-type-not-at-end',
454 ]
455 endif
456
457 if get_option('mode') == 'release'
458 # We could enable 'pattern' for developer mode, but that can interfere with
459 # valgrind and sanitizer builds. Also, clang does not zero-initialize unions,
460 # breaking some of our code (https://reviews.llvm.org/D68115).
461 possible_common_cc_flags += '-ftrivial-auto-var-init=zero'
462 endif
463
464 possible_cc_flags = [
465 '-fno-strict-aliasing',
466 '-fstrict-flex-arrays=1',
467 '-fvisibility=hidden',
468 ]
469
470 if get_option('buildtype') != 'debug'
471 possible_cc_flags += [
472 '-ffunction-sections',
473 '-fdata-sections',
474 ]
475
476 possible_link_flags += '-Wl,--gc-sections'
477 endif
478
479 if get_option('mode') == 'developer'
480 possible_cc_flags += '-fno-omit-frame-pointer'
481 endif
482
483 add_project_arguments(
484 cc.get_supported_arguments(
485 basic_disabled_warnings,
486 possible_common_cc_flags
487 ),
488 language : 'c')
489
490 add_project_link_arguments(
491 cc.get_supported_link_arguments(possible_common_link_flags),
492 language : 'c')
493
494 userspace_c_args += cc.get_supported_arguments(possible_cc_flags)
495 userspace_c_ld_args += cc.get_supported_link_arguments(possible_link_flags)
496
497 have = cc.has_argument('-Wzero-length-bounds')
498 conf.set10('HAVE_ZERO_LENGTH_BOUNDS', have)
499
500 if cc.compiles('''
501 #include <time.h>
502 #include <inttypes.h>
503 typedef uint64_t usec_t;
504 usec_t now(clockid_t clock);
505 int main(void) {
506 struct timespec now;
507 return 0;
508 }
509 ''', args: '-Werror=shadow', name : '-Werror=shadow with local shadowing')
510 add_project_arguments('-Werror=shadow', language : 'c')
511 endif
512
513 if cxx_cmd != ''
514 add_project_arguments(cxx.get_supported_arguments(basic_disabled_warnings), language : 'cpp')
515 endif
516
517 cpp = ' '.join(cc.cmd_array() + get_option('c_args')) + ' -E'
518
519 has_wstringop_truncation = cc.has_argument('-Wstringop-truncation')
520
521 #####################################################################
522 # compilation result tests
523
524 conf.set('_GNU_SOURCE', 1)
525 conf.set('__SANE_USERSPACE_TYPES__', true)
526 conf.set10('HAVE_WSTRINGOP_TRUNCATION', has_wstringop_truncation)
527
528 conf.set('SIZEOF_DEV_T', cc.sizeof('dev_t', prefix : '#include <sys/types.h>'))
529 conf.set('SIZEOF_INO_T', cc.sizeof('ino_t', prefix : '#include <sys/types.h>'))
530 conf.set('SIZEOF_RLIM_T', cc.sizeof('rlim_t', prefix : '#include <sys/resource.h>'))
531 conf.set('SIZEOF_TIME_T', cc.sizeof('time_t', prefix : '#include <sys/time.h>'))
532 conf.set('SIZEOF_TIMEX_MEMBER', cc.sizeof('typeof(((struct timex *)0)->freq)', prefix : '#include <sys/timex.h>'))
533
534 long_max = cc.compute_int(
535 'LONG_MAX',
536 prefix : '#include <limits.h>',
537 guess : 0x7FFFFFFFFFFFFFFF,
538 high : 0x7FFFFFFFFFFFFFFF)
539 assert(long_max > 100000)
540 conf.set_quoted('LONG_MAX_STR', '@0@'.format(long_max))
541
542 decl_headers = '''
543 #include <dirent.h>
544 #include <uchar.h>
545 #include <sys/mount.h>
546 #include <sys/stat.h>
547 '''
548
549 foreach decl : ['char16_t',
550 'char32_t',
551 'struct mount_attr',
552 'struct statx',
553 'struct dirent64',
554 ]
555
556 # We get -1 if the size cannot be determined
557 have = cc.sizeof(decl, prefix : decl_headers, args : '-D_GNU_SOURCE') > 0
558
559 if decl == 'struct mount_attr'
560 if have
561 want_linux_fs_h = false
562 else
563 have = cc.sizeof(decl,
564 prefix : decl_headers + '#include <linux/fs.h>',
565 args : '-D_GNU_SOURCE') > 0
566 want_linux_fs_h = have
567 endif
568 endif
569
570 if decl == 'struct statx'
571 if have
572 want_linux_stat_h = false
573 else
574 have = cc.sizeof(decl,
575 prefix : decl_headers + '#include <linux/stat.h>',
576 args : '-D_GNU_SOURCE') > 0
577 want_linux_stat_h = have
578 endif
579 endif
580
581 conf.set10('HAVE_' + decl.underscorify().to_upper(), have)
582 endforeach
583
584 conf.set10('WANT_LINUX_STAT_H', want_linux_stat_h)
585 conf.set10('WANT_LINUX_FS_H', want_linux_fs_h)
586
587 foreach ident : ['secure_getenv', '__secure_getenv']
588 conf.set10('HAVE_' + ident.to_upper(), cc.has_function(ident))
589 endforeach
590
591 foreach ident : [
592 ['memfd_create', '''#include <sys/mman.h>'''],
593 ['gettid', '''#include <sys/types.h>
594 #include <unistd.h>'''],
595 ['fchmodat2', '''#include <stdlib.h>
596 #include <fcntl.h>'''], # no known header declares fchmodat2
597 ['pivot_root', '''#include <stdlib.h>
598 #include <unistd.h>'''], # no known header declares pivot_root
599 ['ioprio_get', '''#include <sched.h>'''], # no known header declares ioprio_get
600 ['ioprio_set', '''#include <sched.h>'''], # no known header declares ioprio_set
601 ['name_to_handle_at', '''#include <sys/types.h>
602 #include <sys/stat.h>
603 #include <fcntl.h>'''],
604 ['setns', '''#include <sched.h>'''],
605 ['renameat2', '''#include <stdio.h>
606 #include <fcntl.h>'''],
607 ['kcmp', '''#include <linux/kcmp.h>'''],
608 ['keyctl', '''#include <sys/types.h>
609 #include <keyutils.h>'''],
610 ['copy_file_range', '''#include <sys/syscall.h>
611 #include <unistd.h>'''],
612 ['bpf', '''#include <sys/syscall.h>
613 #include <unistd.h>'''],
614 ['statx', '''#include <sys/types.h>
615 #include <sys/stat.h>
616 #include <unistd.h>'''],
617 ['explicit_bzero' , '''#include <string.h>'''],
618 ['reallocarray', '''#include <stdlib.h>'''],
619 ['set_mempolicy', '''#include <stdlib.h>
620 #include <unistd.h>'''],
621 ['get_mempolicy', '''#include <stdlib.h>
622 #include <unistd.h>'''],
623 ['pidfd_send_signal', '''#include <stdlib.h>
624 #include <unistd.h>
625 #include <signal.h>
626 #include <sys/wait.h>'''],
627 ['pidfd_open', '''#include <stdlib.h>
628 #include <unistd.h>
629 #include <signal.h>
630 #include <sys/wait.h>'''],
631 ['rt_sigqueueinfo', '''#include <stdlib.h>
632 #include <unistd.h>
633 #include <signal.h>
634 #include <sys/wait.h>'''],
635 ['rt_tgsigqueueinfo', '''#include <stdlib.h>
636 #include <unistd.h>
637 #include <signal.h>
638 #include <sys/wait.h>'''],
639 ['mallinfo', '''#include <malloc.h>'''],
640 ['mallinfo2', '''#include <malloc.h>'''],
641 ['execveat', '''#include <unistd.h>'''],
642 ['close_range', '''#include <unistd.h>'''],
643 ['epoll_pwait2', '''#include <sys/epoll.h>'''],
644 ['mount_setattr', '''#include <sys/mount.h>'''],
645 ['move_mount', '''#include <sys/mount.h>'''],
646 ['open_tree', '''#include <sys/mount.h>'''],
647 ['fsopen', '''#include <sys/mount.h>'''],
648 ['fsconfig', '''#include <sys/mount.h>'''],
649 ['fsmount', '''#include <sys/mount.h>'''],
650 ['getdents64', '''#include <dirent.h>'''],
651 ['pidfd_spawn', '''#include <spawn.h>'''],
652 ]
653
654 have = cc.has_function(ident[0], prefix : ident[1], args : '-D_GNU_SOURCE')
655 conf.set10('HAVE_' + ident[0].to_upper(), have)
656 endforeach
657
658 if cc.has_function('getrandom', prefix : '''#include <sys/random.h>''', args : '-D_GNU_SOURCE')
659 conf.set10('USE_SYS_RANDOM_H', true)
660 conf.set10('HAVE_GETRANDOM', true)
661 else
662 have = cc.has_function('getrandom', prefix : '''#include <linux/random.h>''')
663 conf.set10('USE_SYS_RANDOM_H', false)
664 conf.set10('HAVE_GETRANDOM', have)
665 endif
666
667 #####################################################################
668
669 sh = find_program('sh')
670 echo = find_program('echo')
671 sed = find_program('sed')
672 awk = find_program('awk')
673 stat = find_program('stat')
674 ln = find_program('ln')
675 git = find_program('git', required : false)
676 env = find_program('env')
677 rsync = find_program('rsync', required : false)
678 diff = find_program('diff')
679 find = find_program('find')
680
681 ln_s = ln.full_path() + ' -frsT -- "${DESTDIR:-}@0@" "${DESTDIR:-}@1@"'
682
683 # If -Dxxx-path option is found, use that. Otherwise, check in $PATH,
684 # /usr/sbin, /sbin, and fall back to the default from middle column.
685 progs = [['quotaon', '/usr/sbin/quotaon' ],
686 ['quotacheck', '/usr/sbin/quotacheck' ],
687 ['kmod', '/usr/bin/kmod' ],
688 ['kexec', '/usr/sbin/kexec' ],
689 ['sulogin', '/usr/sbin/sulogin' ],
690 ['mount', '/usr/bin/mount', 'MOUNT_PATH'],
691 ['umount', '/usr/bin/umount', 'UMOUNT_PATH'],
692 ['loadkeys', '/usr/bin/loadkeys', 'KBD_LOADKEYS'],
693 ['setfont', '/usr/bin/setfont', 'KBD_SETFONT'],
694 ['nologin', '/usr/sbin/nologin', ],
695 ]
696 foreach prog : progs
697 path = get_option(prog[0] + '-path')
698 if path != ''
699 message('Using @1@ for @0@'.format(prog[0], path))
700 else
701 exe = find_program(prog[0],
702 '/usr/sbin/' + prog[0],
703 '/sbin/' + prog[0],
704 required: false)
705 path = exe.found() ? exe.full_path() : prog[1]
706 endif
707 name = prog.length() > 2 ? prog[2] : prog[0].to_upper()
708 conf.set_quoted(name, path)
709 endforeach
710
711 if run_command(ln, '--relative', '--help', check : false).returncode() != 0
712 error('ln does not support --relative (added in coreutils 8.16)')
713 endif
714
715 #####################################################################
716
717 gperf = find_program('gperf')
718
719 gperf_test_format = '''
720 #include <string.h>
721 const char * in_word_set(const char *, @0@);
722 @1@
723 '''
724 gperf_snippet = run_command(sh, '-c', 'echo foo,bar | "$1" -L ANSI-C', '_', gperf,
725 check : true)
726 gperf_test = gperf_test_format.format('size_t', gperf_snippet.stdout())
727 if cc.compiles(gperf_test)
728 gperf_len_type = 'size_t'
729 else
730 gperf_test = gperf_test_format.format('unsigned', gperf_snippet.stdout())
731 if cc.compiles(gperf_test)
732 gperf_len_type = 'unsigned'
733 else
734 error('unable to determine gperf len type')
735 endif
736 endif
737 message('gperf len type is @0@'.format(gperf_len_type))
738 conf.set('GPERF_LEN_TYPE', gperf_len_type,
739 description : 'The type of gperf "len" parameter')
740
741 #####################################################################
742
743 if not cc.has_header('sys/capability.h')
744 error('POSIX caps headers not found')
745 endif
746 foreach header : ['crypt.h',
747 'linux/ioprio.h',
748 'linux/memfd.h',
749 'linux/time_types.h',
750 'linux/vm_sockets.h',
751 'sys/auxv.h',
752 'sys/sdt.h',
753 'threads.h',
754 'valgrind/memcheck.h',
755 'valgrind/valgrind.h',
756 ]
757
758 conf.set10('HAVE_' + header.underscorify().to_upper(),
759 cc.has_header(header))
760 endforeach
761
762 #####################################################################
763
764 fallback_hostname = get_option('fallback-hostname')
765 if fallback_hostname == '' or fallback_hostname[0] == '.' or fallback_hostname[0] == '-'
766 error('Invalid fallback-hostname configuration')
767 # A more extensive test is done in test-hostname-util. Let's catch
768 # the most obvious errors here so we don't fail with an assert later.
769 endif
770 conf.set_quoted('FALLBACK_HOSTNAME', fallback_hostname)
771
772 extra_net_naming_schemes = []
773 extra_net_naming_map = []
774 foreach scheme: get_option('extra-net-naming-schemes').split(',')
775 if scheme != ''
776 name = scheme.split('=')[0]
777 value = scheme.split('=')[1]
778 NAME = name.underscorify().to_upper()
779 VALUE = []
780 foreach field: value.split('+')
781 VALUE += 'NAMING_' + field.underscorify().to_upper()
782 endforeach
783 extra_net_naming_schemes += 'NAMING_@0@ = @1@,'.format(NAME, '|'.join(VALUE))
784 extra_net_naming_map += '{ "@0@", NAMING_@1@ },'.format(name, NAME)
785 endif
786 endforeach
787 conf.set('EXTRA_NET_NAMING_SCHEMES', ' '.join(extra_net_naming_schemes))
788 conf.set('EXTRA_NET_NAMING_MAP', ' '.join(extra_net_naming_map))
789
790 default_net_naming_scheme = get_option('default-net-naming-scheme')
791 conf.set_quoted('DEFAULT_NET_NAMING_SCHEME', default_net_naming_scheme,
792 description : 'Default naming scheme as a string')
793 if default_net_naming_scheme != 'latest'
794 conf.set('_DEFAULT_NET_NAMING_SCHEME',
795 'NAMING_' + default_net_naming_scheme.underscorify().to_upper(),
796 description : 'Default naming scheme as a constant')
797 endif
798
799 time_epoch = get_option('time-epoch')
800 if time_epoch <= 0
801 time_epoch = run_command(sh, '-c', 'echo "$SOURCE_DATE_EPOCH"', check : true).stdout().strip()
802 if time_epoch == '' and git.found() and fs.is_dir('.git')
803 # If we're in a git repository, use the creation time of the latest git tag.
804 latest_tag = run_command(git, 'describe', '--abbrev=0', '--tags',
805 check : false)
806 if latest_tag.returncode() == 0
807 time_epoch = run_command(
808 git, 'log', '--no-show-signature', '-1', '--format=%at',
809 latest_tag.stdout().strip(),
810 check : false).stdout()
811 endif
812 endif
813 if time_epoch == ''
814 NEWS = files('NEWS')
815 time_epoch = run_command(stat, '-c', '%Y', NEWS,
816 check : true).stdout()
817 endif
818 time_epoch = time_epoch.strip().to_int()
819 endif
820 conf.set('TIME_EPOCH', time_epoch)
821
822 conf.set('CLOCK_VALID_RANGE_USEC_MAX', get_option('clock-valid-range-usec-max'))
823
824 default_user_shell = get_option('default-user-shell')
825 conf.set_quoted('DEFAULT_USER_SHELL', default_user_shell)
826 conf.set_quoted('DEFAULT_USER_SHELL_NAME', fs.name(default_user_shell))
827
828 foreach tuple : [['system-alloc-uid-min', 'SYS_UID_MIN', 1], # Also see login.defs(5).
829 ['system-uid-max', 'SYS_UID_MAX', 999],
830 ['system-alloc-gid-min', 'SYS_GID_MIN', 1],
831 ['system-gid-max', 'SYS_GID_MAX', 999]]
832 v = get_option(tuple[0])
833 if v <= 0
834 v = run_command(
835 awk,
836 '/^\s*@0@\s+/ { uid=$2 } END { print uid }'.format(tuple[1]),
837 '/etc/login.defs',
838 check : false).stdout().strip()
839 if v == ''
840 v = tuple[2]
841 else
842 v = v.to_int()
843 endif
844 endif
845 conf.set(tuple[0].underscorify().to_upper(), v)
846 endforeach
847 if conf.get('SYSTEM_ALLOC_UID_MIN') >= conf.get('SYSTEM_UID_MAX')
848 error('Invalid uid allocation range')
849 endif
850 if conf.get('SYSTEM_ALLOC_GID_MIN') >= conf.get('SYSTEM_GID_MAX')
851 error('Invalid gid allocation range')
852 endif
853
854 dynamic_uid_min = get_option('dynamic-uid-min')
855 dynamic_uid_max = get_option('dynamic-uid-max')
856 conf.set('DYNAMIC_UID_MIN', dynamic_uid_min)
857 conf.set('DYNAMIC_UID_MAX', dynamic_uid_max)
858
859 container_uid_base_min = get_option('container-uid-base-min')
860 container_uid_base_max = get_option('container-uid-base-max')
861 conf.set('CONTAINER_UID_BASE_MIN', container_uid_base_min)
862 conf.set('CONTAINER_UID_BASE_MAX', container_uid_base_max)
863
864 nobody_user = get_option('nobody-user')
865 nobody_group = get_option('nobody-group')
866
867 if not meson.is_cross_build()
868 getent_result = run_command('getent', 'passwd', '65534', check : false)
869 if getent_result.returncode() == 0
870 name = getent_result.stdout().split(':')[0]
871 if name != nobody_user
872 warning('\n' +
873 'The local user with the UID 65534 does not match the configured user name "@0@" of the nobody user (its name is @1@).\n'.format(nobody_user, name) +
874 'Your build will result in an user table setup that is incompatible with the local system.')
875 endif
876 endif
877 id_result = run_command('id', '-u', nobody_user, check : false)
878 if id_result.returncode() == 0
879 id = id_result.stdout().strip().to_int()
880 if id != 65534
881 warning('\n' +
882 'The local user with the configured user name "@0@" of the nobody user does not have UID 65534 (it has @1@).\n'.format(nobody_user, id) +
883 'Your build will result in an user table setup that is incompatible with the local system.')
884 endif
885 endif
886
887 getent_result = run_command('getent', 'group', '65534', check : false)
888 if getent_result.returncode() == 0
889 name = getent_result.stdout().split(':')[0]
890 if name != nobody_group
891 warning('\n' +
892 'The local group with the GID 65534 does not match the configured group name "@0@" of the nobody group (its name is @1@).\n'.format(nobody_group, name) +
893 'Your build will result in an group table setup that is incompatible with the local system.')
894 endif
895 endif
896 id_result = run_command('id', '-g', nobody_group, check : false)
897 if id_result.returncode() == 0
898 id = id_result.stdout().strip().to_int()
899 if id != 65534
900 warning('\n' +
901 'The local group with the configured group name "@0@" of the nobody group does not have GID 65534 (it has @1@).\n'.format(nobody_group, id) +
902 'Your build will result in an group table setup that is incompatible with the local system.')
903 endif
904 endif
905 endif
906 if nobody_user != nobody_group and not (nobody_user == 'nobody' and nobody_group == 'nogroup')
907 warning('\n' +
908 'The configured user name "@0@" and group name "@1@" of the nobody user/group are not equivalent.\n'.format(nobody_user, nobody_group) +
909 'Please re-check that both "nobody-user" and "nobody-group" options are correctly set.')
910 endif
911
912 conf.set_quoted('NOBODY_USER_NAME', nobody_user)
913 conf.set_quoted('NOBODY_GROUP_NAME', nobody_group)
914
915 static_ugids = []
916 foreach option : ['adm-gid',
917 'audio-gid',
918 'cdrom-gid',
919 'dialout-gid',
920 'disk-gid',
921 'input-gid',
922 'kmem-gid',
923 'kvm-gid',
924 'lp-gid',
925 'render-gid',
926 'sgx-gid',
927 'tape-gid',
928 'tty-gid',
929 'users-gid',
930 'utmp-gid',
931 'video-gid',
932 'wheel-gid',
933 'systemd-journal-gid',
934 'systemd-network-uid',
935 'systemd-resolve-uid',
936 'systemd-timesync-uid']
937 name = option.underscorify().to_upper()
938 val = get_option(option)
939
940 # Ensure provided GID argument is numeric, otherwise fall back to default assignment
941 conf.set(name, val > 0 ? val : '-')
942 if val > 0
943 static_ugids += '@0@:@1@'.format(option, val)
944 endif
945 endforeach
946
947 conf.set10('ENABLE_ADM_GROUP', get_option('adm-group'))
948 conf.set10('ENABLE_WHEEL_GROUP', get_option('wheel-group'))
949
950 dev_kvm_mode = get_option('dev-kvm-mode')
951 conf.set_quoted('DEV_KVM_MODE', dev_kvm_mode) # FIXME: convert to 0o… notation
952 conf.set10('DEV_KVM_UACCESS', dev_kvm_mode != '0666')
953 group_render_mode = get_option('group-render-mode')
954 conf.set_quoted('GROUP_RENDER_MODE', group_render_mode)
955 conf.set10('GROUP_RENDER_UACCESS', group_render_mode != '0666')
956
957 kill_user_processes = get_option('default-kill-user-processes')
958 conf.set10('KILL_USER_PROCESSES', kill_user_processes)
959
960 dns_servers = get_option('dns-servers')
961 conf.set_quoted('DNS_SERVERS', dns_servers)
962
963 ntp_servers = get_option('ntp-servers')
964 conf.set_quoted('NTP_SERVERS', ntp_servers)
965
966 default_locale = get_option('default-locale')
967 conf.set_quoted('SYSTEMD_DEFAULT_LOCALE', default_locale)
968
969 nspawn_locale = get_option('nspawn-locale')
970 conf.set_quoted('SYSTEMD_NSPAWN_LOCALE', nspawn_locale)
971
972 default_keymap = get_option('default-keymap')
973 if default_keymap == ''
974 # We canonicalize empty keymap to '@kernel', as it makes the default value
975 # in the factory provided /etc/vconsole.conf more obvious.
976 default_keymap = '@kernel'
977 endif
978 conf.set_quoted('SYSTEMD_DEFAULT_KEYMAP', default_keymap)
979
980 localegen_path = get_option('localegen-path')
981 if localegen_path != ''
982 conf.set_quoted('LOCALEGEN_PATH', localegen_path)
983 endif
984 conf.set10('HAVE_LOCALEGEN', localegen_path != '')
985
986 conf.set_quoted('GETTEXT_PACKAGE', meson.project_name())
987
988 service_watchdog = get_option('service-watchdog')
989 watchdog_value = service_watchdog == '' ? '' : 'WatchdogSec=' + service_watchdog
990 conf.set_quoted('SERVICE_WATCHDOG', watchdog_value)
991
992 conf.set_quoted('SUSHELL', get_option('debug-shell'))
993 conf.set_quoted('DEBUGTTY', get_option('debug-tty'))
994
995 enable_debug_hashmap = false
996 enable_debug_mmap_cache = false
997 enable_debug_siphash = false
998 foreach name : get_option('debug-extra')
999 if name == 'hashmap'
1000 enable_debug_hashmap = true
1001 elif name == 'mmap-cache'
1002 enable_debug_mmap_cache = true
1003 elif name == 'siphash'
1004 enable_debug_siphash = true
1005 else
1006 message('unknown debug option "@0@", ignoring'.format(name))
1007 endif
1008 endforeach
1009 conf.set10('ENABLE_DEBUG_HASHMAP', enable_debug_hashmap)
1010 conf.set10('ENABLE_DEBUG_MMAP_CACHE', enable_debug_mmap_cache)
1011 conf.set10('ENABLE_DEBUG_SIPHASH', enable_debug_siphash)
1012 conf.set10('LOG_TRACE', get_option('log-trace'))
1013
1014 default_user_path = get_option('user-path')
1015 if default_user_path != ''
1016 conf.set_quoted('DEFAULT_USER_PATH', default_user_path)
1017 endif
1018
1019 #####################################################################
1020
1021 threads = dependency('threads')
1022 librt = cc.find_library('rt')
1023 libm = cc.find_library('m')
1024 libdl = cc.find_library('dl')
1025 libcrypt = dependency('libcrypt', 'libxcrypt', required : false)
1026 if not libcrypt.found()
1027 # fallback to use find_library() if libcrypt is provided by glibc, e.g. for LibreELEC.
1028 libcrypt = cc.find_library('crypt')
1029 endif
1030 libcap = dependency('libcap')
1031
1032 # On some architectures, libatomic is required. But on some installations,
1033 # it is found, but actual linking fails. So let's try to use it opportunistically.
1034 # If it is installed, but not needed, it will be dropped because of --as-needed.
1035 if cc.links('''int main(int argc, char **argv) { return 0; }''',
1036 args : '-latomic',
1037 name : 'libatomic')
1038 libatomic = declare_dependency(link_args : '-latomic')
1039 else
1040 libatomic = []
1041 endif
1042
1043 crypt_header = conf.get('HAVE_CRYPT_H') == 1 ? '''#include <crypt.h>''' : '''#include <unistd.h>'''
1044 foreach ident : [
1045 ['crypt_ra', crypt_header],
1046 ['crypt_preferred_method', crypt_header],
1047 ['crypt_gensalt_ra', crypt_header]]
1048
1049 have = cc.has_function(ident[0], prefix : ident[1], args : '-D_GNU_SOURCE',
1050 dependencies : libcrypt)
1051 conf.set10('HAVE_' + ident[0].to_upper(), have)
1052 endforeach
1053
1054 bpf_framework = get_option('bpf-framework')
1055 bpf_compiler = get_option('bpf-compiler')
1056 libbpf = dependency('libbpf',
1057 required : bpf_framework,
1058 version : bpf_compiler == 'gcc' ? '>= 1.0.0' : '>= 0.1.0')
1059 conf.set10('HAVE_LIBBPF', libbpf.found())
1060
1061 if not libbpf.found()
1062 conf.set10('BPF_FRAMEWORK', false)
1063 else
1064 clang_found = false
1065 clang_supports_bpf = false
1066 bpf_gcc_found = false
1067 bpftool_strip = false
1068 deps_found = false
1069
1070 if bpf_compiler == 'clang'
1071 # Support 'versioned' clang/llvm-strip binaries, as seen on Debian/Ubuntu
1072 # (like clang-10/llvm-strip-10)
1073 if meson.is_cross_build() or cc.get_id() != 'clang' or cc.cmd_array()[0].contains('afl-clang') or cc.cmd_array()[0].contains('hfuzz-clang')
1074 r = find_program('clang',
1075 required : bpf_framework,
1076 version : '>= 10.0.0')
1077 clang_found = r.found()
1078 if clang_found
1079 clang = r.full_path()
1080 endif
1081 else
1082 clang_found = true
1083 clang = cc.cmd_array()
1084 endif
1085
1086 if clang_found
1087 # Check if 'clang -target bpf' is supported.
1088 clang_supports_bpf = run_command(clang, '-target', 'bpf', '--print-supported-cpus', check : false).returncode() == 0
1089 endif
1090 elif bpf_compiler == 'gcc'
1091 bpf_gcc = find_program('bpf-gcc',
1092 'bpf-none-gcc',
1093 required : true,
1094 version : '>= 13.1.0')
1095 bpf_gcc_found = bpf_gcc.found()
1096 endif
1097
1098 if clang_supports_bpf or bpf_gcc_found
1099 # Debian installs this in /usr/sbin/ which is not in $PATH.
1100 # We check for 'bpftool' first, honouring $PATH, and in /usr/sbin/ for Debian.
1101 # We use 'bpftool gen object' subcommand for bpftool strip, it was added by d80b2fcbe0a023619e0fc73112f2a02c2662f6ab (v5.13).
1102 bpftool = find_program('bpftool',
1103 '/usr/sbin/bpftool',
1104 required : bpf_framework.enabled() and bpf_compiler == 'gcc',
1105 version : bpf_compiler == 'gcc' ? '>= 7.0.0' : '>= 5.13.0')
1106
1107 if bpftool.found()
1108 bpftool_strip = true
1109 deps_found = true
1110 elif bpf_compiler == 'clang'
1111 # We require the 'bpftool gen skeleton' subcommand, it was added by 985ead416df39d6fe8e89580cc1db6aa273e0175 (v5.6).
1112 bpftool = find_program('bpftool',
1113 '/usr/sbin/bpftool',
1114 required : bpf_framework,
1115 version : '>= 5.6.0')
1116 endif
1117
1118 # We use `llvm-strip` as a fallback if `bpftool gen object` strip support is not available.
1119 if not bpftool_strip and bpftool.found() and clang_supports_bpf
1120 if not meson.is_cross_build()
1121 llvm_strip_bin = run_command(clang, '--print-prog-name', 'llvm-strip',
1122 check : true).stdout().strip()
1123 else
1124 llvm_strip_bin = 'llvm-strip'
1125 endif
1126 llvm_strip = find_program(llvm_strip_bin,
1127 required : bpf_framework,
1128 version : '>= 10.0.0')
1129 deps_found = llvm_strip.found()
1130 endif
1131 endif
1132
1133 # Can build BPF program from source code in restricted C
1134 conf.set10('BPF_FRAMEWORK', deps_found)
1135 endif
1136
1137 libmount = dependency('mount',
1138 version : fuzzer_build ? '>= 0' : '>= 2.30')
1139
1140 libfdisk = dependency('fdisk',
1141 version : '>= 2.32',
1142 disabler : true,
1143 required : get_option('fdisk'))
1144 conf.set10('HAVE_LIBFDISK', libfdisk.found())
1145
1146 # This prefers pwquality if both are enabled or auto.
1147 feature = get_option('pwquality').disable_auto_if(get_option('passwdqc').enabled())
1148 libpwquality = dependency('pwquality',
1149 version : '>= 1.4.1',
1150 required : feature)
1151 have = libpwquality.found()
1152 if not have
1153 # libpwquality is used for both features for simplicity
1154 libpwquality = dependency('passwdqc',
1155 required : get_option('passwdqc'))
1156 endif
1157 conf.set10('HAVE_PWQUALITY', have)
1158 conf.set10('HAVE_PASSWDQC', not have and libpwquality.found())
1159
1160 libseccomp = dependency('libseccomp',
1161 version : '>= 2.3.1',
1162 required : get_option('seccomp'))
1163 conf.set10('HAVE_SECCOMP', libseccomp.found())
1164
1165 libselinux = dependency('libselinux',
1166 version : '>= 2.1.9',
1167 required : get_option('selinux'))
1168 conf.set10('HAVE_SELINUX', libselinux.found())
1169
1170 libapparmor = dependency('libapparmor',
1171 version : '>= 2.13',
1172 required : get_option('apparmor'))
1173 conf.set10('HAVE_APPARMOR', libapparmor.found())
1174
1175 have = get_option('smack') and get_option('smack-run-label') != ''
1176 conf.set10('HAVE_SMACK_RUN_LABEL', have)
1177 if have
1178 conf.set_quoted('SMACK_RUN_LABEL', get_option('smack-run-label'))
1179 endif
1180
1181 have = get_option('smack') and get_option('smack-default-process-label') != ''
1182 if have
1183 conf.set_quoted('SMACK_DEFAULT_PROCESS_LABEL', get_option('smack-default-process-label'))
1184 endif
1185
1186 feature = get_option('polkit')
1187 libpolkit = dependency('polkit-gobject-1',
1188 required : feature.disabled() ? feature : false)
1189 install_polkit = feature.allowed()
1190 install_polkit_pkla = libpolkit.found() and libpolkit.version().version_compare('< 0.106')
1191 if install_polkit_pkla
1192 message('Old polkit detected, will install pkla files')
1193 endif
1194 conf.set10('ENABLE_POLKIT', install_polkit)
1195
1196 libacl = dependency('libacl',
1197 required : get_option('acl'))
1198 conf.set10('HAVE_ACL', libacl.found())
1199
1200 libaudit = dependency('audit',
1201 required : get_option('audit'))
1202 conf.set10('HAVE_AUDIT', libaudit.found())
1203
1204 libblkid = dependency('blkid',
1205 required : get_option('blkid'))
1206 conf.set10('HAVE_BLKID', libblkid.found())
1207 conf.set10('HAVE_BLKID_PROBE_SET_HINT',
1208 libblkid.found() and cc.has_function('blkid_probe_set_hint', dependencies : libblkid))
1209
1210 libkmod = dependency('libkmod',
1211 version : '>= 15',
1212 required : get_option('kmod'))
1213 conf.set10('HAVE_KMOD', libkmod.found())
1214 libkmod_cflags = libkmod.partial_dependency(includes: true, compile_args: true)
1215
1216 libxenctrl = dependency('xencontrol',
1217 version : '>= 4.9',
1218 required : get_option('xenctrl'))
1219 conf.set10('HAVE_XENCTRL', libxenctrl.found())
1220 libxenctrl_cflags = libxenctrl.partial_dependency(includes: true, compile_args: true)
1221
1222 feature = get_option('pam')
1223 libpam = dependency('pam',
1224 required : feature.disabled() ? feature : false)
1225 if not libpam.found()
1226 # Debian older than bookworm and Ubuntu older than 22.10 do not provide the .pc file.
1227 libpam = cc.find_library('pam', required : feature)
1228 endif
1229 libpam_misc = dependency('pam_misc',
1230 required : feature.disabled() ? feature : false)
1231 if not libpam_misc.found()
1232 libpam_misc = cc.find_library('pam_misc', required : feature)
1233 endif
1234 conf.set10('HAVE_PAM', libpam.found() and libpam_misc.found())
1235
1236 libmicrohttpd = dependency('libmicrohttpd',
1237 version : '>= 0.9.33',
1238 required : get_option('microhttpd'))
1239 conf.set10('HAVE_MICROHTTPD', libmicrohttpd.found())
1240
1241 libcryptsetup = get_option('libcryptsetup')
1242 libcryptsetup_plugins = get_option('libcryptsetup-plugins')
1243 if libcryptsetup_plugins.enabled()
1244 if libcryptsetup.disabled()
1245 error('libcryptsetup-plugins cannot be requested without libcryptsetup')
1246 endif
1247 libcryptsetup = libcryptsetup_plugins
1248 endif
1249
1250 libcryptsetup = dependency('libcryptsetup',
1251 version : libcryptsetup_plugins.enabled() ? '>= 2.4.0' : '>= 2.0.1',
1252 required : libcryptsetup)
1253
1254 have = libcryptsetup.found()
1255 foreach ident : ['crypt_set_metadata_size',
1256 'crypt_activate_by_signed_key',
1257 'crypt_token_max',
1258 'crypt_reencrypt_init_by_passphrase',
1259 'crypt_reencrypt',
1260 'crypt_set_data_offset',
1261 'crypt_set_keyring_to_link',
1262 'crypt_resume_by_volume_key']
1263 have_ident = have and cc.has_function(
1264 ident,
1265 prefix : '#include <libcryptsetup.h>',
1266 dependencies : libcryptsetup)
1267 conf.set10('HAVE_' + ident.to_upper(), have_ident)
1268 endforeach
1269 conf.set10('HAVE_LIBCRYPTSETUP', have)
1270
1271 # TODO: Use has_function(required : libcryptsetup_plugins) with meson >= 1.3.0
1272 if libcryptsetup_plugins.allowed()
1273 have = (cc.has_function(
1274 'crypt_activate_by_token_pin',
1275 prefix : '#include <libcryptsetup.h>',
1276 dependencies : libcryptsetup) and
1277 cc.has_function(
1278 'crypt_token_external_path',
1279 prefix : '#include <libcryptsetup.h>',
1280 dependencies : libcryptsetup))
1281 else
1282 have = false
1283 endif
1284 conf.set10('HAVE_LIBCRYPTSETUP_PLUGINS', have)
1285
1286 libcurl = dependency('libcurl',
1287 version : '>= 7.32.0',
1288 required : get_option('libcurl'))
1289 conf.set10('HAVE_LIBCURL', libcurl.found())
1290 conf.set10('CURL_NO_OLDIES', conf.get('BUILD_MODE_DEVELOPER') == 1)
1291
1292 feature = get_option('libidn2').disable_auto_if(get_option('libidn').enabled())
1293 libidn = dependency('libidn2',
1294 required : feature)
1295 have = libidn.found()
1296 if not have
1297 # libidn is used for both libidn and libidn2 objects
1298 libidn = dependency('libidn',
1299 required : get_option('libidn'))
1300 endif
1301 conf.set10('HAVE_LIBIDN', not have and libidn.found())
1302 conf.set10('HAVE_LIBIDN2', have)
1303
1304 libiptc = dependency('libiptc',
1305 required : get_option('libiptc'))
1306 conf.set10('HAVE_LIBIPTC', libiptc.found())
1307 libiptc_cflags = libiptc.partial_dependency(includes: true, compile_args: true)
1308
1309 libqrencode = dependency('libqrencode',
1310 version : '>= 3',
1311 required : get_option('qrencode'))
1312 conf.set10('HAVE_QRENCODE', libqrencode.found())
1313
1314 feature = get_option('gcrypt')
1315 libgcrypt = dependency('libgcrypt',
1316 required : feature)
1317 libgpg_error = dependency('gpg-error',
1318 required : feature.disabled() ? feature : false)
1319 if not libgpg_error.found()
1320 # CentOS 8 does not provide the .pc file.
1321 libgpg_error = cc.find_library('gpg-error', required : feature)
1322 endif
1323
1324 have = libgcrypt.found() and libgpg_error.found()
1325 if not have
1326 # link to neither of the libs if one is not found
1327 libgcrypt = []
1328 libgpg_error = []
1329 libgcrypt_cflags = []
1330 else
1331 libgcrypt_cflags = libgcrypt.partial_dependency(includes: true, compile_args: true)
1332 endif
1333 conf.set10('HAVE_GCRYPT', have)
1334
1335 libgnutls = dependency('gnutls',
1336 version : '>= 3.1.4',
1337 required : get_option('gnutls'))
1338 conf.set10('HAVE_GNUTLS', libgnutls.found())
1339
1340 libopenssl = dependency('openssl',
1341 version : '>= 1.1.0',
1342 required : get_option('openssl'))
1343 conf.set10('HAVE_OPENSSL', libopenssl.found())
1344
1345 libp11kit = dependency('p11-kit-1',
1346 version : '>= 0.23.3',
1347 required : get_option('p11kit'))
1348 conf.set10('HAVE_P11KIT', libp11kit.found())
1349 libp11kit_cflags = libp11kit.partial_dependency(includes: true, compile_args: true)
1350
1351 feature = get_option('libfido2').require(
1352 conf.get('HAVE_OPENSSL') == 1,
1353 error_message : 'openssl required')
1354 libfido2 = dependency('libfido2',
1355 required : feature)
1356 conf.set10('HAVE_LIBFIDO2', libfido2.found())
1357
1358 tpm2 = dependency('tss2-esys tss2-rc tss2-mu tss2-tcti-device',
1359 required : get_option('tpm2'))
1360 conf.set10('HAVE_TPM2', tpm2.found())
1361 conf.set10('HAVE_TSS2_ESYS3', tpm2.found() and tpm2.version().version_compare('>= 3.0.0'))
1362
1363 libdw = dependency('libdw',
1364 required : get_option('elfutils'))
1365 conf.set10('HAVE_ELFUTILS', libdw.found())
1366 # New in elfutils 0.177
1367 conf.set10('HAVE_DWELF_ELF_E_MACHINE_STRING',
1368 libdw.found() and cc.has_function('dwelf_elf_e_machine_string', dependencies : libdw))
1369
1370 libz = dependency('zlib',
1371 required : get_option('zlib'))
1372 conf.set10('HAVE_ZLIB', libz.found())
1373
1374 feature = get_option('bzip2')
1375 libbzip2 = dependency('bzip2',
1376 required : feature.disabled() ? feature : false)
1377 if not libbzip2.found()
1378 # Debian and Ubuntu do not provide the .pc file.
1379 libbzip2 = cc.find_library('bz2', required : feature)
1380 endif
1381 conf.set10('HAVE_BZIP2', libbzip2.found())
1382
1383 libxz = dependency('liblzma',
1384 required : get_option('xz'))
1385 conf.set10('HAVE_XZ', libxz.found())
1386 libxz_cflags = libxz.partial_dependency(includes: true, compile_args: true)
1387
1388 liblz4 = dependency('liblz4',
1389 version : '>= 1.3.0',
1390 required : get_option('lz4'))
1391 conf.set10('HAVE_LZ4', liblz4.found())
1392 liblz4_cflags = liblz4.partial_dependency(includes: true, compile_args: true)
1393
1394 libzstd = dependency('libzstd',
1395 version : '>= 1.4.0',
1396 required : get_option('zstd'))
1397 conf.set10('HAVE_ZSTD', libzstd.found())
1398 libzstd_cflags = libzstd.partial_dependency(includes: true, compile_args: true)
1399
1400 conf.set10('HAVE_COMPRESSION', libxz.found() or liblz4.found() or libzstd.found())
1401
1402 compression = get_option('default-compression')
1403 if compression == 'auto'
1404 if libzstd.found()
1405 compression = 'zstd'
1406 elif liblz4.found()
1407 compression = 'lz4'
1408 elif libxz.found()
1409 compression = 'xz'
1410 else
1411 compression = 'none'
1412 endif
1413 elif compression == 'zstd' and not libzstd.found()
1414 error('default-compression=zstd requires zstd')
1415 elif compression == 'lz4' and not liblz4.found()
1416 error('default-compression=lz4 requires lz4')
1417 elif compression == 'xz' and not libxz.found()
1418 error('default-compression=xz requires xz')
1419 endif
1420 conf.set('DEFAULT_COMPRESSION', 'COMPRESSION_@0@'.format(compression.to_upper()))
1421
1422 libarchive = dependency('libarchive',
1423 version : '>= 3.0',
1424 required : get_option('libarchive'))
1425 conf.set10('HAVE_LIBARCHIVE', libarchive.found())
1426
1427 libxkbcommon = dependency('xkbcommon',
1428 version : '>= 0.3.0',
1429 required : get_option('xkbcommon'))
1430 conf.set10('HAVE_XKBCOMMON', libxkbcommon.found())
1431
1432 libpcre2 = dependency('libpcre2-8',
1433 required : get_option('pcre2'))
1434 conf.set10('HAVE_PCRE2', libpcre2.found())
1435
1436 libglib = dependency('glib-2.0',
1437 version : '>= 2.22.0',
1438 required : get_option('glib'))
1439 libgobject = dependency('gobject-2.0',
1440 version : '>= 2.22.0',
1441 required : get_option('glib'))
1442 libgio = dependency('gio-2.0',
1443 required : get_option('glib'))
1444 conf.set10('HAVE_GLIB', libglib.found() and libgobject.found() and libgio.found())
1445
1446 libdbus = dependency('dbus-1',
1447 version : '>= 1.3.2',
1448 required : get_option('dbus'))
1449 conf.set10('HAVE_DBUS', libdbus.found())
1450
1451 dbusdatadir = libdbus.get_variable(pkgconfig: 'datadir', default_value: datadir) / 'dbus-1'
1452
1453 dbuspolicydir = get_option('dbuspolicydir')
1454 if dbuspolicydir == ''
1455 dbuspolicydir = dbusdatadir / 'system.d'
1456 endif
1457
1458 dbussessionservicedir = get_option('dbussessionservicedir')
1459 if dbussessionservicedir == ''
1460 dbussessionservicedir = libdbus.get_variable(pkgconfig: 'session_bus_services_dir', default_value: dbusdatadir / 'services')
1461 endif
1462
1463 dbussystemservicedir = get_option('dbussystemservicedir')
1464 if dbussystemservicedir == ''
1465 dbussystemservicedir = libdbus.get_variable(pkgconfig: 'system_bus_services_dir', default_value: dbusdatadir / 'system-services')
1466 endif
1467
1468 dbus_interfaces_dir = get_option('dbus-interfaces-dir')
1469 if dbus_interfaces_dir == '' or dbus_interfaces_dir == 'yes'
1470 if meson.is_cross_build() and dbus_interfaces_dir != 'yes'
1471 dbus_interfaces_dir = 'no'
1472 warning('Exporting D-Bus interface XML files is disabled during cross build. Pass path or "yes" to force enable.')
1473 else
1474 dbus_interfaces_dir = libdbus.get_variable(pkgconfig: 'interfaces_dir', default_value: dbusdatadir / 'interfaces')
1475 endif
1476 endif
1477
1478 dmi_arches = ['x86', 'x86_64', 'aarch64', 'arm', 'ia64', 'loongarch64', 'mips']
1479 conf.set10('HAVE_DMI', host_machine.cpu_family() in dmi_arches)
1480
1481 # We support one or the other. If gcrypt is available, we assume it's there to
1482 # be used, and use it in preference.
1483 opt = get_option('cryptolib')
1484 if opt == 'openssl' and conf.get('HAVE_OPENSSL') == 0
1485 error('openssl requested as the default cryptolib, but not available')
1486 endif
1487 conf.set10('PREFER_OPENSSL',
1488 opt == 'openssl' or (opt == 'auto' and conf.get('HAVE_OPENSSL') == 1 and conf.get('HAVE_GCRYPT') == 0))
1489 conf.set10('HAVE_OPENSSL_OR_GCRYPT',
1490 conf.get('HAVE_OPENSSL') == 1 or conf.get('HAVE_GCRYPT') == 1)
1491 lib_openssl_or_gcrypt = conf.get('PREFER_OPENSSL') == 1 ? [libopenssl] : [libgcrypt, libgpg_error]
1492
1493 dns_over_tls = get_option('dns-over-tls')
1494 if dns_over_tls != 'false'
1495 if dns_over_tls == 'gnutls' and conf.get('PREFER_OPENSSL') == 1
1496 error('Sorry, -Ddns-over-tls=gnutls is not supported when openssl is used as the cryptolib')
1497 endif
1498
1499 if dns_over_tls == 'gnutls'
1500 have_openssl = false
1501 else
1502 have_openssl = conf.get('HAVE_OPENSSL') == 1
1503 if dns_over_tls == 'openssl' and not have_openssl
1504 error('DNS-over-TLS support was requested with openssl, but dependencies are not available')
1505 endif
1506 endif
1507 if dns_over_tls == 'openssl' or have_openssl
1508 have_gnutls = false
1509 else
1510 have_gnutls = conf.get('HAVE_GNUTLS') == 1 and libgnutls.version().version_compare('>= 3.6.0')
1511 if dns_over_tls != 'auto' and not have_gnutls
1512 str = dns_over_tls == 'gnutls' ? ' with gnutls' : ''
1513 error('DNS-over-TLS support was requested@0@, but dependencies are not available'.format(str))
1514 endif
1515 endif
1516 have = have_gnutls or have_openssl
1517 else
1518 have = false
1519 have_gnutls = false
1520 have_openssl = false
1521 endif
1522 conf.set10('ENABLE_DNS_OVER_TLS', have)
1523 conf.set10('DNS_OVER_TLS_USE_GNUTLS', have_gnutls)
1524 conf.set10('DNS_OVER_TLS_USE_OPENSSL', have_openssl)
1525
1526 default_dns_over_tls = get_option('default-dns-over-tls')
1527 if default_dns_over_tls != 'no' and conf.get('ENABLE_DNS_OVER_TLS') == 0
1528 message('default-dns-over-tls cannot be enabled or set to opportunistic when DNS-over-TLS support is disabled. Setting default-dns-over-tls to no.')
1529 default_dns_over_tls = 'no'
1530 endif
1531 conf.set('DEFAULT_DNS_OVER_TLS_MODE',
1532 'DNS_OVER_TLS_' + default_dns_over_tls.underscorify().to_upper())
1533 conf.set_quoted('DEFAULT_DNS_OVER_TLS_MODE_STR', default_dns_over_tls)
1534
1535 default_mdns = get_option('default-mdns')
1536 conf.set('DEFAULT_MDNS_MODE',
1537 'RESOLVE_SUPPORT_' + default_mdns.to_upper())
1538 conf.set_quoted('DEFAULT_MDNS_MODE_STR', default_mdns)
1539
1540 default_llmnr = get_option('default-llmnr')
1541 conf.set('DEFAULT_LLMNR_MODE',
1542 'RESOLVE_SUPPORT_' + default_llmnr.to_upper())
1543 conf.set_quoted('DEFAULT_LLMNR_MODE_STR', default_llmnr)
1544
1545 have = get_option('repart').require(
1546 conf.get('HAVE_LIBFDISK') == 1,
1547 error_message : 'fdisk required').allowed()
1548 conf.set10('ENABLE_REPART', have)
1549
1550 default_dnssec = get_option('default-dnssec')
1551 if default_dnssec != 'no' and conf.get('HAVE_OPENSSL_OR_GCRYPT') == 0
1552 message('default-dnssec cannot be set to yes or allow-downgrade openssl and gcrypt are disabled. Setting default-dnssec to no.')
1553 default_dnssec = 'no'
1554 endif
1555 conf.set('DEFAULT_DNSSEC_MODE',
1556 'DNSSEC_' + default_dnssec.underscorify().to_upper())
1557 conf.set_quoted('DEFAULT_DNSSEC_MODE_STR', default_dnssec)
1558
1559 have = get_option('sysupdate').require(
1560 conf.get('HAVE_OPENSSL') == 1 and
1561 conf.get('HAVE_LIBFDISK') == 1,
1562 error_message : 'fdisk and openssl required').allowed()
1563 conf.set10('ENABLE_SYSUPDATE', have)
1564
1565 conf.set10('ENABLE_STORAGETM', get_option('storagetm'))
1566
1567 have = get_option('importd').require(
1568 conf.get('HAVE_LIBCURL') == 1 and
1569 conf.get('HAVE_OPENSSL_OR_GCRYPT') == 1 and
1570 conf.get('HAVE_ZLIB') == 1 and
1571 conf.get('HAVE_XZ') == 1,
1572 error_message : 'curl, openssl/grypt, zlib and xz required').allowed()
1573 conf.set10('ENABLE_IMPORTD', have)
1574
1575 have = get_option('homed').require(
1576 conf.get('HAVE_OPENSSL') == 1 and
1577 conf.get('HAVE_LIBFDISK') == 1 and
1578 conf.get('HAVE_LIBCRYPTSETUP') == 1 and
1579 conf.get('HAVE_CRYPT_RESUME_BY_VOLUME_KEY') == 1,
1580 error_message : 'openssl, fdisk and libcryptsetup required').allowed()
1581 conf.set10('ENABLE_HOMED', have)
1582
1583 have = have and conf.get('HAVE_PAM') == 1
1584 conf.set10('ENABLE_PAM_HOME', have)
1585
1586 feature = get_option('remote')
1587 have_deps = [conf.get('HAVE_MICROHTTPD') == 1,
1588 conf.get('HAVE_LIBCURL') == 1]
1589 # sd-j-remote requires µhttpd, and sd-j-upload requires libcurl, so
1590 # it's possible to build one without the other. Complain only if
1591 # support was explicitly requested. The auxiliary files like sysusers
1592 # config should be installed when any of the programs are built.
1593 if feature.enabled() and not (have_deps[0] and have_deps[1])
1594 error('remote support was requested, but dependencies are not available')
1595 endif
1596 have = feature.allowed() and (have_deps[0] or have_deps[1])
1597 conf.set10('ENABLE_REMOTE', have)
1598
1599 feature = get_option('vmspawn').disable_auto_if(conf.get('BUILD_MODE_DEVELOPER') == 0)
1600 conf.set10('ENABLE_VMSPAWN', feature.allowed())
1601
1602 conf.set10('DEFAULT_MOUNTFSD_TRUSTED_DIRECTORIES', get_option('default-mountfsd-trusted-directories'))
1603
1604 foreach term : ['analyze',
1605 'backlight',
1606 'binfmt',
1607 'compat-mutable-uid-boundaries',
1608 'coredump',
1609 'efi',
1610 'environment-d',
1611 'firstboot',
1612 'gshadow',
1613 'hibernate',
1614 'hostnamed',
1615 'hwdb',
1616 'idn',
1617 'ima',
1618 'initrd',
1619 'kernel-install',
1620 'ldconfig',
1621 'localed',
1622 'logind',
1623 'machined',
1624 'mountfsd',
1625 'networkd',
1626 'nscd',
1627 'nsresourced',
1628 'nss-myhostname',
1629 'nss-systemd',
1630 'oomd',
1631 'portabled',
1632 'pstore',
1633 'quotacheck',
1634 'randomseed',
1635 'resolve',
1636 'rfkill',
1637 'smack',
1638 'sysext',
1639 'sysusers',
1640 'timedated',
1641 'timesyncd',
1642 'tmpfiles',
1643 'tpm',
1644 'userdb',
1645 'utmp',
1646 'vconsole',
1647 'xdg-autostart']
1648 have = get_option(term)
1649 name = 'ENABLE_' + term.underscorify().to_upper()
1650 conf.set10(name, have)
1651 endforeach
1652
1653 enable_sysusers = conf.get('ENABLE_SYSUSERS') == 1
1654
1655 foreach tuple : [['nss-mymachines', 'machined'],
1656 ['nss-resolve', 'resolve']]
1657 want = get_option(tuple[0])
1658 if want.allowed()
1659 have = get_option(tuple[1])
1660 if want.enabled() and not have
1661 error('@0@ is requested but @1@ is disabled'.format(tuple[0], tuple[1]))
1662 endif
1663 else
1664 have = false
1665 endif
1666 name = 'ENABLE_' + tuple[0].underscorify().to_upper()
1667 conf.set10(name, have)
1668 endforeach
1669
1670 enable_nss = false
1671 foreach term : ['ENABLE_NSS_MYHOSTNAME',
1672 'ENABLE_NSS_MYMACHINES',
1673 'ENABLE_NSS_RESOLVE',
1674 'ENABLE_NSS_SYSTEMD']
1675 if conf.get(term) == 1
1676 enable_nss = true
1677 endif
1678 endforeach
1679 conf.set10('ENABLE_NSS', enable_nss)
1680
1681 conf.set10('ENABLE_TIMEDATECTL', get_option('timedated') or get_option('timesyncd'))
1682
1683 conf.set10('ENABLE_SSH_PROXY_CONFIG', sshconfdir != 'no')
1684 conf.set10('ENABLE_SSH_USERDB_CONFIG', conf.get('ENABLE_USERDB') == 1 and sshdconfdir != 'no')
1685
1686 conf.set10('SYSTEMD_SLOW_TESTS_DEFAULT', slow_tests)
1687
1688 #####################################################################
1689
1690 pymod = import('python')
1691 python = pymod.find_installation('python3', required : true, modules : ['jinja2'])
1692 python_39 = python.language_version().version_compare('>=3.9')
1693
1694 #####################################################################
1695
1696 if conf.get('BPF_FRAMEWORK') == 1
1697 bpf_clang_flags = [
1698 '-std=gnu11',
1699 '-Wno-compare-distinct-pointer-types',
1700 '-fno-stack-protector',
1701 '-O2',
1702 '-target',
1703 'bpf',
1704 '-g',
1705 '-c',
1706 ]
1707
1708 bpf_gcc_flags = [
1709 '-std=gnu11',
1710 '-fno-stack-protector',
1711 '-fno-ssa-phiopt',
1712 '-O2',
1713 '-mcpu=v3',
1714 '-mco-re',
1715 '-gbtf',
1716 '-c',
1717 ]
1718
1719 # Generate defines that are appropriate to tell the compiler what architecture
1720 # we're compiling for. By default we just map meson's cpu_family to __<cpu_family>__.
1721 # This dictionary contains the exceptions where this doesn't work.
1722 #
1723 # C.f. https://mesonbuild.com/Reference-tables.html#cpu-families
1724 # and src/basic/missing_syscall_def.h.
1725 cpu_arch_defines = {
1726 'ppc' : ['-D__powerpc__'],
1727 'ppc64' : ['-D__powerpc64__', '-D_CALL_ELF=2'],
1728 'riscv32' : ['-D__riscv', '-D__riscv_xlen=32'],
1729 'riscv64' : ['-D__riscv', '-D__riscv_xlen=64'],
1730 'x86' : ['-D__i386__'],
1731
1732 # For arm, assume hardware fp is available.
1733 'arm' : ['-D__arm__', '-D__ARM_PCS_VFP'],
1734 }
1735
1736 bpf_arch_flags = cpu_arch_defines.get(host_machine.cpu_family(),
1737 ['-D__@0@__'.format(host_machine.cpu_family())])
1738 if bpf_compiler == 'gcc'
1739 bpf_arch_flags += ['-m' + host_machine.endian() + '-endian']
1740 endif
1741
1742 libbpf_include_dir = libbpf.get_variable(pkgconfig : 'includedir')
1743
1744 bpf_o_unstripped_cmd = []
1745 if bpf_compiler == 'clang'
1746 bpf_o_unstripped_cmd += [
1747 clang,
1748 bpf_clang_flags,
1749 bpf_arch_flags,
1750 ]
1751 elif bpf_compiler == 'gcc'
1752 bpf_o_unstripped_cmd += [
1753 bpf_gcc,
1754 bpf_gcc_flags,
1755 bpf_arch_flags,
1756 ]
1757 endif
1758
1759 bpf_o_unstripped_cmd += ['-I.']
1760
1761 if not meson.is_cross_build()
1762 target_triplet_cmd = run_command('gcc', '-dumpmachine', check: false)
1763 if target_triplet_cmd.returncode() == 0
1764 target_triplet = target_triplet_cmd.stdout().strip()
1765 bpf_o_unstripped_cmd += [
1766 '-isystem',
1767 '/usr/include/@0@'.format(target_triplet)
1768 ]
1769 endif
1770 endif
1771
1772 bpf_o_unstripped_cmd += [
1773 '-idirafter',
1774 libbpf_include_dir,
1775 '@INPUT@',
1776 '-o',
1777 '@OUTPUT@'
1778 ]
1779
1780 if bpftool_strip
1781 bpf_o_cmd = [
1782 bpftool,
1783 'gen',
1784 'object',
1785 '@OUTPUT@',
1786 '@INPUT@'
1787 ]
1788 elif bpf_compiler == 'clang'
1789 bpf_o_cmd = [
1790 llvm_strip,
1791 '-g',
1792 '@INPUT@',
1793 '-o',
1794 '@OUTPUT@'
1795 ]
1796 endif
1797
1798 skel_h_cmd = [
1799 bpftool,
1800 'gen',
1801 'skeleton',
1802 '@INPUT@'
1803 ]
1804 endif
1805
1806 #####################################################################
1807
1808 efi_arch = {
1809 'aarch64' : 'aa64',
1810 'arm' : 'arm',
1811 'loongarch32' : 'loongarch32',
1812 'loongarch64' : 'loongarch64',
1813 'riscv32' : 'riscv32',
1814 'riscv64' : 'riscv64',
1815 'x86_64' : 'x64',
1816 'x86' : 'ia32',
1817 }.get(host_machine.cpu_family(), '')
1818
1819 pyelftools = pymod.find_installation('python3',
1820 required : get_option('bootloader'),
1821 modules : ['elftools'])
1822
1823 have = get_option('bootloader').require(
1824 pyelftools.found() and get_option('efi') and efi_arch != '',
1825 error_message : 'unsupported EFI arch or EFI support is disabled').allowed()
1826 conf.set10('ENABLE_BOOTLOADER', have)
1827 conf.set_quoted('EFI_MACHINE_TYPE_NAME', have ? efi_arch : '')
1828
1829 efi_arch_alt = ''
1830 efi_cpu_family_alt = ''
1831 if have and efi_arch == 'x64' and cc.links('''
1832 #include <limits.h>
1833 int main(int argc, char *argv[]) {
1834 return __builtin_popcount(argc - CHAR_MAX);
1835 }''', args : ['-m32', '-march=i686'], name : '32bit build possible')
1836 efi_arch_alt = 'ia32'
1837 efi_cpu_family_alt = 'x86'
1838 endif
1839
1840 pefile = pymod.find_installation('python3', required: false, modules : ['pefile'])
1841
1842 want_ukify = get_option('ukify').require(python_39 and (want_tests != 'true' or pefile.found()), error_message : 'Python >= 3.9 and pefile required').allowed()
1843 conf.set10('ENABLE_UKIFY', want_ukify)
1844
1845 #####################################################################
1846
1847 check_efi_alignment_py = find_program('tools/check-efi-alignment.py')
1848
1849 #####################################################################
1850
1851 use_provided_vmlinux_h = false
1852 use_generated_vmlinux_h = false
1853 provided_vmlinux_h_path = get_option('vmlinux-h-path')
1854
1855 # For the more complex BPF programs we really want a vmlinux.h (which is arch
1856 # specific, but only somewhat bound to kernel version). Ideally the kernel
1857 # development headers would ship that, but right now they don't. Hence address
1858 # this in two ways:
1859 #
1860 # 1. Provide a vmlinux.h at build time
1861 # 2. Generate the file on the fly where possible (which requires /sys/ to be mounted)
1862 #
1863 # We generally prefer the former (to support reproducible builds), but will
1864 # fallback to the latter.
1865
1866 if conf.get('BPF_FRAMEWORK') == 1
1867 enable_vmlinux_h = get_option('vmlinux-h')
1868
1869 if enable_vmlinux_h == 'auto'
1870 if provided_vmlinux_h_path != ''
1871 use_provided_vmlinux_h = true
1872 elif fs.exists('/sys/kernel/btf/vmlinux') and \
1873 bpftool.found() and \
1874 (host_machine.cpu_family() == build_machine.cpu_family()) and \
1875 host_machine.cpu_family() in ['x86_64', 'aarch64']
1876
1877 # We will only generate a vmlinux.h from the running
1878 # kernel if the host and build machine are of the same
1879 # family. Also for now we focus on x86_64 and aarch64,
1880 # since other archs don't seem to be ready yet.
1881
1882 use_generated_vmlinux_h = true
1883 endif
1884 elif enable_vmlinux_h == 'provided'
1885 use_provided_vmlinux_h = true
1886 elif enable_vmlinux_h == 'generated'
1887 if not fs.exists('/sys/kernel/btf/vmlinux')
1888 error('BTF data from kernel not available (/sys/kernel/btf/vmlinux missing), cannot generate vmlinux.h, but was asked to.')
1889 endif
1890 if not bpftool.found()
1891 error('bpftool not available, cannot generate vmlinux.h, but was asked to.')
1892 endif
1893 use_generated_vmlinux_h = true
1894 endif
1895 endif
1896
1897 if use_provided_vmlinux_h
1898 if not fs.exists(provided_vmlinux_h_path)
1899 error('Path to provided vmlinux.h does not exist.')
1900 endif
1901 vmlinux_h_dependency = []
1902 bpf_o_unstripped_cmd += ['-I' + fs.parent(provided_vmlinux_h_path)]
1903 message('Using provided @0@'.format(provided_vmlinux_h_path))
1904 elif use_generated_vmlinux_h
1905 vmlinux_h_dependency = custom_target(
1906 'vmlinux.h',
1907 output: 'vmlinux.h',
1908 command : [ bpftool, 'btf', 'dump', 'file', '/sys/kernel/btf/vmlinux', 'format', 'c' ],
1909 capture : true)
1910
1911 bpf_o_unstripped_cmd += ['-I' + fs.parent(vmlinux_h_dependency.full_path())]
1912 message('Using generated @0@'.format(vmlinux_h_dependency.full_path()))
1913 else
1914 message('Using neither provided nor generated vmlinux.h, some features will not be available.')
1915 endif
1916
1917 conf.set10('HAVE_VMLINUX_H', use_provided_vmlinux_h or use_generated_vmlinux_h)
1918
1919 #####################################################################
1920
1921 check_version_history_py = find_program('tools/check-version-history.py')
1922 elf2efi_py = find_program('tools/elf2efi.py')
1923 export_dbus_interfaces_py = find_program('tools/dbus_exporter.py')
1924 generate_gperfs = find_program('tools/generate-gperfs.py')
1925 make_autosuspend_rules_py = find_program('tools/make-autosuspend-rules.py')
1926 make_directive_index_py = find_program('tools/make-directive-index.py')
1927 sync_docs_py = find_program('tools/sync-docs.py')
1928 make_man_index_py = find_program('tools/make-man-index.py')
1929 meson_render_jinja2 = find_program('tools/meson-render-jinja2.py')
1930 update_dbus_docs_py = find_program('tools/update-dbus-docs.py')
1931 update_hwdb_autosuspend_sh = find_program('tools/update-hwdb-autosuspend.sh')
1932 update_hwdb_sh = find_program('tools/update-hwdb.sh')
1933 update_man_rules_py = find_program('tools/update-man-rules.py')
1934 update_syscall_tables_sh = find_program('tools/update-syscall-tables.sh')
1935 xml_helper_py = find_program('tools/xml_helper.py')
1936
1937 #####################################################################
1938
1939 version_tag = get_option('version-tag')
1940 if version_tag == ''
1941 version_tag = meson.project_version()
1942 endif
1943
1944 conf.set_quoted('VERSION_TAG', version_tag)
1945
1946 vcs_tag = get_option('vcs-tag')
1947 command = ['sh', '-c',
1948 vcs_tag and fs.exists(project_source_root / '.git') ?
1949 'echo "-g$(git -C . describe --abbrev=7 --match="" --always --dirty=^)"' : ':']
1950 version_h = vcs_tag(
1951 input : 'src/version/version.h.in',
1952 output : 'version.h',
1953 fallback : '',
1954 command : command,
1955 )
1956
1957 shared_lib_tag = get_option('shared-lib-tag')
1958 if shared_lib_tag == ''
1959 shared_lib_tag = meson.project_version().split('~')[0]
1960 endif
1961
1962 #####################################################################
1963
1964 if get_option('b_coverage')
1965 userspace_c_args += ['-include', 'src/basic/coverage.h']
1966 endif
1967
1968 #####################################################################
1969
1970 config_h = configure_file(
1971 output : 'config.h',
1972 configuration : conf)
1973
1974 userspace_c_args += ['-include', 'config.h']
1975
1976 jinja2_cmdline = [meson_render_jinja2, config_h]
1977
1978 userspace = declare_dependency(
1979 compile_args : userspace_c_args,
1980 link_args : userspace_c_ld_args,
1981 sources : version_h,
1982 )
1983
1984 man_page_depends = []
1985
1986 #####################################################################
1987
1988 simple_tests = []
1989 libsystemd_tests = []
1990 simple_fuzzers = []
1991 catalogs = []
1992 modules = [] # nss, pam, and other plugins
1993 executables = []
1994 executables_by_name = {}
1995 fuzzer_exes = []
1996
1997 # binaries that have --help and are intended for use by humans,
1998 # usually, but not always, installed in /bin.
1999 public_programs = []
2000
2001 # D-Bus introspection XML export
2002 dbus_programs = []
2003
2004 # A list of boot stubs. Required for testing of ukify.
2005 boot_stubs = []
2006
2007 build_dir_include = include_directories('.')
2008
2009 basic_includes = include_directories(
2010 'src/basic',
2011 'src/fundamental',
2012 'src/systemd',
2013 '.')
2014
2015 libsystemd_includes = [basic_includes, include_directories(
2016 'src/libsystemd/sd-bus',
2017 'src/libsystemd/sd-device',
2018 'src/libsystemd/sd-event',
2019 'src/libsystemd/sd-hwdb',
2020 'src/libsystemd/sd-id128',
2021 'src/libsystemd/sd-journal',
2022 'src/libsystemd/sd-netlink',
2023 'src/libsystemd/sd-network',
2024 'src/libsystemd/sd-resolve')]
2025
2026 includes = [libsystemd_includes, include_directories('src/shared')]
2027
2028 subdir('po')
2029 subdir('catalog')
2030 subdir('src/fundamental')
2031 subdir('src/basic')
2032 subdir('src/libsystemd')
2033 subdir('src/shared')
2034 subdir('src/libudev')
2035
2036 libsystemd = shared_library(
2037 'systemd',
2038 version : libsystemd_version,
2039 include_directories : libsystemd_includes,
2040 link_args : ['-shared',
2041 '-Wl,--version-script=' + libsystemd_sym_path],
2042 link_with : [libbasic],
2043 link_whole : [libsystemd_static],
2044 dependencies : [librt,
2045 threads,
2046 userspace],
2047 link_depends : libsystemd_sym,
2048 install : true,
2049 install_tag: 'libsystemd',
2050 install_dir : libdir)
2051
2052 alias_target('libsystemd', libsystemd)
2053
2054 install_libsystemd_static = static_library(
2055 'systemd',
2056 libsystemd_sources,
2057 basic_sources,
2058 fundamental_sources,
2059 include_directories : libsystemd_includes,
2060 build_by_default : static_libsystemd != 'false',
2061 install : static_libsystemd != 'false',
2062 install_tag: 'libsystemd',
2063 install_dir : libdir,
2064 pic : static_libsystemd_pic,
2065 dependencies : [libblkid,
2066 libcap,
2067 libdl,
2068 libgcrypt_cflags,
2069 liblz4_cflags,
2070 libmount,
2071 libopenssl,
2072 librt,
2073 libxz_cflags,
2074 libzstd_cflags,
2075 threads,
2076 userspace],
2077 c_args : libsystemd_c_args + (static_libsystemd_pic ? [] : ['-fno-PIC']))
2078
2079 libudev = shared_library(
2080 'udev',
2081 version : libudev_version,
2082 include_directories : includes,
2083 link_args : ['-shared',
2084 '-Wl,--version-script=' + libudev_sym_path],
2085 link_with : [libsystemd_static, libshared_static],
2086 link_whole : libudev_basic,
2087 dependencies : [threads,
2088 userspace],
2089 link_depends : libudev_sym,
2090 install : true,
2091 install_tag: 'libudev',
2092 install_dir : libdir)
2093
2094 alias_target('libudev', libudev)
2095
2096 install_libudev_static = static_library(
2097 'udev',
2098 basic_sources,
2099 fundamental_sources,
2100 shared_sources,
2101 libsystemd_sources,
2102 libudev_sources,
2103 include_directories : includes,
2104 build_by_default : static_libudev != 'false',
2105 install : static_libudev != 'false',
2106 install_tag: 'libudev',
2107 install_dir : libdir,
2108 link_depends : libudev_sym,
2109 dependencies : [libmount,
2110 libshared_deps,
2111 userspace],
2112 c_args : static_libudev_pic ? [] : ['-fno-PIC'],
2113 pic : static_libudev_pic)
2114
2115 #####################################################################
2116
2117 runtest_env = custom_target(
2118 'systemd-runtest.env',
2119 output : 'systemd-runtest.env',
2120 command : [sh, '-c',
2121 '{ echo SYSTEMD_TEST_DATA=@0@; echo SYSTEMD_CATALOG_DIR=@1@; } >@OUTPUT@'.format(
2122 project_source_root / 'test',
2123 project_build_root / 'catalog')],
2124 depends : catalogs,
2125 build_by_default : true)
2126
2127 test_cflags = ['-DTEST_CODE=1']
2128 # We intentionally do not do inline initializations with definitions for a
2129 # bunch of _cleanup_ variables in tests, to ensure valgrind is triggered if we
2130 # use the variable unexpectedly. This triggers a lot of maybe-uninitialized
2131 # false positives when the combination of -O2 and -flto is used. Suppress them.
2132 if '-O2' in c_args and '-flto=auto' in c_args
2133 test_cflags += cc.first_supported_argument('-Wno-maybe-uninitialized')
2134 endif
2135
2136 #####################################################################
2137
2138 executable_template = {
2139 'include_directories' : includes,
2140 'link_with' : libshared,
2141 'install_rpath' : pkglibdir,
2142 'install' : true,
2143 }
2144
2145 generator_template = executable_template + {
2146 'install_dir' : systemgeneratordir,
2147 }
2148
2149 libexec_template = executable_template + {
2150 'install_dir' : libexecdir,
2151 }
2152
2153 executable_additional_kwargs = {
2154 'dependencies' : userspace,
2155 }
2156
2157 test_template = executable_template + {
2158 'build_by_default' : want_tests != 'false',
2159 'install' : install_tests,
2160 'install_dir' : unittestsdir,
2161 }
2162
2163 test_additional_kwargs = {
2164 'c_args' : test_cflags,
2165 'link_depends' : runtest_env,
2166 }
2167
2168 fuzz_template = executable_template + {
2169 'build_by_default' : fuzzer_build,
2170 'install' : false,
2171 }
2172
2173 if want_ossfuzz or (want_libfuzzer and fuzzing_engine.found())
2174 fuzz_additional_kwargs = {
2175 'dependencies' : fuzzing_engine,
2176 }
2177 elif want_libfuzzer and not fuzzing_engine.found()
2178 fuzz_additional_kwargs = {
2179 'link_args' : ['-fsanitize=fuzzer'],
2180 }
2181 else
2182 fuzz_additional_kwargs = {
2183 'sources' : files('src/fuzz/fuzz-main.c'),
2184 }
2185 endif
2186 fuzz_additional_kwargs += {
2187 'include_directories' : include_directories('src/fuzz'),
2188 'c_args' : test_cflags,
2189 }
2190
2191 nss_template = {
2192 'version' : '2',
2193 'include_directories' : includes,
2194 # Note that we link NSS modules with '-z nodelete' so that mempools never get orphaned
2195 'link_args' : ['-z', 'nodelete'],
2196 'link_with' : [
2197 libsystemd_static,
2198 libshared_static,
2199 libbasic,
2200 ],
2201 'dependencies' : [
2202 librt,
2203 threads,
2204 ],
2205 'install' : true,
2206 'install_tag' : 'nss',
2207 'install_dir' : libdir,
2208 }
2209
2210 pam_template = {
2211 'name_prefix' : '',
2212 'include_directories' : includes,
2213 'link_with' : [
2214 libsystemd_static,
2215 libshared_static,
2216 ],
2217 'dependencies' : [
2218 libpam_misc,
2219 libpam,
2220 threads,
2221 ],
2222 'install' : true,
2223 'install_tag' : 'pam',
2224 'install_dir' : pamlibdir,
2225 }
2226
2227 module_additional_kwargs = {
2228 'link_args' : ['-shared'],
2229 'dependencies' : userspace,
2230 }
2231
2232 #####################################################################
2233
2234 # systemd-analyze requires 'libcore'
2235 subdir('src/core')
2236 # systemd-networkd requires 'libsystemd_network'
2237 subdir('src/libsystemd-network')
2238 # hwdb requires 'udev_link_with' and 'udev_rpath'
2239 subdir('src/udev')
2240
2241 subdir('src/ac-power')
2242 subdir('src/analyze')
2243 subdir('src/ask-password')
2244 subdir('src/backlight')
2245 subdir('src/battery-check')
2246 subdir('src/binfmt')
2247 subdir('src/boot')
2248 subdir('src/boot/efi')
2249 subdir('src/busctl')
2250 subdir('src/cgls')
2251 subdir('src/cgroups-agent')
2252 subdir('src/cgtop')
2253 subdir('src/coredump')
2254 subdir('src/creds')
2255 subdir('src/cryptenroll')
2256 subdir('src/cryptsetup')
2257 subdir('src/debug-generator')
2258 subdir('src/delta')
2259 subdir('src/detect-virt')
2260 subdir('src/dissect')
2261 subdir('src/environment-d-generator')
2262 subdir('src/escape')
2263 subdir('src/firstboot')
2264 subdir('src/fsck')
2265 subdir('src/fstab-generator')
2266 subdir('src/getty-generator')
2267 subdir('src/gpt-auto-generator')
2268 subdir('src/hibernate-resume')
2269 subdir('src/home')
2270 subdir('src/hostname')
2271 subdir('src/hwdb')
2272 subdir('src/id128')
2273 subdir('src/import')
2274 subdir('src/initctl')
2275 subdir('src/integritysetup')
2276 subdir('src/journal')
2277 subdir('src/journal-remote')
2278 subdir('src/kernel-install')
2279 subdir('src/locale')
2280 subdir('src/login')
2281 subdir('src/machine')
2282 subdir('src/machine-id-setup')
2283 subdir('src/mountfsd')
2284 subdir('src/modules-load')
2285 subdir('src/mount')
2286 subdir('src/network')
2287 subdir('src/notify')
2288 subdir('src/nspawn')
2289 subdir('src/nsresourced')
2290 subdir('src/nss-myhostname')
2291 subdir('src/nss-mymachines')
2292 subdir('src/nss-resolve')
2293 subdir('src/nss-systemd')
2294 subdir('src/oom')
2295 subdir('src/partition')
2296 subdir('src/path')
2297 subdir('src/pcrextend')
2298 subdir('src/pcrlock')
2299 subdir('src/portable')
2300 subdir('src/pstore')
2301 subdir('src/quotacheck')
2302 subdir('src/random-seed')
2303 subdir('src/rc-local-generator')
2304 subdir('src/remount-fs')
2305 subdir('src/reply-password')
2306 subdir('src/resolve')
2307 subdir('src/rfkill')
2308 subdir('src/rpm')
2309 subdir('src/run')
2310 subdir('src/run-generator')
2311 subdir('src/shutdown')
2312 subdir('src/sleep')
2313 subdir('src/socket-activate')
2314 subdir('src/socket-proxy')
2315 subdir('src/ssh-generator')
2316 subdir('src/stdio-bridge')
2317 subdir('src/sulogin-shell')
2318 subdir('src/sysctl')
2319 subdir('src/sysext')
2320 subdir('src/system-update-generator')
2321 subdir('src/systemctl')
2322 subdir('src/sysupdate')
2323 subdir('src/sysusers')
2324 subdir('src/sysv-generator')
2325 subdir('src/storagetm')
2326 subdir('src/timedate')
2327 subdir('src/timesync')
2328 subdir('src/tmpfiles')
2329 subdir('src/tpm2-setup')
2330 subdir('src/tty-ask-password-agent')
2331 subdir('src/update-done')
2332 subdir('src/update-utmp')
2333 subdir('src/user-sessions')
2334 subdir('src/userdb')
2335 subdir('src/varlinkctl')
2336 subdir('src/vconsole')
2337 subdir('src/veritysetup')
2338 subdir('src/vmspawn')
2339 subdir('src/volatile-root')
2340 subdir('src/vpick')
2341 subdir('src/xdg-autostart-generator')
2342
2343 subdir('src/systemd')
2344
2345 subdir('src/test')
2346 subdir('src/fuzz')
2347 subdir('src/ukify/test') # needs to be last for test_env variable
2348 subdir('test/fuzz')
2349
2350 subdir('mime')
2351
2352 alias_target('devel', libsystemd_pc, libudev_pc, systemd_pc, udev_pc)
2353
2354 #####################################################################
2355
2356 foreach test : simple_tests
2357 executables += test_template + { 'sources' : [test] }
2358 endforeach
2359
2360 foreach test : libsystemd_tests
2361 executables += test_template + test
2362 endforeach
2363
2364 foreach fuzzer : simple_fuzzers
2365 executables += fuzz_template + { 'sources' : [fuzzer] }
2366 endforeach
2367
2368 foreach dict : executables
2369 name = dict.get('name', '')
2370 if name == ''
2371 name = fs.stem(dict.get('sources')[0])
2372 assert(name.split('-')[0] in ['test', 'fuzz'])
2373 endif
2374
2375 is_test = name.startswith('test-')
2376 is_fuzz = name.startswith('fuzz-')
2377
2378 build = true
2379 foreach cond : dict.get('conditions', [])
2380 if conf.get(cond) != 1
2381 build = false
2382 break
2383 endif
2384 endforeach
2385 if not build
2386 continue
2387 endif
2388
2389 kwargs = {}
2390 foreach key, val : dict
2391 if key in ['name', 'dbus', 'public', 'conditions',
2392 'type', 'suite', 'timeout', 'parallel']
2393 continue
2394 endif
2395
2396 kwargs += { key : val }
2397 endforeach
2398
2399 foreach key, val : executable_additional_kwargs
2400 kwargs += { key : [ kwargs.get(key, []), val ]}
2401 endforeach
2402
2403 if is_test
2404 kwargs += { 'install_dir' : kwargs.get('install_dir') / dict.get('type', '') }
2405 foreach key, val : test_additional_kwargs
2406 kwargs += { key : [ kwargs.get(key, []), val ] }
2407 endforeach
2408 endif
2409
2410 if is_fuzz
2411 foreach key, val : fuzz_additional_kwargs
2412 kwargs += { key : [ kwargs.get(key, []), val ] }
2413 endforeach
2414 endif
2415
2416 exe = executable(
2417 name,
2418 kwargs : kwargs,
2419 )
2420
2421 executables_by_name += { name : exe }
2422
2423 if dict.get('build_by_default', true)
2424 if dict.get('dbus', false)
2425 dbus_programs += exe
2426 endif
2427 if dict.get('public', false)
2428 public_programs += exe
2429 endif
2430 endif
2431
2432 if is_test
2433 type = dict.get('type', '')
2434 suite = dict.get('suite', '')
2435 if suite == ''
2436 suite = fs.name(fs.parent(dict.get('sources')[0]))
2437 if suite.startswith('sd-')
2438 suite = 'libsystemd'
2439 endif
2440 endif
2441
2442 if type == 'manual'
2443 message('@0@/@1@ is a manual test'.format(suite, name))
2444 elif type == 'unsafe' and want_tests != 'unsafe'
2445 message('@0@/@1@ is an unsafe test'.format(suite, name))
2446 elif dict.get('build_by_default')
2447 test(name, exe,
2448 env : test_env,
2449 timeout : dict.get('timeout', 30),
2450 suite : suite,
2451 is_parallel : dict.get('parallel', true))
2452 endif
2453 endif
2454
2455 if is_fuzz
2456 fuzzer_exes += exe
2457
2458 if want_tests != 'false'
2459 # Run the fuzz regression tests without any sanitizers enabled.
2460 # Additional invocations with sanitizers may get added below.
2461 fuzz_ins = fuzz_regression_tests.get(name, {})
2462 foreach directive : fuzz_ins.get('directives', [])
2463 tt = '@0@_@1@'.format(name, fs.name(directive.full_path()))
2464 if tt.substring(45) != ''
2465 error('Directive sample name is too long:', directive.full_path())
2466 endif
2467
2468 test(tt,
2469 exe,
2470 suite : 'fuzz',
2471 args : directive.full_path(),
2472 depends : directive)
2473 endforeach
2474 foreach file : fuzz_ins.get('files', [])
2475 tt = '@0@_@1@'.format(name, fs.name(file))
2476 if tt.substring(45) != ''
2477 error('Fuzz sample name is too long:', fs.name(file))
2478 endif
2479
2480 test(tt,
2481 exe,
2482 suite : 'fuzz',
2483 args : file)
2484 endforeach
2485 endif
2486 endif
2487 endforeach
2488
2489 alias_target('fuzzers', fuzzer_exes)
2490
2491 #####################################################################
2492
2493 test_dlopen = executables_by_name.get('test-dlopen')
2494
2495 foreach dict : modules
2496 name = dict.get('name')
2497 is_nss = name.startswith('nss_')
2498 is_pam = name.startswith('pam_')
2499
2500 build = true
2501 foreach cond : dict.get('conditions', [])
2502 if conf.get(cond) != 1
2503 build = false
2504 break
2505 endif
2506 endforeach
2507 if not build
2508 continue
2509 endif
2510
2511 kwargs = {}
2512 foreach key, val : dict
2513 if key in ['name', 'conditions', 'version-script']
2514 continue
2515 endif
2516 kwargs += { key : val }
2517 endforeach
2518
2519 kwargs += {
2520 'link_args' : [
2521 kwargs.get('link_args', []),
2522 '-Wl,--version-script=' + dict.get('version-script'),
2523 ],
2524 'link_depends' : [
2525 kwargs.get('link_depends', []),
2526 dict.get('version-script'),
2527 ],
2528 }
2529 foreach key, val : module_additional_kwargs
2530 kwargs += { key : [ kwargs.get(key, []), val ]}
2531 endforeach
2532
2533 lib = shared_library(
2534 name,
2535 kwargs : kwargs,
2536 )
2537
2538 if is_nss
2539 # We cannot use shared_module because it does not support version suffix.
2540 # Unfortunately shared_library insists on creating the symlink…
2541 meson.add_install_script(sh, '-c', 'rm $DESTDIR@0@/lib@1@.so'.format(libdir, name),
2542 install_tag : 'nss')
2543 endif
2544
2545 if want_tests != 'false' and (is_nss or is_pam)
2546 test('dlopen-' + name,
2547 test_dlopen,
2548 # path to dlopen must include a slash
2549 args : lib.full_path(),
2550 depends : lib,
2551 suite : is_nss ? 'nss' : 'pam')
2552 endif
2553 endforeach
2554
2555 #####################################################################
2556
2557 ukify = custom_target(
2558 'ukify',
2559 input : 'src/ukify/ukify.py',
2560 output : 'ukify',
2561 command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'],
2562 install : want_ukify,
2563 install_mode : 'rwxr-xr-x',
2564 install_dir : bindir)
2565 if want_ukify
2566 public_programs += ukify
2567
2568 # symlink for backwards compatibility after rename
2569 meson.add_install_script(sh, '-c',
2570 ln_s.format(bindir / 'ukify',
2571 libexecdir / 'ukify'))
2572 endif
2573
2574 #####################################################################
2575
2576 if get_option('integration-tests') != false
2577 system_mkosi = custom_target('system_mkosi',
2578 build_always_stale : true,
2579 output : 'system',
2580 console : true,
2581 command : ['mkosi', '-C', meson.project_source_root(), '--image=system', '--format=disk', '--output-dir', meson.project_build_root() / '@OUTPUT@', '--without-tests', '-fi', 'build'],
2582 depends : [executables_by_name['bootctl'], executables_by_name['systemd-measure'], executables_by_name['systemd-repart'], ukify],
2583 )
2584 endif
2585
2586 ############################################################
2587
2588 subdir('rules.d')
2589 subdir('test')
2590
2591 #####################################################################
2592
2593 subdir('docs/sysvinit')
2594 subdir('docs/var-log')
2595 subdir('hwdb.d')
2596 subdir('man')
2597 subdir('modprobe.d')
2598 subdir('network')
2599 subdir('presets')
2600 subdir('shell-completion/bash')
2601 subdir('shell-completion/zsh')
2602 subdir('sysctl.d')
2603 subdir('sysusers.d')
2604 subdir('tmpfiles.d')
2605 subdir('units')
2606
2607 install_subdir('factory/etc',
2608 install_dir : factorydir)
2609 subdir('factory/templates')
2610
2611 if install_sysconfdir
2612 install_data('xorg/50-systemd-user.sh',
2613 install_dir : xinitrcdir)
2614 endif
2615 install_data('LICENSE.GPL2',
2616 'LICENSE.LGPL2.1',
2617 'NEWS',
2618 'README',
2619 'docs/CODING_STYLE.md',
2620 'docs/DISTRO_PORTING.md',
2621 'docs/ENVIRONMENT.md',
2622 'docs/HACKING.md',
2623 'docs/TRANSIENT-SETTINGS.md',
2624 'docs/TRANSLATORS.md',
2625 'docs/UIDS-GIDS.md',
2626 install_dir : docdir)
2627
2628 install_subdir('LICENSES',
2629 install_dir : docdir)
2630
2631 install_emptydir(systemdstatedir)
2632
2633 #####################################################################
2634
2635 # Ensure that changes to the docs/ directory do not break the
2636 # basic Github pages build. But only run it in developer mode,
2637 # as it might be fragile due to changes in the tooling, and it is
2638 # not generally useful for users.
2639 jekyll = find_program('jekyll', required : false)
2640 if get_option('mode') == 'developer' and want_tests != 'false' and jekyll.found()
2641 test('github-pages',
2642 jekyll,
2643 suite : 'dist',
2644 args : ['build',
2645 '--source', project_source_root / 'docs',
2646 '--destination', project_build_root / '_site'])
2647 endif
2648
2649 #####################################################################
2650
2651 check_help = find_program('tools/check-help.sh')
2652 check_version = find_program('tools/check-version.sh')
2653
2654 foreach exec : public_programs
2655 name = fs.name(exec.full_path())
2656 if want_tests != 'false'
2657 test('check-help-' + name,
2658 check_help,
2659 suite : 'dist',
2660 args : exec.full_path(),
2661 depends: exec)
2662
2663 version = meson.project_version()
2664 if name == 'udevadm'
2665 # For compatibility reasons we can't use the full version in udevadm.
2666 version = version.split('~')[0]
2667 endif
2668
2669 test('check-version-' + name,
2670 check_version,
2671 suite : 'dist',
2672 args : [exec.full_path(),
2673 version],
2674 depends: exec)
2675 endif
2676 endforeach
2677
2678 # Enable tests for all supported sanitizers
2679 foreach tuple : fuzz_sanitizers
2680 sanitizer = tuple[0]
2681 build = tuple[1]
2682
2683 if cc.has_link_argument('-fsanitize=@0@'.format(sanitizer))
2684 foreach fuzzer, fuzz_ins : fuzz_regression_tests
2685 name = '@0@:@1@'.format(fuzzer, sanitizer)
2686 if want_tests == 'false'
2687 message('Not compiling @0@ because tests is set to false'.format(name))
2688 continue
2689 endif
2690 if not fuzz_tests
2691 message('Not compiling @0@ because fuzz-tests is set to false'.format(name))
2692 continue
2693 endif
2694 exe = custom_target(
2695 name,
2696 output : name,
2697 depends : build,
2698 command : [ln, '-fs',
2699 build.full_path() / fuzzer,
2700 '@OUTPUT@'],
2701 build_by_default : true)
2702
2703 foreach directive : fuzz_ins.get('directives', [])
2704 test('@0@_@1@_@2@'.format(fuzzer, fs.name(directive.full_path()), sanitizer),
2705 env,
2706 suite : 'fuzz+san',
2707 env : ['UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1'],
2708 timeout : 60,
2709 args : [exe.full_path(), directive.full_path()],
2710 depends : directive)
2711 endforeach
2712 foreach file : fuzz_ins.get('files', [])
2713 test('@0@_@1@_@2@'.format(fuzzer, fs.name(file), sanitizer),
2714 env,
2715 suite : 'fuzz+san',
2716 env : ['UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1'],
2717 timeout : 60,
2718 args : [exe.full_path(), file])
2719 endforeach
2720 endforeach
2721 endif
2722 endforeach
2723
2724 #####################################################################
2725
2726 if git.found()
2727 all_files = run_command(
2728 env, '-u', 'GIT_WORK_TREE',
2729 git, '--git-dir=@0@/.git'.format(project_source_root),
2730 'ls-files', ':/*.[ch]', ':/*.cc',
2731 check : false)
2732 if all_files.returncode() == 0
2733 all_files = files(all_files.stdout().split())
2734
2735 custom_target(
2736 'tags',
2737 output : 'tags',
2738 command : [env, 'etags', '-o', '@0@/TAGS'.format(project_source_root)] + all_files)
2739 run_target(
2740 'ctags',
2741 command : [env, 'ctags', '--tag-relative=never', '-o', '@0@/tags'.format(project_source_root)] + all_files)
2742
2743 ############################################
2744
2745 if want_tests != 'false' and conf.get('BUILD_MODE_DEVELOPER') == 1
2746 test('check-includes',
2747 files('tools/check-includes.py'),
2748 args: all_files,
2749 env : ['PROJECT_SOURCE_ROOT=@0@'.format(project_source_root)],
2750 suite : 'headers')
2751 endif
2752 endif
2753
2754 ####################################################
2755
2756 git_contrib_sh = find_program('tools/git-contrib.sh')
2757 run_target(
2758 'git-contrib',
2759 command : [git_contrib_sh])
2760
2761 ####################################################
2762
2763 git_head = run_command(
2764 git, '--git-dir=@0@/.git'.format(project_source_root),
2765 'rev-parse', 'HEAD',
2766 check : false).stdout().strip()
2767 git_head_short = run_command(
2768 git, '--git-dir=@0@/.git'.format(project_source_root),
2769 'rev-parse', '--short=7', 'HEAD',
2770 check : false).stdout().strip()
2771
2772 run_target(
2773 'git-snapshot',
2774 command : [git, 'archive',
2775 '-o', '@0@/systemd-@1@.tar.gz'.format(project_source_root,
2776 git_head_short),
2777 '--prefix', 'systemd-@0@/'.format(git_head),
2778 'HEAD'])
2779 endif
2780
2781 #####################################################################
2782
2783 check_api_docs_sh = find_program('tools/check-api-docs.sh')
2784 run_target(
2785 'check-api-docs',
2786 depends : [man, libsystemd, libudev],
2787 command : [check_api_docs_sh, libsystemd.full_path(), libudev.full_path()])
2788
2789 alias_target('update-dbus-docs', update_dbus_docs)
2790 alias_target('update-man-rules', update_man_rules)
2791
2792 if not meson.is_cross_build()
2793 custom_target(
2794 'export-dbus-interfaces',
2795 output : fs.name(dbus_interfaces_dir),
2796 install : dbus_interfaces_dir != 'no',
2797 install_dir : fs.parent(dbus_interfaces_dir),
2798 command : [export_dbus_interfaces_py, '@OUTPUT@', dbus_programs])
2799 endif
2800
2801 meson_extract_unit_files = find_program('tools/meson-extract-unit-files.py')
2802 custom_target('installed-unit-files.txt',
2803 output : 'installed-unit-files.txt',
2804 capture : true,
2805 install : want_tests != 'no' and install_tests,
2806 install_dir : testdata_dir,
2807 command : [meson_extract_unit_files, project_build_root])
2808
2809 #####################################################################
2810
2811 alt_time_epoch = run_command('date', '-Is', '-u', '-d', '@@0@'.format(time_epoch),
2812 check : true).stdout().strip()
2813
2814 summary({
2815 'split bin-sbin' : split_bin,
2816 'prefix directory' : prefixdir,
2817 'sysconf directory' : sysconfdir,
2818 'include directory' : includedir,
2819 'lib directory' : libdir,
2820 'SysV init scripts' : sysvinit_path,
2821 'SysV rc?.d directories' : sysvrcnd_path,
2822 'PAM modules directory' : pamlibdir,
2823 'PAM configuration directory' : pamconfdir,
2824 'ssh server configuration directory' : sshdconfdir,
2825 'ssh server privilege separation directory' : sshdprivsepdir,
2826 'ssh client configuration directory' : sshconfdir,
2827 'libcryptsetup plugins directory' : libcryptsetup_plugins_dir,
2828 'RPM macros directory' : rpmmacrosdir,
2829 'modprobe.d directory' : modprobedir,
2830 'D-Bus policy directory' : dbuspolicydir,
2831 'D-Bus session directory' : dbussessionservicedir,
2832 'D-Bus system directory' : dbussystemservicedir,
2833 'D-Bus interfaces directory' : dbus_interfaces_dir,
2834 'bash completions directory' : bashcompletiondir,
2835 'zsh completions directory' : zshcompletiondir,
2836 'private shared lib version tag' : shared_lib_tag,
2837 'extra start script' : get_option('rc-local'),
2838 'debug shell' : '@0@ @ @1@'.format(get_option('debug-shell'),
2839 get_option('debug-tty')),
2840 'system UIDs' : '<=@0@ (alloc >=@1@)'.format(conf.get('SYSTEM_UID_MAX'),
2841 conf.get('SYSTEM_ALLOC_UID_MIN')),
2842 'system GIDs' : '<=@0@ (alloc >=@1@)'.format(conf.get('SYSTEM_GID_MAX'),
2843 conf.get('SYSTEM_ALLOC_GID_MIN')),
2844 'dynamic UIDs' : '@0@…@1@'.format(dynamic_uid_min, dynamic_uid_max),
2845 'container UID bases' : '@0@…@1@'.format(container_uid_base_min, container_uid_base_max),
2846 'static UID/GID allocations' : ' '.join(static_ugids),
2847 '/dev/kvm access mode' : get_option('dev-kvm-mode'),
2848 'render group access mode' : get_option('group-render-mode'),
2849 'certificate root directory' : get_option('certificate-root'),
2850 'support URL' : support_url,
2851 'nobody user name' : nobody_user,
2852 'nobody group name' : nobody_group,
2853 'fallback hostname' : get_option('fallback-hostname'),
2854 'default compression method' : compression,
2855 'default DNSSEC mode' : default_dnssec,
2856 'default DNS-over-TLS mode' : default_dns_over_tls,
2857 'default mDNS mode' : default_mdns,
2858 'default LLMNR mode' : default_llmnr,
2859 'default DNS servers' : dns_servers.split(' '),
2860 'default NTP servers' : ntp_servers.split(' '),
2861 'default net.naming_scheme= value': default_net_naming_scheme,
2862 'default KillUserProcesses= value': kill_user_processes,
2863 'default locale' : default_locale,
2864 'default nspawn locale' : nspawn_locale,
2865 'default status unit format' : status_unit_format_default,
2866 'default user $PATH' :
2867 default_user_path != '' ? default_user_path : '(same as system services)',
2868 'systemd service watchdog' : service_watchdog == '' ? 'disabled' : service_watchdog,
2869 'time epoch' : '@0@ (@1@)'.format(time_epoch, alt_time_epoch)})
2870
2871 # TODO:
2872 # CFLAGS: ${OUR_CFLAGS} ${CFLAGS}
2873 # CPPFLAGS: ${OUR_CPPFLAGS} ${CPPFLAGS}
2874 # LDFLAGS: ${OUR_LDFLAGS} ${LDFLAGS}
2875
2876 found = []
2877 missing = []
2878
2879 foreach tuple : [
2880 # dependencies
2881 ['ACL'],
2882 ['AUDIT'],
2883 ['AppArmor'],
2884 ['IMA'],
2885 ['PAM'],
2886 ['SECCOMP'],
2887 ['SELinux'],
2888 ['SMACK'],
2889 ['blkid'],
2890 ['elfutils'],
2891 ['gcrypt'],
2892 ['gnutls'],
2893 ['libbpf'],
2894 ['libcryptsetup'],
2895 ['libcryptsetup-plugins'],
2896 ['libcurl'],
2897 ['libfdisk'],
2898 ['libfido2'],
2899 ['libidn'],
2900 ['libidn2'],
2901 ['libiptc'],
2902 ['microhttpd'],
2903 ['openssl'],
2904 ['p11kit'],
2905 ['passwdqc'],
2906 ['pcre2'],
2907 ['pwquality'],
2908 ['qrencode'],
2909 ['tpm2'],
2910 ['xkbcommon'],
2911
2912 # compression libs
2913 ['zstd'],
2914 ['lz4'],
2915 ['xz'],
2916 ['zlib'],
2917 ['bzip2'],
2918
2919 # components
2920 ['backlight'],
2921 ['binfmt'],
2922 ['bootloader'],
2923 ['bpf-framework', conf.get('BPF_FRAMEWORK') == 1],
2924 ['coredump'],
2925 ['efi'],
2926 ['environment.d'],
2927 ['firstboot'],
2928 ['hibernate'],
2929 ['homed'],
2930 ['hostnamed'],
2931 ['hwdb'],
2932 ['importd'],
2933 ['initrd'],
2934 ['kernel-install'],
2935 ['localed'],
2936 ['logind'],
2937 ['machined'],
2938 ['networkd'],
2939 ['nss-myhostname'],
2940 ['nss-mymachines'],
2941 ['nss-resolve'],
2942 ['nss-systemd'],
2943 ['oomd'],
2944 ['portabled'],
2945 ['pstore'],
2946 ['quotacheck'],
2947 ['randomseed'],
2948 ['repart'],
2949 ['resolve'],
2950 ['rfkill'],
2951 ['sysext'],
2952 ['systemd-analyze', conf.get('ENABLE_ANALYZE') == 1],
2953 ['sysupdate'],
2954 ['sysusers'],
2955 ['storagetm'],
2956 ['timedated'],
2957 ['timesyncd'],
2958 ['tmpfiles'],
2959 ['userdb'],
2960 ['vconsole'],
2961 ['vmspawn'],
2962 ['xdg-autostart'],
2963
2964 # optional features
2965 ['dmi'],
2966 ['idn'],
2967 ['polkit'],
2968 ['nscd'],
2969 ['legacy-pkla', install_polkit_pkla],
2970 ['kmod'],
2971 ['xenctrl'],
2972 ['dbus'],
2973 ['glib'],
2974 ['tpm'],
2975 ['man pages', want_man],
2976 ['html pages', want_html],
2977 ['man page indices', want_man and have_lxml],
2978 ['SysV compat'],
2979 ['compat-mutable-uid-boundaries'],
2980 ['utmp'],
2981 ['ldconfig'],
2982 ['adm group', get_option('adm-group')],
2983 ['wheel group', get_option('wheel-group')],
2984 ['gshadow'],
2985 ['debug hashmap'],
2986 ['debug mmap cache'],
2987 ['debug siphash'],
2988 ['trace logging', conf.get('LOG_TRACE') == 1],
2989 ['slow tests', slow_tests],
2990 ['fuzz tests', fuzz_tests],
2991 ['install tests', install_tests],
2992 ['link-udev-shared', get_option('link-udev-shared')],
2993 ['link-systemctl-shared', get_option('link-systemctl-shared')],
2994 ['link-networkd-shared', get_option('link-networkd-shared')],
2995 ['link-timesyncd-shared', get_option('link-timesyncd-shared')],
2996 ['link-journalctl-shared', get_option('link-journalctl-shared')],
2997 ['link-boot-shared', get_option('link-boot-shared')],
2998 ['link-portabled-shared', get_option('link-portabled-shared')],
2999 ['first-boot-full-preset'],
3000 ['fexecve'],
3001 ['standalone-binaries', get_option('standalone-binaries')],
3002 ['coverage', get_option('b_coverage')],
3003 ]
3004
3005 if tuple.length() >= 2
3006 cond = tuple[1]
3007 else
3008 ident1 = 'HAVE_' + tuple[0].underscorify().to_upper()
3009 ident2 = 'ENABLE_' + tuple[0].underscorify().to_upper()
3010 cond = conf.get(ident1, 0) == 1 or conf.get(ident2, 0) == 1
3011 endif
3012 if cond
3013 found += tuple[0]
3014 else
3015 missing += tuple[0]
3016 endif
3017 endforeach
3018
3019 if static_libsystemd == 'false'
3020 missing += 'static-libsystemd'
3021 else
3022 found += 'static-libsystemd(@0@)'.format(static_libsystemd)
3023 endif
3024
3025 if static_libudev == 'false'
3026 missing += 'static-libudev'
3027 else
3028 found += 'static-libudev(@0@)'.format(static_libudev)
3029 endif
3030
3031 if conf.get('HAVE_OPENSSL_OR_GCRYPT') == 1 and conf.get('PREFER_OPENSSL') == 1
3032 found += 'cryptolib(openssl)'
3033 elif conf.get('HAVE_OPENSSL_OR_GCRYPT') == 1
3034 found += 'cryptolib(gcrypt)'
3035 else
3036 missing += 'cryptolib'
3037 endif
3038
3039 if conf.get('DNS_OVER_TLS_USE_GNUTLS') == 1
3040 found += 'DNS-over-TLS(gnutls)'
3041 elif conf.get('DNS_OVER_TLS_USE_OPENSSL') == 1
3042 found += 'DNS-over-TLS(openssl)'
3043 else
3044 missing += 'DNS-over-TLS'
3045 endif
3046
3047 summary({
3048 'enabled' : ', '.join(found),
3049 'disabled' : ', '.join(missing)},
3050 section : 'Features')