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