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