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