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