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