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