]> git.ipfire.org Git - thirdparty/systemd.git/blob - meson.build
Merge pull request #31899 from yuwata/sd-journal-add-match
[thirdparty/systemd.git] / meson.build
1 # SPDX-License-Identifier: LGPL-2.1-or-later
2
3 project('systemd', 'c',
4 version : files('meson.version'),
5 license : 'LGPLv2+',
6 default_options: [
7 'c_std=gnu11',
8 'prefix=/usr',
9 'sysconfdir=/etc',
10 'localstatedir=/var',
11 'warning_level=2',
12 ],
13 meson_version : '>= 0.60.0',
14 )
15
16 libsystemd_version = '0.38.0'
17 libudev_version = '1.7.8'
18
19 conf = configuration_data()
20 conf.set_quoted('PROJECT_URL', 'https://systemd.io/')
21 conf.set('PROJECT_VERSION', meson.project_version().split('~')[0],
22 description : 'Numerical project version (used where a simple number is expected)')
23 conf.set_quoted('PROJECT_VERSION_FULL', meson.project_version(), description : 'Full project version')
24
25 # This is to be used instead of meson.source_root(), as the latter will return
26 # the wrong result when systemd is being built as a meson subproject
27 project_source_root = meson.current_source_dir()
28 project_build_root = meson.current_build_dir()
29 relative_source_path = run_command('realpath',
30 '--relative-to=@0@'.format(project_build_root),
31 project_source_root,
32 check : true).stdout().strip()
33 conf.set_quoted('RELATIVE_SOURCE_PATH', relative_source_path)
34
35 conf.set10('BUILD_MODE_DEVELOPER', get_option('mode') == 'developer',
36 description : 'tailor build to development or release builds')
37
38 feature = get_option('log-message-verification')
39 if feature.auto()
40 have = conf.get('BUILD_MODE_DEVELOPER') == 1
41 else
42 have = feature.enabled()
43 endif
44 conf.set10('LOG_MESSAGE_VERIFICATION', have)
45
46 want_ossfuzz = get_option('oss-fuzz')
47 want_libfuzzer = get_option('llvm-fuzz')
48 if want_ossfuzz and want_libfuzzer
49 error('only one of oss-fuzz or llvm-fuzz can be specified')
50 endif
51
52 fuzzer_build = want_ossfuzz or want_libfuzzer
53
54 # If we're building *not* for actual fuzzing, allow input samples of any size
55 # (for testing and for reproduction of issues discovered with previously-higher
56 # limits).
57 conf.set10('FUZZ_USE_SIZE_LIMIT', fuzzer_build)
58
59 # We'll set this to '1' for EFI builds in a different place.
60 conf.set10('SD_BOOT', false)
61
62 # Create a title-less summary section early, so it ends up first in the output.
63 # More items are added later after they have been detected.
64 summary({'build mode' : get_option('mode')})
65
66 #####################################################################
67
68 # Try to install the git pre-commit hook
69 git_setup_sh = find_program('tools/git-setup.sh', required : false)
70 if git_setup_sh.found()
71 git_hook = run_command(git_setup_sh, check : false)
72 if git_hook.returncode() == 0
73 message(git_hook.stdout().strip())
74 endif
75 endif
76
77 #####################################################################
78
79 fs = import('fs')
80 if get_option('split-bin') == 'auto'
81 split_bin = not fs.is_symlink('/usr/sbin')
82 else
83 split_bin = get_option('split-bin') == 'true'
84 endif
85 conf.set10('HAVE_SPLIT_BIN', split_bin,
86 description : 'bin and sbin directories are separate')
87
88 have_standalone_binaries = get_option('standalone-binaries')
89
90 sysvinit_path = get_option('sysvinit-path')
91 sysvrcnd_path = get_option('sysvrcnd-path')
92 conf.set10('HAVE_SYSV_COMPAT', sysvinit_path != '' and sysvrcnd_path != '',
93 description : 'SysV init scripts and rcN.d links are supported')
94 conf.set10('CREATE_LOG_DIRS', get_option('create-log-dirs'))
95
96 if get_option('hibernate') and not get_option('initrd')
97 error('hibernate depends on initrd')
98 endif
99
100 conf.set10('BUMP_PROC_SYS_FS_FILE_MAX', get_option('bump-proc-sys-fs-file-max'))
101 conf.set10('BUMP_PROC_SYS_FS_NR_OPEN', get_option('bump-proc-sys-fs-nr-open'))
102 conf.set('HIGH_RLIMIT_NOFILE', 512*1024)
103
104 # Meson ignores the preceding arguments when joining paths if an absolute
105 # component is encountered, so this should canonicalize various paths when they
106 # are absolute or relative.
107 prefixdir = get_option('prefix')
108 if not prefixdir.startswith('/')
109 error('Prefix is not absolute: "@0@"'.format(prefixdir))
110 endif
111
112 prefixdir_noslash = '/' + prefixdir.strip('/')
113 bindir = prefixdir / get_option('bindir')
114 sbindir = prefixdir / (split_bin ? 'sbin' : 'bin')
115 sbin_to_bin = split_bin ? '../bin/' : ''
116 libdir = prefixdir / get_option('libdir')
117 sysconfdir = prefixdir / get_option('sysconfdir')
118 includedir = prefixdir / get_option('includedir')
119 datadir = prefixdir / get_option('datadir')
120 localstatedir = '/' / get_option('localstatedir')
121
122 libexecdir = prefixdir / 'lib/systemd'
123 pkglibdir = libdir / 'systemd'
124
125 install_sysconfdir = get_option('install-sysconfdir') != 'false'
126 install_sysconfdir_samples = get_option('install-sysconfdir') == 'true'
127 # Dirs of external packages
128 pkgconfigdatadir = get_option('pkgconfigdatadir') != '' ? get_option('pkgconfigdatadir') : datadir / 'pkgconfig'
129 pkgconfiglibdir = get_option('pkgconfiglibdir') != '' ? get_option('pkgconfiglibdir') : libdir / 'pkgconfig'
130 polkitpolicydir = datadir / 'polkit-1/actions'
131 polkitrulesdir = datadir / 'polkit-1/rules.d'
132 polkitpkladir = localstatedir / 'lib/polkit-1/localauthority/10-vendor.d'
133 xinitrcdir = get_option('xinitrcdir') != '' ? get_option('xinitrcdir') : sysconfdir / 'X11/xinit/xinitrc.d'
134 rpmmacrosdir = get_option('rpmmacrosdir')
135 if rpmmacrosdir != 'no'
136 rpmmacrosdir = prefixdir / rpmmacrosdir
137 endif
138 modprobedir = prefixdir / 'lib/modprobe.d'
139
140 # Our own paths
141 pkgdatadir = datadir / 'systemd'
142 environmentdir = prefixdir / 'lib/environment.d'
143 pkgsysconfdir = sysconfdir / 'systemd'
144 userunitdir = prefixdir / 'lib/systemd/user'
145 userpresetdir = prefixdir / 'lib/systemd/user-preset'
146 tmpfilesdir = prefixdir / 'lib/tmpfiles.d'
147 usertmpfilesdir = prefixdir / 'share/user-tmpfiles.d'
148 sysusersdir = prefixdir / 'lib/sysusers.d'
149 sysctldir = prefixdir / 'lib/sysctl.d'
150 binfmtdir = prefixdir / 'lib/binfmt.d'
151 modulesloaddir = prefixdir / 'lib/modules-load.d'
152 networkdir = prefixdir / 'lib/systemd/network'
153 systemgeneratordir = libexecdir / 'system-generators'
154 usergeneratordir = prefixdir / 'lib/systemd/user-generators'
155 systemenvgeneratordir = prefixdir / 'lib/systemd/system-environment-generators'
156 userenvgeneratordir = prefixdir / 'lib/systemd/user-environment-generators'
157 systemshutdowndir = libexecdir / 'system-shutdown'
158 systemsleepdir = libexecdir / 'system-sleep'
159 systemunitdir = prefixdir / 'lib/systemd/system'
160 systempresetdir = prefixdir / 'lib/systemd/system-preset'
161 udevlibexecdir = prefixdir / 'lib/udev'
162 udevrulesdir = udevlibexecdir / 'rules.d'
163 udevhwdbdir = udevlibexecdir / 'hwdb.d'
164 catalogdir = prefixdir / 'lib/systemd/catalog'
165 kerneldir = prefixdir / 'lib/kernel'
166 kernelinstalldir = kerneldir / 'install.d'
167 factorydir = datadir / 'factory'
168 bootlibdir = prefixdir / 'lib/systemd/boot/efi'
169 testsdir = prefixdir / 'lib/systemd/tests'
170 unittestsdir = testsdir / 'unit-tests'
171 testdata_dir = testsdir / 'testdata'
172 systemdstatedir = localstatedir / 'lib/systemd'
173 catalogstatedir = systemdstatedir / 'catalog'
174 randomseeddir = localstatedir / 'lib/systemd'
175 profiledir = libexecdir / 'portable' / 'profile'
176 repartdefinitionsdir = libexecdir / 'repart/definitions'
177 ntpservicelistdir = prefixdir / 'lib/systemd/ntp-units.d'
178 credstoredir = prefixdir / 'lib/credstore'
179 pcrlockdir = prefixdir / 'lib/pcrlock.d'
180 mimepackagesdir = prefixdir / 'share/mime/packages'
181
182 configfiledir = get_option('configfiledir')
183 if configfiledir == ''
184 configfiledir= sysconfdir
185 endif
186 pkgconfigfiledir = configfiledir / 'systemd'
187
188 docdir = get_option('docdir')
189 if docdir == ''
190 docdir = datadir / 'doc/systemd'
191 endif
192
193 pamlibdir = get_option('pamlibdir')
194 if pamlibdir == ''
195 pamlibdir = libdir / 'security'
196 endif
197
198 pamconfdir = get_option('pamconfdir')
199 if pamconfdir == ''
200 pamconfdir = prefixdir / 'lib/pam.d'
201 endif
202
203 sshconfdir = get_option('sshconfdir')
204 if sshconfdir == ''
205 sshconfdir = sysconfdir / 'ssh/ssh_config.d'
206 endif
207
208 sshdconfdir = get_option('sshdconfdir')
209 if sshdconfdir == ''
210 sshdconfdir = sysconfdir / 'ssh/sshd_config.d'
211 endif
212
213 libcryptsetup_plugins_dir = get_option('libcryptsetup-plugins-dir')
214 if libcryptsetup_plugins_dir == ''
215 libcryptsetup_plugins_dir = libdir / 'cryptsetup'
216 endif
217
218 memory_accounting_default = get_option('memory-accounting-default')
219 status_unit_format_default = get_option('status-unit-format-default')
220 if status_unit_format_default == 'auto'
221 status_unit_format_default = conf.get('BUILD_MODE_DEVELOPER') == 1 ? 'name' : 'description'
222 endif
223
224 conf.set_quoted('BINDIR', bindir)
225 conf.set_quoted('BINFMT_DIR', binfmtdir)
226 conf.set_quoted('BOOTLIBDIR', bootlibdir)
227 conf.set_quoted('CATALOG_DATABASE', catalogstatedir / 'database')
228 conf.set_quoted('CERTIFICATE_ROOT', get_option('certificate-root'))
229 conf.set_quoted('DOC_DIR', docdir)
230 conf.set_quoted('DOCUMENT_ROOT', pkgdatadir / 'gatewayd')
231 conf.set_quoted('ENVIRONMENT_DIR', environmentdir)
232 conf.set_quoted('INCLUDE_DIR', includedir)
233 conf.set_quoted('LIBDIR', libdir)
234 conf.set_quoted('LIBEXECDIR', libexecdir)
235 conf.set_quoted('KERNEL_INSTALL_DIR', kernelinstalldir)
236 conf.set_quoted('MODPROBE_DIR', modprobedir)
237 conf.set_quoted('MODULESLOAD_DIR', modulesloaddir)
238 conf.set_quoted('PKGSYSCONFDIR', pkgsysconfdir)
239 conf.set_quoted('POLKIT_AGENT_BINARY_PATH', bindir / 'pkttyagent')
240 conf.set_quoted('PREFIX', prefixdir)
241 conf.set_quoted('PREFIX_NOSLASH', prefixdir_noslash)
242 conf.set_quoted('RANDOM_SEED', randomseeddir / 'random-seed')
243 conf.set_quoted('RANDOM_SEED_DIR', randomseeddir)
244 conf.set_quoted('RC_LOCAL_PATH', get_option('rc-local'))
245 conf.set_quoted('SSHCONFDIR', sshconfdir)
246 conf.set_quoted('SSHDCONFDIR', sshdconfdir)
247 conf.set_quoted('SYSCONF_DIR', sysconfdir)
248 conf.set_quoted('SYSCTL_DIR', sysctldir)
249 conf.set_quoted('SYSTEMCTL_BINARY_PATH', bindir / 'systemctl')
250 conf.set_quoted('SYSTEMD_BINARY_PATH', libexecdir / 'systemd')
251 conf.set_quoted('SYSTEMD_EXECUTOR_BINARY_PATH', libexecdir / 'systemd-executor')
252 conf.set_quoted('SYSTEMD_CATALOG_DIR', catalogdir)
253 conf.set_quoted('SYSTEMD_CGROUPS_AGENT_PATH', libexecdir / 'systemd-cgroups-agent')
254 conf.set_quoted('SYSTEMD_CRYPTSETUP_PATH', bindir / 'systemd-cryptsetup')
255 conf.set_quoted('SYSTEMD_EXPORT_PATH', libexecdir / 'systemd-export')
256 conf.set_quoted('SYSTEMD_FSCK_PATH', libexecdir / 'systemd-fsck')
257 conf.set_quoted('SYSTEMD_GROWFS_PATH', libexecdir / 'systemd-growfs')
258 conf.set_quoted('SYSTEMD_HOMEWORK_PATH', libexecdir / 'systemd-homework')
259 conf.set_quoted('SYSTEMD_IMPORT_FS_PATH', libexecdir / 'systemd-import-fs')
260 conf.set_quoted('SYSTEMD_IMPORT_PATH', libexecdir / 'systemd-import')
261 conf.set_quoted('SYSTEMD_INTEGRITYSETUP_PATH', libexecdir / 'systemd-integritysetup')
262 conf.set_quoted('SYSTEMD_KBD_MODEL_MAP', pkgdatadir / 'kbd-model-map')
263 conf.set_quoted('SYSTEMD_LANGUAGE_FALLBACK_MAP', pkgdatadir / 'language-fallback-map')
264 conf.set_quoted('SYSTEMD_MAKEFS_PATH', libexecdir / 'systemd-makefs')
265 conf.set_quoted('SYSTEMD_PULL_PATH', libexecdir / 'systemd-pull')
266 conf.set_quoted('SYSTEMD_SHUTDOWN_BINARY_PATH', libexecdir / 'systemd-shutdown')
267 conf.set_quoted('SYSTEMD_TEST_DATA', testdata_dir)
268 conf.set_quoted('SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH', bindir / 'systemd-tty-ask-password-agent')
269 conf.set_quoted('SYSTEMD_UPDATE_HELPER_PATH', libexecdir / 'systemd-update-helper')
270 conf.set_quoted('SYSTEMD_USERWORK_PATH', libexecdir / 'systemd-userwork')
271 conf.set_quoted('SYSTEMD_VERITYSETUP_PATH', libexecdir / 'systemd-veritysetup')
272 conf.set_quoted('SYSTEM_CONFIG_UNIT_DIR', pkgsysconfdir / 'system')
273 conf.set_quoted('SYSTEM_DATA_UNIT_DIR', systemunitdir)
274 conf.set_quoted('SYSTEM_ENV_GENERATOR_DIR', systemenvgeneratordir)
275 conf.set_quoted('SYSTEM_GENERATOR_DIR', systemgeneratordir)
276 conf.set_quoted('SYSTEM_PRESET_DIR', systempresetdir)
277 conf.set_quoted('SYSTEM_SHUTDOWN_PATH', systemshutdowndir)
278 conf.set_quoted('SYSTEM_SLEEP_PATH', systemsleepdir)
279 conf.set_quoted('SYSTEM_SYSVINIT_PATH', sysvinit_path)
280 conf.set_quoted('SYSTEM_SYSVRCND_PATH', sysvrcnd_path)
281 conf.set_quoted('SYSUSERS_DIR', sysusersdir)
282 conf.set_quoted('TMPFILES_DIR', tmpfilesdir)
283 conf.set_quoted('USER_TMPFILES_DIR', usertmpfilesdir)
284 conf.set_quoted('UDEVLIBEXECDIR', udevlibexecdir)
285 conf.set_quoted('UDEV_HWDB_DIR', udevhwdbdir)
286 conf.set_quoted('UDEV_RULES_DIR', udevrulesdir)
287 conf.set_quoted('USER_CONFIG_UNIT_DIR', pkgsysconfdir / 'user')
288 conf.set_quoted('USER_DATA_UNIT_DIR', userunitdir)
289 conf.set_quoted('USER_ENV_GENERATOR_DIR', userenvgeneratordir)
290 conf.set_quoted('USER_GENERATOR_DIR', usergeneratordir)
291 conf.set_quoted('USER_KEYRING_PATH', pkgsysconfdir / 'import-pubring.gpg')
292 conf.set_quoted('USER_PRESET_DIR', userpresetdir)
293 conf.set_quoted('VENDOR_KEYRING_PATH', libexecdir / 'import-pubring.gpg')
294
295 conf.set('ANSI_OK_COLOR', 'ANSI_' + get_option('ok-color').underscorify().to_upper())
296 conf.set10('ENABLE_URLIFY', get_option('urlify'))
297 conf.set10('ENABLE_FEXECVE', get_option('fexecve'))
298 conf.set10('MEMORY_ACCOUNTING_DEFAULT', memory_accounting_default)
299 conf.set('STATUS_UNIT_FORMAT_DEFAULT', 'STATUS_UNIT_FORMAT_' + status_unit_format_default.to_upper())
300 conf.set_quoted('STATUS_UNIT_FORMAT_DEFAULT_STR', status_unit_format_default)
301
302 conf.set('DEFAULT_TIMEOUT_SEC', get_option('default-timeout-sec'))
303 conf.set('DEFAULT_USER_TIMEOUT_SEC', get_option('default-user-timeout-sec'))
304 conf.set('UPDATE_HELPER_USER_TIMEOUT_SEC', get_option('update-helper-user-timeout-sec'))
305
306 conf.set10('ENABLE_FIRST_BOOT_FULL_PRESET', get_option('first-boot-full-preset'))
307
308 #####################################################################
309
310 cc = meson.get_compiler('c')
311 userspace_c_args = []
312 userspace_c_ld_args = []
313 meson_build_sh = find_program('tools/meson-build.sh')
314
315 want_tests = get_option('tests')
316 slow_tests = want_tests != 'false' and get_option('slow-tests')
317 fuzz_tests = want_tests != 'false' and get_option('fuzz-tests')
318 install_tests = want_tests != 'false' and get_option('install-tests')
319
320 if add_languages('cpp', native : false, required : fuzzer_build)
321 # Used only for tests
322 cxx = meson.get_compiler('cpp')
323 cxx_cmd = ' '.join(cxx.cmd_array())
324 else
325 cxx_cmd = ''
326 endif
327
328 if want_libfuzzer
329 fuzzing_engine = meson.get_compiler('cpp').find_library('Fuzzer', required : false)
330 if fuzzing_engine.found()
331 userspace_c_args += '-fsanitize-coverage=trace-pc-guard,trace-cmp'
332 elif cc.has_argument('-fsanitize=fuzzer-no-link')
333 userspace_c_args += '-fsanitize=fuzzer-no-link'
334 else
335 error('Looks like neither libFuzzer nor -fsanitize=fuzzer-no-link is supported')
336 endif
337 elif want_ossfuzz
338 fuzzing_engine = meson.get_compiler('cpp').find_library('FuzzingEngine')
339 endif
340
341 # Those generate many false positives, and we do not want to change the code to
342 # avoid them.
343 basic_disabled_warnings = [
344 '-Wno-missing-field-initializers',
345 '-Wno-unused-parameter',
346 '-Wno-nonnull-compare',
347 ]
348
349 possible_common_cc_flags = [
350 '-Warray-bounds', # clang
351 '-Warray-bounds=2',
352 '-Wdate-time',
353 '-Wendif-labels',
354 '-Werror=format=2',
355 '-Werror=format-signedness',
356 '-Werror=implicit-function-declaration',
357 '-Werror=implicit-int',
358 '-Werror=incompatible-pointer-types',
359 '-Werror=int-conversion',
360 '-Werror=missing-declarations',
361 '-Werror=missing-prototypes',
362 '-Werror=overflow',
363 '-Werror=override-init',
364 '-Werror=return-type',
365 '-Werror=shift-count-overflow',
366 '-Werror=shift-overflow=2',
367 '-Werror=strict-flex-arrays',
368 '-Werror=undef',
369 '-Wfloat-equal',
370 # gperf prevents us from enabling this because it does not emit fallthrough
371 # attribute with clang.
372 #'-Wimplicit-fallthrough',
373 '-Wimplicit-fallthrough=5',
374 '-Winit-self',
375 '-Wlogical-op',
376 '-Wmissing-include-dirs',
377 '-Wmissing-noreturn',
378 '-Wnested-externs',
379 '-Wold-style-definition',
380 '-Wpointer-arith',
381 '-Wredundant-decls',
382 '-Wshadow',
383 '-Wstrict-aliasing=2',
384 '-Wstrict-prototypes',
385 '-Wsuggest-attribute=noreturn',
386 '-Wunused-function',
387 '-Wwrite-strings',
388 '-Wzero-length-bounds',
389
390 # negative arguments are correctly detected starting with meson 0.46.
391 '-Wno-error=#warnings', # clang
392 '-Wno-string-plus-int', # clang
393
394 '-fdiagnostics-show-option',
395 '-fno-common',
396 '-fstack-protector',
397 '-fstack-protector-strong',
398 '-fstrict-flex-arrays',
399 '--param=ssp-buffer-size=4',
400 ]
401
402 possible_common_link_flags = [
403 '-fstack-protector',
404 ]
405
406 c_args = get_option('c_args')
407
408 # Our json library does not support -ffinite-math-only, which is enabled by -Ofast or -ffast-math.
409 if (('-Ofast' in c_args or '-ffast-math' in c_args or '-ffinite-math-only' in c_args) and '-fno-finite-math-only' not in c_args)
410 error('-Ofast, -ffast-math, or -ffinite-math-only is specified in c_args.')
411 endif
412
413 # Disable -Wmaybe-uninitialized when compiling with -Os/-O1/-O3/etc. There are
414 # too many false positives with gcc >= 8. Effectively, we only test with -O0
415 # and -O2; this should be enough to catch most important cases without too much
416 # busywork. See https://github.com/systemd/systemd/pull/19226.
417 if cc.get_id() == 'gcc' and (not '02'.contains(get_option('optimization')) or
418 cc.version().version_compare('<10') or
419 '-Os' in c_args or
420 '-O1' in c_args or
421 '-O3' in c_args or
422 '-Og' in c_args)
423 possible_common_cc_flags += '-Wno-maybe-uninitialized'
424 endif
425
426 # Disable -Wno-unused-result with gcc, see
427 # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425.
428 if cc.get_id() == 'gcc'
429 possible_common_cc_flags += '-Wno-unused-result'
430 endif
431
432 # --as-needed and --no-undefined are provided by meson by default,
433 # run 'meson configure' to see what is enabled
434 possible_link_flags = [
435 '-Wl,--fatal-warnings',
436 '-Wl,-z,now',
437 '-Wl,-z,relro',
438 ]
439
440 if get_option('b_sanitize') == 'none'
441 possible_link_flags += '-Wl,--warn-common'
442 endif
443
444 if cc.get_id() == 'clang'
445 possible_common_cc_flags += [
446 '-Wno-typedef-redefinition',
447 '-Wno-gnu-variable-sized-type-not-at-end',
448 ]
449 endif
450
451 if get_option('mode') == 'release'
452 # We could enable 'pattern' for developer mode, but that can interfere with
453 # valgrind and sanitizer builds. Also, clang does not zero-initialize unions,
454 # breaking some of our code (https://reviews.llvm.org/D68115).
455 possible_common_cc_flags += '-ftrivial-auto-var-init=zero'
456 endif
457
458 possible_cc_flags = [
459 '-fno-strict-aliasing',
460 '-fstrict-flex-arrays=1',
461 '-fvisibility=hidden',
462 ]
463
464 if get_option('buildtype') != 'debug'
465 possible_cc_flags += [
466 '-ffunction-sections',
467 '-fdata-sections',
468 ]
469
470 possible_link_flags += '-Wl,--gc-sections'
471 endif
472
473 if get_option('mode') == 'developer'
474 possible_cc_flags += '-fno-omit-frame-pointer'
475 endif
476
477 add_project_arguments(
478 cc.get_supported_arguments(
479 basic_disabled_warnings,
480 possible_common_cc_flags
481 ),
482 language : 'c')
483
484 add_project_link_arguments(
485 cc.get_supported_link_arguments(possible_common_link_flags),
486 language : 'c')
487
488 userspace_c_args += cc.get_supported_arguments(possible_cc_flags)
489 userspace_c_ld_args += cc.get_supported_link_arguments(possible_link_flags)
490
491 have = cc.has_argument('-Wzero-length-bounds')
492 conf.set10('HAVE_ZERO_LENGTH_BOUNDS', have)
493
494 if cc.compiles('''
495 #include <time.h>
496 #include <inttypes.h>
497 typedef uint64_t usec_t;
498 usec_t now(clockid_t clock);
499 int main(void) {
500 struct timespec now;
501 return 0;
502 }
503 ''', args: '-Werror=shadow', name : '-Werror=shadow with local shadowing')
504 add_project_arguments('-Werror=shadow', language : 'c')
505 endif
506
507 if cxx_cmd != ''
508 add_project_arguments(cxx.get_supported_arguments(basic_disabled_warnings), language : 'cpp')
509 endif
510
511 cpp = ' '.join(cc.cmd_array() + get_option('c_args')) + ' -E'
512
513 has_wstringop_truncation = cc.has_argument('-Wstringop-truncation')
514
515 #####################################################################
516 # compilation result tests
517
518 conf.set('_GNU_SOURCE', 1)
519 conf.set('__SANE_USERSPACE_TYPES__', true)
520 conf.set10('HAVE_WSTRINGOP_TRUNCATION', has_wstringop_truncation)
521
522 conf.set('SIZEOF_DEV_T', cc.sizeof('dev_t', prefix : '#include <sys/types.h>'))
523 conf.set('SIZEOF_INO_T', cc.sizeof('ino_t', prefix : '#include <sys/types.h>'))
524 conf.set('SIZEOF_RLIM_T', cc.sizeof('rlim_t', prefix : '#include <sys/resource.h>'))
525 conf.set('SIZEOF_TIME_T', cc.sizeof('time_t', prefix : '#include <sys/time.h>'))
526 conf.set('SIZEOF_TIMEX_MEMBER', cc.sizeof('typeof(((struct timex *)0)->freq)', prefix : '#include <sys/timex.h>'))
527
528 long_max = cc.compute_int(
529 'LONG_MAX',
530 prefix : '#include <limits.h>',
531 guess : 0x7FFFFFFFFFFFFFFF,
532 high : 0x7FFFFFFFFFFFFFFF)
533 assert(long_max > 100000)
534 conf.set_quoted('LONG_MAX_STR', '@0@'.format(long_max))
535
536 decl_headers = '''
537 #include <dirent.h>
538 #include <uchar.h>
539 #include <sys/mount.h>
540 #include <sys/stat.h>
541 '''
542
543 foreach decl : ['char16_t',
544 'char32_t',
545 'struct mount_attr',
546 'struct statx',
547 'struct dirent64',
548 ]
549
550 # We get -1 if the size cannot be determined
551 have = cc.sizeof(decl, prefix : decl_headers, args : '-D_GNU_SOURCE') > 0
552
553 if decl == 'struct mount_attr'
554 if have
555 want_linux_fs_h = false
556 else
557 have = cc.sizeof(decl,
558 prefix : decl_headers + '#include <linux/fs.h>',
559 args : '-D_GNU_SOURCE') > 0
560 want_linux_fs_h = have
561 endif
562 endif
563
564 if decl == 'struct statx'
565 if have
566 want_linux_stat_h = false
567 else
568 have = cc.sizeof(decl,
569 prefix : decl_headers + '#include <linux/stat.h>',
570 args : '-D_GNU_SOURCE') > 0
571 want_linux_stat_h = have
572 endif
573 endif
574
575 conf.set10('HAVE_' + decl.underscorify().to_upper(), have)
576 endforeach
577
578 conf.set10('WANT_LINUX_STAT_H', want_linux_stat_h)
579 conf.set10('WANT_LINUX_FS_H', want_linux_fs_h)
580
581 foreach ident : ['secure_getenv', '__secure_getenv']
582 conf.set10('HAVE_' + ident.to_upper(), cc.has_function(ident))
583 endforeach
584
585 foreach ident : [
586 ['memfd_create', '''#include <sys/mman.h>'''],
587 ['gettid', '''#include <sys/types.h>
588 #include <unistd.h>'''],
589 ['fchmodat2', '''#include <stdlib.h>
590 #include <fcntl.h>'''], # no known header declares fchmodat2
591 ['pivot_root', '''#include <stdlib.h>
592 #include <unistd.h>'''], # no known header declares pivot_root
593 ['ioprio_get', '''#include <sched.h>'''], # no known header declares ioprio_get
594 ['ioprio_set', '''#include <sched.h>'''], # no known header declares ioprio_set
595 ['name_to_handle_at', '''#include <sys/types.h>
596 #include <sys/stat.h>
597 #include <fcntl.h>'''],
598 ['setns', '''#include <sched.h>'''],
599 ['renameat2', '''#include <stdio.h>
600 #include <fcntl.h>'''],
601 ['kcmp', '''#include <linux/kcmp.h>'''],
602 ['keyctl', '''#include <sys/types.h>
603 #include <keyutils.h>'''],
604 ['copy_file_range', '''#include <sys/syscall.h>
605 #include <unistd.h>'''],
606 ['bpf', '''#include <sys/syscall.h>
607 #include <unistd.h>'''],
608 ['statx', '''#include <sys/types.h>
609 #include <sys/stat.h>
610 #include <unistd.h>'''],
611 ['explicit_bzero' , '''#include <string.h>'''],
612 ['reallocarray', '''#include <stdlib.h>'''],
613 ['set_mempolicy', '''#include <stdlib.h>
614 #include <unistd.h>'''],
615 ['get_mempolicy', '''#include <stdlib.h>
616 #include <unistd.h>'''],
617 ['pidfd_send_signal', '''#include <stdlib.h>
618 #include <unistd.h>
619 #include <signal.h>
620 #include <sys/wait.h>'''],
621 ['pidfd_open', '''#include <stdlib.h>
622 #include <unistd.h>
623 #include <signal.h>
624 #include <sys/wait.h>'''],
625 ['rt_sigqueueinfo', '''#include <stdlib.h>
626 #include <unistd.h>
627 #include <signal.h>
628 #include <sys/wait.h>'''],
629 ['rt_tgsigqueueinfo', '''#include <stdlib.h>
630 #include <unistd.h>
631 #include <signal.h>
632 #include <sys/wait.h>'''],
633 ['mallinfo', '''#include <malloc.h>'''],
634 ['mallinfo2', '''#include <malloc.h>'''],
635 ['execveat', '''#include <unistd.h>'''],
636 ['close_range', '''#include <unistd.h>'''],
637 ['epoll_pwait2', '''#include <sys/epoll.h>'''],
638 ['mount_setattr', '''#include <sys/mount.h>'''],
639 ['move_mount', '''#include <sys/mount.h>'''],
640 ['open_tree', '''#include <sys/mount.h>'''],
641 ['fsopen', '''#include <sys/mount.h>'''],
642 ['fsconfig', '''#include <sys/mount.h>'''],
643 ['fsmount', '''#include <sys/mount.h>'''],
644 ['getdents64', '''#include <dirent.h>'''],
645 ['pidfd_spawn', '''#include <spawn.h>'''],
646 ]
647
648 have = cc.has_function(ident[0], prefix : ident[1], args : '-D_GNU_SOURCE')
649 conf.set10('HAVE_' + ident[0].to_upper(), have)
650 endforeach
651
652 if cc.has_function('getrandom', prefix : '''#include <sys/random.h>''', args : '-D_GNU_SOURCE')
653 conf.set10('USE_SYS_RANDOM_H', true)
654 conf.set10('HAVE_GETRANDOM', true)
655 else
656 have = cc.has_function('getrandom', prefix : '''#include <linux/random.h>''')
657 conf.set10('USE_SYS_RANDOM_H', false)
658 conf.set10('HAVE_GETRANDOM', have)
659 endif
660
661 #####################################################################
662
663 sh = find_program('sh')
664 echo = find_program('echo')
665 sed = find_program('sed')
666 awk = find_program('awk')
667 stat = find_program('stat')
668 ln = find_program('ln')
669 git = find_program('git', required : false)
670 env = find_program('env')
671 rsync = find_program('rsync', required : false)
672 diff = find_program('diff')
673 find = find_program('find')
674
675 ln_s = ln.full_path() + ' -frsT -- "${DESTDIR:-}@0@" "${DESTDIR:-}@1@"'
676
677 # If -Dxxx-path option is found, use that. Otherwise, check in $PATH,
678 # /usr/sbin, /sbin, and fall back to the default from middle column.
679 progs = [['quotaon', '/usr/sbin/quotaon' ],
680 ['quotacheck', '/usr/sbin/quotacheck' ],
681 ['kmod', '/usr/bin/kmod' ],
682 ['kexec', '/usr/sbin/kexec' ],
683 ['sulogin', '/usr/sbin/sulogin' ],
684 ['mount', '/usr/bin/mount', 'MOUNT_PATH'],
685 ['umount', '/usr/bin/umount', 'UMOUNT_PATH'],
686 ['loadkeys', '/usr/bin/loadkeys', 'KBD_LOADKEYS'],
687 ['setfont', '/usr/bin/setfont', 'KBD_SETFONT'],
688 ['nologin', '/usr/sbin/nologin', ],
689 ]
690 foreach prog : progs
691 path = get_option(prog[0] + '-path')
692 if path != ''
693 message('Using @1@ for @0@'.format(prog[0], path))
694 else
695 exe = find_program(prog[0],
696 '/usr/sbin/' + prog[0],
697 '/sbin/' + prog[0],
698 required: false)
699 path = exe.found() ? exe.full_path() : prog[1]
700 endif
701 name = prog.length() > 2 ? prog[2] : prog[0].to_upper()
702 conf.set_quoted(name, path)
703 endforeach
704
705 if run_command(ln, '--relative', '--help', check : false).returncode() != 0
706 error('ln does not support --relative (added in coreutils 8.16)')
707 endif
708
709 #####################################################################
710
711 gperf = find_program('gperf')
712
713 gperf_test_format = '''
714 #include <string.h>
715 const char * in_word_set(const char *, @0@);
716 @1@
717 '''
718 gperf_snippet = run_command(sh, '-c', 'echo foo,bar | "$1" -L ANSI-C', '_', gperf,
719 check : true)
720 gperf_test = gperf_test_format.format('size_t', gperf_snippet.stdout())
721 if cc.compiles(gperf_test)
722 gperf_len_type = 'size_t'
723 else
724 gperf_test = gperf_test_format.format('unsigned', gperf_snippet.stdout())
725 if cc.compiles(gperf_test)
726 gperf_len_type = 'unsigned'
727 else
728 error('unable to determine gperf len type')
729 endif
730 endif
731 message('gperf len type is @0@'.format(gperf_len_type))
732 conf.set('GPERF_LEN_TYPE', gperf_len_type,
733 description : 'The type of gperf "len" parameter')
734
735 #####################################################################
736
737 if not cc.has_header('sys/capability.h')
738 error('POSIX caps headers not found')
739 endif
740 foreach header : ['crypt.h',
741 'linux/ioprio.h',
742 'linux/memfd.h',
743 'linux/time_types.h',
744 'linux/vm_sockets.h',
745 'sys/auxv.h',
746 'sys/sdt.h',
747 'threads.h',
748 'valgrind/memcheck.h',
749 'valgrind/valgrind.h',
750 ]
751
752 conf.set10('HAVE_' + header.underscorify().to_upper(),
753 cc.has_header(header))
754 endforeach
755
756 #####################################################################
757
758 fallback_hostname = get_option('fallback-hostname')
759 if fallback_hostname == '' or fallback_hostname[0] == '.' or fallback_hostname[0] == '-'
760 error('Invalid fallback-hostname configuration')
761 # A more extensive test is done in test-hostname-util. Let's catch
762 # the most obvious errors here so we don't fail with an assert later.
763 endif
764 conf.set_quoted('FALLBACK_HOSTNAME', fallback_hostname)
765
766 extra_net_naming_schemes = []
767 extra_net_naming_map = []
768 foreach scheme: get_option('extra-net-naming-schemes').split(',')
769 if scheme != ''
770 name = scheme.split('=')[0]
771 value = scheme.split('=')[1]
772 NAME = name.underscorify().to_upper()
773 VALUE = []
774 foreach field: value.split('+')
775 VALUE += 'NAMING_' + field.underscorify().to_upper()
776 endforeach
777 extra_net_naming_schemes += 'NAMING_@0@ = @1@,'.format(NAME, '|'.join(VALUE))
778 extra_net_naming_map += '{ "@0@", NAMING_@1@ },'.format(name, NAME)
779 endif
780 endforeach
781 conf.set('EXTRA_NET_NAMING_SCHEMES', ' '.join(extra_net_naming_schemes))
782 conf.set('EXTRA_NET_NAMING_MAP', ' '.join(extra_net_naming_map))
783
784 default_net_naming_scheme = get_option('default-net-naming-scheme')
785 conf.set_quoted('DEFAULT_NET_NAMING_SCHEME', default_net_naming_scheme,
786 description : 'Default naming scheme as a string')
787 if default_net_naming_scheme != 'latest'
788 conf.set('_DEFAULT_NET_NAMING_SCHEME',
789 'NAMING_' + default_net_naming_scheme.underscorify().to_upper(),
790 description : 'Default naming scheme as a constant')
791 endif
792
793 time_epoch = get_option('time-epoch')
794 if time_epoch <= 0
795 time_epoch = run_command(sh, '-c', 'echo "$SOURCE_DATE_EPOCH"', check : true).stdout().strip()
796 if time_epoch == '' and git.found() and fs.is_dir('.git')
797 # If we're in a git repository, use the creation time of the latest git tag.
798 latest_tag = run_command(git, 'describe', '--abbrev=0', '--tags',
799 check : false)
800 if latest_tag.returncode() == 0
801 time_epoch = run_command(
802 git, 'log', '--no-show-signature', '-1', '--format=%at',
803 latest_tag.stdout().strip(),
804 check : false).stdout()
805 endif
806 endif
807 if time_epoch == ''
808 NEWS = files('NEWS')
809 time_epoch = run_command(stat, '-c', '%Y', NEWS,
810 check : true).stdout()
811 endif
812 time_epoch = time_epoch.strip().to_int()
813 endif
814 conf.set('TIME_EPOCH', time_epoch)
815
816 conf.set('CLOCK_VALID_RANGE_USEC_MAX', get_option('clock-valid-range-usec-max'))
817
818 default_user_shell = get_option('default-user-shell')
819 conf.set_quoted('DEFAULT_USER_SHELL', default_user_shell)
820 conf.set_quoted('DEFAULT_USER_SHELL_NAME', fs.name(default_user_shell))
821
822 foreach tuple : [['system-alloc-uid-min', 'SYS_UID_MIN', 1], # Also see login.defs(5).
823 ['system-uid-max', 'SYS_UID_MAX', 999],
824 ['system-alloc-gid-min', 'SYS_GID_MIN', 1],
825 ['system-gid-max', 'SYS_GID_MAX', 999]]
826 v = get_option(tuple[0])
827 if v <= 0
828 v = run_command(
829 awk,
830 '/^\s*@0@\s+/ { uid=$2 } END { print uid }'.format(tuple[1]),
831 '/etc/login.defs',
832 check : false).stdout().strip()
833 if v == ''
834 v = tuple[2]
835 else
836 v = v.to_int()
837 endif
838 endif
839 conf.set(tuple[0].underscorify().to_upper(), v)
840 endforeach
841 if conf.get('SYSTEM_ALLOC_UID_MIN') >= conf.get('SYSTEM_UID_MAX')
842 error('Invalid uid allocation range')
843 endif
844 if conf.get('SYSTEM_ALLOC_GID_MIN') >= conf.get('SYSTEM_GID_MAX')
845 error('Invalid gid allocation range')
846 endif
847
848 dynamic_uid_min = get_option('dynamic-uid-min')
849 dynamic_uid_max = get_option('dynamic-uid-max')
850 conf.set('DYNAMIC_UID_MIN', dynamic_uid_min)
851 conf.set('DYNAMIC_UID_MAX', dynamic_uid_max)
852
853 container_uid_base_min = get_option('container-uid-base-min')
854 container_uid_base_max = get_option('container-uid-base-max')
855 conf.set('CONTAINER_UID_BASE_MIN', container_uid_base_min)
856 conf.set('CONTAINER_UID_BASE_MAX', container_uid_base_max)
857
858 nobody_user = get_option('nobody-user')
859 nobody_group = get_option('nobody-group')
860
861 if not meson.is_cross_build()
862 getent_result = run_command('getent', 'passwd', '65534', check : false)
863 if getent_result.returncode() == 0
864 name = getent_result.stdout().split(':')[0]
865 if name != nobody_user
866 warning('\n' +
867 'The local user with the UID 65534 does not match the configured user name "@0@" of the nobody user (its name is @1@).\n'.format(nobody_user, name) +
868 'Your build will result in an user table setup that is incompatible with the local system.')
869 endif
870 endif
871 id_result = run_command('id', '-u', nobody_user, check : false)
872 if id_result.returncode() == 0
873 id = id_result.stdout().strip().to_int()
874 if id != 65534
875 warning('\n' +
876 'The local user with the configured user name "@0@" of the nobody user does not have UID 65534 (it has @1@).\n'.format(nobody_user, id) +
877 'Your build will result in an user table setup that is incompatible with the local system.')
878 endif
879 endif
880
881 getent_result = run_command('getent', 'group', '65534', check : false)
882 if getent_result.returncode() == 0
883 name = getent_result.stdout().split(':')[0]
884 if name != nobody_group
885 warning('\n' +
886 'The local group with the GID 65534 does not match the configured group name "@0@" of the nobody group (its name is @1@).\n'.format(nobody_group, name) +
887 'Your build will result in an group table setup that is incompatible with the local system.')
888 endif
889 endif
890 id_result = run_command('id', '-g', nobody_group, check : false)
891 if id_result.returncode() == 0
892 id = id_result.stdout().strip().to_int()
893 if id != 65534
894 warning('\n' +
895 'The local group with the configured group name "@0@" of the nobody group does not have GID 65534 (it has @1@).\n'.format(nobody_group, id) +
896 'Your build will result in an group table setup that is incompatible with the local system.')
897 endif
898 endif
899 endif
900 if nobody_user != nobody_group and not (nobody_user == 'nobody' and nobody_group == 'nogroup')
901 warning('\n' +
902 'The configured user name "@0@" and group name "@1@" of the nobody user/group are not equivalent.\n'.format(nobody_user, nobody_group) +
903 'Please re-check that both "nobody-user" and "nobody-group" options are correctly set.')
904 endif
905
906 conf.set_quoted('NOBODY_USER_NAME', nobody_user)
907 conf.set_quoted('NOBODY_GROUP_NAME', nobody_group)
908
909 static_ugids = []
910 foreach option : ['adm-gid',
911 'audio-gid',
912 'cdrom-gid',
913 'dialout-gid',
914 'disk-gid',
915 'input-gid',
916 'kmem-gid',
917 'kvm-gid',
918 'lp-gid',
919 'render-gid',
920 'sgx-gid',
921 'tape-gid',
922 'tty-gid',
923 'users-gid',
924 'utmp-gid',
925 'video-gid',
926 'wheel-gid',
927 'systemd-journal-gid',
928 'systemd-network-uid',
929 'systemd-resolve-uid',
930 'systemd-timesync-uid']
931 name = option.underscorify().to_upper()
932 val = get_option(option)
933
934 # Ensure provided GID argument is numeric, otherwise fall back to default assignment
935 conf.set(name, val > 0 ? val : '-')
936 if val > 0
937 static_ugids += '@0@:@1@'.format(option, val)
938 endif
939 endforeach
940
941 conf.set10('ENABLE_ADM_GROUP', get_option('adm-group'))
942 conf.set10('ENABLE_WHEEL_GROUP', get_option('wheel-group'))
943
944 dev_kvm_mode = get_option('dev-kvm-mode')
945 conf.set_quoted('DEV_KVM_MODE', dev_kvm_mode) # FIXME: convert to 0o… notation
946 conf.set10('DEV_KVM_UACCESS', dev_kvm_mode != '0666')
947 group_render_mode = get_option('group-render-mode')
948 conf.set_quoted('GROUP_RENDER_MODE', group_render_mode)
949 conf.set10('GROUP_RENDER_UACCESS', group_render_mode != '0666')
950
951 kill_user_processes = get_option('default-kill-user-processes')
952 conf.set10('KILL_USER_PROCESSES', kill_user_processes)
953
954 dns_servers = get_option('dns-servers')
955 conf.set_quoted('DNS_SERVERS', dns_servers)
956
957 ntp_servers = get_option('ntp-servers')
958 conf.set_quoted('NTP_SERVERS', ntp_servers)
959
960 default_locale = get_option('default-locale')
961 conf.set_quoted('SYSTEMD_DEFAULT_LOCALE', default_locale)
962
963 nspawn_locale = get_option('nspawn-locale')
964 conf.set_quoted('SYSTEMD_NSPAWN_LOCALE', nspawn_locale)
965
966 default_keymap = get_option('default-keymap')
967 if default_keymap == ''
968 # We canonicalize empty keymap to '@kernel', as it makes the default value
969 # in the factory provided /etc/vconsole.conf more obvious.
970 default_keymap = '@kernel'
971 endif
972 conf.set_quoted('SYSTEMD_DEFAULT_KEYMAP', default_keymap)
973
974 localegen_path = get_option('localegen-path')
975 if localegen_path != ''
976 conf.set_quoted('LOCALEGEN_PATH', localegen_path)
977 endif
978 conf.set10('HAVE_LOCALEGEN', localegen_path != '')
979
980 conf.set_quoted('GETTEXT_PACKAGE', meson.project_name())
981
982 service_watchdog = get_option('service-watchdog')
983 watchdog_value = service_watchdog == '' ? '' : 'WatchdogSec=' + service_watchdog
984 conf.set_quoted('SERVICE_WATCHDOG', watchdog_value)
985
986 conf.set_quoted('SUSHELL', get_option('debug-shell'))
987 conf.set_quoted('DEBUGTTY', get_option('debug-tty'))
988
989 enable_debug_hashmap = false
990 enable_debug_mmap_cache = false
991 enable_debug_siphash = false
992 foreach name : get_option('debug-extra')
993 if name == 'hashmap'
994 enable_debug_hashmap = true
995 elif name == 'mmap-cache'
996 enable_debug_mmap_cache = true
997 elif name == 'siphash'
998 enable_debug_siphash = true
999 else
1000 message('unknown debug option "@0@", ignoring'.format(name))
1001 endif
1002 endforeach
1003 conf.set10('ENABLE_DEBUG_HASHMAP', enable_debug_hashmap)
1004 conf.set10('ENABLE_DEBUG_MMAP_CACHE', enable_debug_mmap_cache)
1005 conf.set10('ENABLE_DEBUG_SIPHASH', enable_debug_siphash)
1006 conf.set10('LOG_TRACE', get_option('log-trace'))
1007
1008 default_user_path = get_option('user-path')
1009 if default_user_path != ''
1010 conf.set_quoted('DEFAULT_USER_PATH', default_user_path)
1011 endif
1012
1013 #####################################################################
1014
1015 threads = dependency('threads')
1016 librt = cc.find_library('rt')
1017 libm = cc.find_library('m')
1018 libdl = cc.find_library('dl')
1019 libcrypt = dependency('libcrypt', 'libxcrypt', required : false)
1020 if not libcrypt.found()
1021 # fallback to use find_library() if libcrypt is provided by glibc, e.g. for LibreELEC.
1022 libcrypt = cc.find_library('crypt')
1023 endif
1024 libcap = dependency('libcap')
1025
1026 # On some architectures, libatomic is required. But on some installations,
1027 # it is found, but actual linking fails. So let's try to use it opportunistically.
1028 # If it is installed, but not needed, it will be dropped because of --as-needed.
1029 if cc.links('''int main(int argc, char **argv) { return 0; }''',
1030 args : '-latomic',
1031 name : 'libatomic')
1032 libatomic = declare_dependency(link_args : '-latomic')
1033 else
1034 libatomic = []
1035 endif
1036
1037 crypt_header = conf.get('HAVE_CRYPT_H') == 1 ? '''#include <crypt.h>''' : '''#include <unistd.h>'''
1038 foreach ident : [
1039 ['crypt_ra', crypt_header],
1040 ['crypt_preferred_method', crypt_header],
1041 ['crypt_gensalt_ra', crypt_header]]
1042
1043 have = cc.has_function(ident[0], prefix : ident[1], args : '-D_GNU_SOURCE',
1044 dependencies : libcrypt)
1045 conf.set10('HAVE_' + ident[0].to_upper(), have)
1046 endforeach
1047
1048 bpf_framework = get_option('bpf-framework')
1049 bpf_compiler = get_option('bpf-compiler')
1050 libbpf = dependency('libbpf',
1051 required : bpf_framework,
1052 version : bpf_compiler == 'gcc' ? '>= 1.0.0' : '>= 0.1.0')
1053 conf.set10('HAVE_LIBBPF', libbpf.found())
1054
1055 if not libbpf.found()
1056 conf.set10('BPF_FRAMEWORK', false)
1057 else
1058 clang_found = false
1059 clang_supports_bpf = false
1060 bpf_gcc_found = false
1061 bpftool_strip = false
1062 deps_found = false
1063
1064 if bpf_compiler == 'clang'
1065 # Support 'versioned' clang/llvm-strip binaries, as seen on Debian/Ubuntu
1066 # (like clang-10/llvm-strip-10)
1067 if meson.is_cross_build() or cc.get_id() != 'clang' or cc.cmd_array()[0].contains('afl-clang') or cc.cmd_array()[0].contains('hfuzz-clang')
1068 r = find_program('clang',
1069 required : bpf_framework,
1070 version : '>= 10.0.0')
1071 clang_found = r.found()
1072 if clang_found
1073 clang = r.full_path()
1074 endif
1075 else
1076 clang_found = true
1077 clang = cc.cmd_array()
1078 endif
1079
1080 if clang_found
1081 # Check if 'clang -target bpf' is supported.
1082 clang_supports_bpf = run_command(clang, '-target', 'bpf', '--print-supported-cpus', check : false).returncode() == 0
1083 endif
1084 elif bpf_compiler == 'gcc'
1085 bpf_gcc = find_program('bpf-gcc',
1086 'bpf-none-gcc',
1087 required : true,
1088 version : '>= 13.1.0')
1089 bpf_gcc_found = bpf_gcc.found()
1090 endif
1091
1092 if clang_supports_bpf or bpf_gcc_found
1093 # Debian installs this in /usr/sbin/ which is not in $PATH.
1094 # We check for 'bpftool' first, honouring $PATH, and in /usr/sbin/ for Debian.
1095 # We use 'bpftool gen object' subcommand for bpftool strip, it was added by d80b2fcbe0a023619e0fc73112f2a02c2662f6ab (v5.13).
1096 bpftool = find_program('bpftool',
1097 '/usr/sbin/bpftool',
1098 required : bpf_framework.enabled() and bpf_compiler == 'gcc',
1099 version : bpf_compiler == 'gcc' ? '>= 7.0.0' : '>= 5.13.0')
1100
1101 if bpftool.found()
1102 bpftool_strip = true
1103 deps_found = true
1104 elif bpf_compiler == 'clang'
1105 # We require the 'bpftool gen skeleton' subcommand, it was added by 985ead416df39d6fe8e89580cc1db6aa273e0175 (v5.6).
1106 bpftool = find_program('bpftool',
1107 '/usr/sbin/bpftool',
1108 required : bpf_framework,
1109 version : '>= 5.6.0')
1110 endif
1111
1112 # We use `llvm-strip` as a fallback if `bpftool gen object` strip support is not available.
1113 if not bpftool_strip and bpftool.found() and clang_supports_bpf
1114 if not meson.is_cross_build()
1115 llvm_strip_bin = run_command(clang, '--print-prog-name', 'llvm-strip',
1116 check : true).stdout().strip()
1117 else
1118 llvm_strip_bin = 'llvm-strip'
1119 endif
1120 llvm_strip = find_program(llvm_strip_bin,
1121 required : bpf_framework,
1122 version : '>= 10.0.0')
1123 deps_found = llvm_strip.found()
1124 endif
1125 endif
1126
1127 # Can build BPF program from source code in restricted C
1128 conf.set10('BPF_FRAMEWORK', deps_found)
1129 endif
1130
1131 libmount = dependency('mount',
1132 version : fuzzer_build ? '>= 0' : '>= 2.30')
1133
1134 libfdisk = dependency('fdisk',
1135 version : '>= 2.32',
1136 disabler : true,
1137 required : get_option('fdisk'))
1138 conf.set10('HAVE_LIBFDISK', libfdisk.found())
1139
1140 # This prefers pwquality if both are enabled or auto.
1141 feature = get_option('pwquality').disable_auto_if(get_option('passwdqc').enabled())
1142 libpwquality = dependency('pwquality',
1143 version : '>= 1.4.1',
1144 required : feature)
1145 have = libpwquality.found()
1146 if not have
1147 # libpwquality is used for both features for simplicity
1148 libpwquality = dependency('passwdqc',
1149 required : get_option('passwdqc'))
1150 endif
1151 conf.set10('HAVE_PWQUALITY', have)
1152 conf.set10('HAVE_PASSWDQC', not have and libpwquality.found())
1153
1154 libseccomp = dependency('libseccomp',
1155 version : '>= 2.3.1',
1156 required : get_option('seccomp'))
1157 conf.set10('HAVE_SECCOMP', libseccomp.found())
1158
1159 libselinux = dependency('libselinux',
1160 version : '>= 2.1.9',
1161 required : get_option('selinux'))
1162 conf.set10('HAVE_SELINUX', libselinux.found())
1163
1164 libapparmor = dependency('libapparmor',
1165 version : '>= 2.13',
1166 required : get_option('apparmor'))
1167 conf.set10('HAVE_APPARMOR', libapparmor.found())
1168
1169 have = get_option('smack') and get_option('smack-run-label') != ''
1170 conf.set10('HAVE_SMACK_RUN_LABEL', have)
1171 if have
1172 conf.set_quoted('SMACK_RUN_LABEL', get_option('smack-run-label'))
1173 endif
1174
1175 have = get_option('smack') and get_option('smack-default-process-label') != ''
1176 if have
1177 conf.set_quoted('SMACK_DEFAULT_PROCESS_LABEL', get_option('smack-default-process-label'))
1178 endif
1179
1180 feature = get_option('polkit')
1181 libpolkit = dependency('polkit-gobject-1',
1182 required : feature.disabled() ? feature : false)
1183 install_polkit = feature.allowed()
1184 install_polkit_pkla = libpolkit.found() and libpolkit.version().version_compare('< 0.106')
1185 if install_polkit_pkla
1186 message('Old polkit detected, will install pkla files')
1187 endif
1188 conf.set10('ENABLE_POLKIT', install_polkit)
1189
1190 libacl = dependency('libacl',
1191 required : get_option('acl'))
1192 conf.set10('HAVE_ACL', libacl.found())
1193
1194 libaudit = dependency('audit',
1195 required : get_option('audit'))
1196 conf.set10('HAVE_AUDIT', libaudit.found())
1197
1198 libblkid = dependency('blkid',
1199 required : get_option('blkid'))
1200 conf.set10('HAVE_BLKID', libblkid.found())
1201 conf.set10('HAVE_BLKID_PROBE_SET_HINT',
1202 libblkid.found() and cc.has_function('blkid_probe_set_hint', dependencies : libblkid))
1203
1204 libkmod = dependency('libkmod',
1205 version : '>= 15',
1206 required : get_option('kmod'))
1207 conf.set10('HAVE_KMOD', libkmod.found())
1208
1209 libxenctrl = dependency('xencontrol',
1210 version : '>= 4.9',
1211 required : get_option('xenctrl'))
1212 conf.set10('HAVE_XENCTRL', libxenctrl.found())
1213 libxenctrl_cflags = libxenctrl.partial_dependency(includes: true, compile_args: true)
1214
1215 feature = get_option('pam')
1216 libpam = dependency('pam',
1217 required : feature.disabled() ? feature : false)
1218 if not libpam.found()
1219 # Debian older than bookworm and Ubuntu older than 22.10 do not provide the .pc file.
1220 libpam = cc.find_library('pam', required : feature)
1221 endif
1222 libpam_misc = dependency('pam_misc',
1223 required : feature.disabled() ? feature : false)
1224 if not libpam_misc.found()
1225 libpam_misc = cc.find_library('pam_misc', required : feature)
1226 endif
1227 conf.set10('HAVE_PAM', libpam.found() and libpam_misc.found())
1228
1229 libmicrohttpd = dependency('libmicrohttpd',
1230 version : '>= 0.9.33',
1231 required : get_option('microhttpd'))
1232 conf.set10('HAVE_MICROHTTPD', libmicrohttpd.found())
1233
1234 libcryptsetup = get_option('libcryptsetup')
1235 libcryptsetup_plugins = get_option('libcryptsetup-plugins')
1236 if libcryptsetup_plugins.enabled()
1237 if libcryptsetup.disabled()
1238 error('libcryptsetup-plugins cannot be requested without libcryptsetup')
1239 endif
1240 libcryptsetup = libcryptsetup_plugins
1241 endif
1242
1243 libcryptsetup = dependency('libcryptsetup',
1244 version : libcryptsetup_plugins.enabled() ? '>= 2.4.0' : '>= 2.0.1',
1245 required : libcryptsetup)
1246
1247 have = libcryptsetup.found()
1248 foreach ident : ['crypt_set_metadata_size',
1249 'crypt_activate_by_signed_key',
1250 'crypt_token_max',
1251 'crypt_reencrypt_init_by_passphrase',
1252 'crypt_reencrypt',
1253 'crypt_set_data_offset',
1254 'crypt_set_keyring_to_link',
1255 'crypt_resume_by_volume_key']
1256 have_ident = have and cc.has_function(
1257 ident,
1258 prefix : '#include <libcryptsetup.h>',
1259 dependencies : libcryptsetup)
1260 conf.set10('HAVE_' + ident.to_upper(), have_ident)
1261 endforeach
1262 conf.set10('HAVE_LIBCRYPTSETUP', have)
1263
1264 # TODO: Use has_function(required : libcryptsetup_plugins) with meson >= 1.3.0
1265 if libcryptsetup_plugins.allowed()
1266 have = (cc.has_function(
1267 'crypt_activate_by_token_pin',
1268 prefix : '#include <libcryptsetup.h>',
1269 dependencies : libcryptsetup) and
1270 cc.has_function(
1271 'crypt_token_external_path',
1272 prefix : '#include <libcryptsetup.h>',
1273 dependencies : libcryptsetup))
1274 else
1275 have = false
1276 endif
1277 conf.set10('HAVE_LIBCRYPTSETUP_PLUGINS', have)
1278
1279 libcurl = dependency('libcurl',
1280 version : '>= 7.32.0',
1281 required : get_option('libcurl'))
1282 conf.set10('HAVE_LIBCURL', libcurl.found())
1283 conf.set10('CURL_NO_OLDIES', conf.get('BUILD_MODE_DEVELOPER') == 1)
1284
1285 feature = get_option('libidn2').disable_auto_if(get_option('libidn').enabled())
1286 libidn = dependency('libidn2',
1287 required : feature)
1288 have = libidn.found()
1289 if not have
1290 # libidn is used for both libidn and libidn2 objects
1291 libidn = dependency('libidn',
1292 required : get_option('libidn'))
1293 endif
1294 conf.set10('HAVE_LIBIDN', not have and libidn.found())
1295 conf.set10('HAVE_LIBIDN2', have)
1296
1297 libiptc = dependency('libiptc',
1298 required : get_option('libiptc'))
1299 conf.set10('HAVE_LIBIPTC', libiptc.found())
1300 libiptc_cflags = libiptc.partial_dependency(includes: true, compile_args: true)
1301
1302 libqrencode = dependency('libqrencode',
1303 version : '>= 3',
1304 required : get_option('qrencode'))
1305 conf.set10('HAVE_QRENCODE', libqrencode.found())
1306
1307 feature = get_option('gcrypt')
1308 libgcrypt = dependency('libgcrypt',
1309 required : feature)
1310 libgpg_error = dependency('gpg-error',
1311 required : feature.disabled() ? feature : false)
1312 if not libgpg_error.found()
1313 # CentOS 8 does not provide the .pc file.
1314 libgpg_error = cc.find_library('gpg-error', required : feature)
1315 endif
1316
1317 have = libgcrypt.found() and libgpg_error.found()
1318 if not have
1319 # link to neither of the libs if one is not found
1320 libgcrypt = []
1321 libgpg_error = []
1322 endif
1323 conf.set10('HAVE_GCRYPT', have)
1324
1325 libgnutls = dependency('gnutls',
1326 version : '>= 3.1.4',
1327 required : get_option('gnutls'))
1328 conf.set10('HAVE_GNUTLS', libgnutls.found())
1329
1330 libopenssl = dependency('openssl',
1331 version : '>= 1.1.0',
1332 required : get_option('openssl'))
1333 conf.set10('HAVE_OPENSSL', libopenssl.found())
1334
1335 libp11kit = dependency('p11-kit-1',
1336 version : '>= 0.23.3',
1337 required : get_option('p11kit'))
1338 conf.set10('HAVE_P11KIT', libp11kit.found())
1339 libp11kit_cflags = libp11kit.partial_dependency(includes: true, compile_args: true)
1340
1341 feature = get_option('libfido2').require(
1342 conf.get('HAVE_OPENSSL') == 1,
1343 error_message : 'openssl required')
1344 libfido2 = dependency('libfido2',
1345 required : feature)
1346 conf.set10('HAVE_LIBFIDO2', libfido2.found())
1347
1348 tpm2 = dependency('tss2-esys tss2-rc tss2-mu tss2-tcti-device',
1349 required : get_option('tpm2'))
1350 conf.set10('HAVE_TPM2', tpm2.found())
1351 conf.set10('HAVE_TSS2_ESYS3', tpm2.found() and tpm2.version().version_compare('>= 3.0.0'))
1352
1353 libdw = dependency('libdw',
1354 required : get_option('elfutils'))
1355 conf.set10('HAVE_ELFUTILS', libdw.found())
1356 # New in elfutils 0.177
1357 conf.set10('HAVE_DWELF_ELF_E_MACHINE_STRING',
1358 libdw.found() and cc.has_function('dwelf_elf_e_machine_string', dependencies : libdw))
1359
1360 libz = dependency('zlib',
1361 required : get_option('zlib'))
1362 conf.set10('HAVE_ZLIB', libz.found())
1363
1364 feature = get_option('bzip2')
1365 libbzip2 = dependency('bzip2',
1366 required : feature.disabled() ? feature : false)
1367 if not libbzip2.found()
1368 # Debian and Ubuntu do not provide the .pc file.
1369 libbzip2 = cc.find_library('bz2', required : feature)
1370 endif
1371 conf.set10('HAVE_BZIP2', libbzip2.found())
1372
1373 libxz = dependency('liblzma',
1374 required : get_option('xz'))
1375 conf.set10('HAVE_XZ', libxz.found())
1376 libxz_cflags = libxz.partial_dependency(includes: true, compile_args: true)
1377
1378 liblz4 = dependency('liblz4',
1379 version : '>= 1.3.0',
1380 required : get_option('lz4'))
1381 conf.set10('HAVE_LZ4', liblz4.found())
1382 liblz4_cflags = liblz4.partial_dependency(includes: true, compile_args: true)
1383
1384 libzstd = dependency('libzstd',
1385 version : '>= 1.4.0',
1386 required : get_option('zstd'))
1387 conf.set10('HAVE_ZSTD', libzstd.found())
1388 libzstd_cflags = libzstd.partial_dependency(includes: true, compile_args: true)
1389
1390 conf.set10('HAVE_COMPRESSION', libxz.found() or liblz4.found() or libzstd.found())
1391
1392 compression = get_option('default-compression')
1393 if compression == 'auto'
1394 if libzstd.found()
1395 compression = 'zstd'
1396 elif liblz4.found()
1397 compression = 'lz4'
1398 elif libxz.found()
1399 compression = 'xz'
1400 else
1401 compression = 'none'
1402 endif
1403 elif compression == 'zstd' and not libzstd.found()
1404 error('default-compression=zstd requires zstd')
1405 elif compression == 'lz4' and not liblz4.found()
1406 error('default-compression=lz4 requires lz4')
1407 elif compression == 'xz' and not libxz.found()
1408 error('default-compression=xz requires xz')
1409 endif
1410 conf.set('DEFAULT_COMPRESSION', 'COMPRESSION_@0@'.format(compression.to_upper()))
1411
1412 libarchive = dependency('libarchive',
1413 version : '>= 3.0',
1414 required : get_option('libarchive'))
1415 conf.set10('HAVE_LIBARCHIVE', libarchive.found())
1416
1417 libxkbcommon = dependency('xkbcommon',
1418 version : '>= 0.3.0',
1419 required : get_option('xkbcommon'))
1420 conf.set10('HAVE_XKBCOMMON', libxkbcommon.found())
1421
1422 libpcre2 = dependency('libpcre2-8',
1423 required : get_option('pcre2'))
1424 conf.set10('HAVE_PCRE2', libpcre2.found())
1425
1426 libglib = dependency('glib-2.0',
1427 version : '>= 2.22.0',
1428 required : get_option('glib'))
1429 libgobject = dependency('gobject-2.0',
1430 version : '>= 2.22.0',
1431 required : get_option('glib'))
1432 libgio = dependency('gio-2.0',
1433 required : get_option('glib'))
1434 conf.set10('HAVE_GLIB', libglib.found() and libgobject.found() and libgio.found())
1435
1436 libdbus = dependency('dbus-1',
1437 version : '>= 1.3.2',
1438 required : get_option('dbus'))
1439 conf.set10('HAVE_DBUS', libdbus.found())
1440
1441 dbusdatadir = libdbus.get_variable(pkgconfig: 'datadir', default_value: datadir) / 'dbus-1'
1442
1443 dbuspolicydir = get_option('dbuspolicydir')
1444 if dbuspolicydir == ''
1445 dbuspolicydir = dbusdatadir / 'system.d'
1446 endif
1447
1448 dbussessionservicedir = get_option('dbussessionservicedir')
1449 if dbussessionservicedir == ''
1450 dbussessionservicedir = libdbus.get_variable(pkgconfig: 'session_bus_services_dir', default_value: dbusdatadir / 'services')
1451 endif
1452
1453 dbussystemservicedir = get_option('dbussystemservicedir')
1454 if dbussystemservicedir == ''
1455 dbussystemservicedir = libdbus.get_variable(pkgconfig: 'system_bus_services_dir', default_value: dbusdatadir / 'system-services')
1456 endif
1457
1458 dbus_interfaces_dir = get_option('dbus-interfaces-dir')
1459 if dbus_interfaces_dir == '' or dbus_interfaces_dir == 'yes'
1460 if meson.is_cross_build() and dbus_interfaces_dir != 'yes'
1461 dbus_interfaces_dir = 'no'
1462 warning('Exporting D-Bus interface XML files is disabled during cross build. Pass path or "yes" to force enable.')
1463 else
1464 dbus_interfaces_dir = libdbus.get_variable(pkgconfig: 'interfaces_dir', default_value: dbusdatadir / 'interfaces')
1465 endif
1466 endif
1467
1468 dmi_arches = ['x86', 'x86_64', 'aarch64', 'arm', 'ia64', 'loongarch64', 'mips']
1469 conf.set10('HAVE_DMI', host_machine.cpu_family() in dmi_arches)
1470
1471 # We support one or the other. If gcrypt is available, we assume it's there to
1472 # be used, and use it in preference.
1473 opt = get_option('cryptolib')
1474 if opt == 'openssl' and conf.get('HAVE_OPENSSL') == 0
1475 error('openssl requested as the default cryptolib, but not available')
1476 endif
1477 conf.set10('PREFER_OPENSSL',
1478 opt == 'openssl' or (opt == 'auto' and conf.get('HAVE_OPENSSL') == 1 and conf.get('HAVE_GCRYPT') == 0))
1479 conf.set10('HAVE_OPENSSL_OR_GCRYPT',
1480 conf.get('HAVE_OPENSSL') == 1 or conf.get('HAVE_GCRYPT') == 1)
1481 lib_openssl_or_gcrypt = conf.get('PREFER_OPENSSL') == 1 ? [libopenssl] : [libgcrypt, libgpg_error]
1482
1483 dns_over_tls = get_option('dns-over-tls')
1484 if dns_over_tls != 'false'
1485 if dns_over_tls == 'gnutls' and conf.get('PREFER_OPENSSL') == 1
1486 error('Sorry, -Ddns-over-tls=gnutls is not supported when openssl is used as the cryptolib')
1487 endif
1488
1489 if dns_over_tls == 'gnutls'
1490 have_openssl = false
1491 else
1492 have_openssl = conf.get('HAVE_OPENSSL') == 1
1493 if dns_over_tls == 'openssl' and not have_openssl
1494 error('DNS-over-TLS support was requested with openssl, but dependencies are not available')
1495 endif
1496 endif
1497 if dns_over_tls == 'openssl' or have_openssl
1498 have_gnutls = false
1499 else
1500 have_gnutls = conf.get('HAVE_GNUTLS') == 1 and libgnutls.version().version_compare('>= 3.6.0')
1501 if dns_over_tls != 'auto' and not have_gnutls
1502 str = dns_over_tls == 'gnutls' ? ' with gnutls' : ''
1503 error('DNS-over-TLS support was requested@0@, but dependencies are not available'.format(str))
1504 endif
1505 endif
1506 have = have_gnutls or have_openssl
1507 else
1508 have = false
1509 have_gnutls = false
1510 have_openssl = false
1511 endif
1512 conf.set10('ENABLE_DNS_OVER_TLS', have)
1513 conf.set10('DNS_OVER_TLS_USE_GNUTLS', have_gnutls)
1514 conf.set10('DNS_OVER_TLS_USE_OPENSSL', have_openssl)
1515
1516 default_dns_over_tls = get_option('default-dns-over-tls')
1517 if default_dns_over_tls != 'no' and conf.get('ENABLE_DNS_OVER_TLS') == 0
1518 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.')
1519 default_dns_over_tls = 'no'
1520 endif
1521 conf.set('DEFAULT_DNS_OVER_TLS_MODE',
1522 'DNS_OVER_TLS_' + default_dns_over_tls.underscorify().to_upper())
1523 conf.set_quoted('DEFAULT_DNS_OVER_TLS_MODE_STR', default_dns_over_tls)
1524
1525 default_mdns = get_option('default-mdns')
1526 conf.set('DEFAULT_MDNS_MODE',
1527 'RESOLVE_SUPPORT_' + default_mdns.to_upper())
1528 conf.set_quoted('DEFAULT_MDNS_MODE_STR', default_mdns)
1529
1530 default_llmnr = get_option('default-llmnr')
1531 conf.set('DEFAULT_LLMNR_MODE',
1532 'RESOLVE_SUPPORT_' + default_llmnr.to_upper())
1533 conf.set_quoted('DEFAULT_LLMNR_MODE_STR', default_llmnr)
1534
1535 have = get_option('repart').require(
1536 conf.get('HAVE_LIBFDISK') == 1,
1537 error_message : 'fdisk required').allowed()
1538 conf.set10('ENABLE_REPART', have)
1539
1540 default_dnssec = get_option('default-dnssec')
1541 if default_dnssec != 'no' and conf.get('HAVE_OPENSSL_OR_GCRYPT') == 0
1542 message('default-dnssec cannot be set to yes or allow-downgrade openssl and gcrypt are disabled. Setting default-dnssec to no.')
1543 default_dnssec = 'no'
1544 endif
1545 conf.set('DEFAULT_DNSSEC_MODE',
1546 'DNSSEC_' + default_dnssec.underscorify().to_upper())
1547 conf.set_quoted('DEFAULT_DNSSEC_MODE_STR', default_dnssec)
1548
1549 have = get_option('sysupdate').require(
1550 conf.get('HAVE_OPENSSL') == 1 and
1551 conf.get('HAVE_LIBFDISK') == 1,
1552 error_message : 'fdisk and openssl required').allowed()
1553 conf.set10('ENABLE_SYSUPDATE', have)
1554
1555 conf.set10('ENABLE_STORAGETM', get_option('storagetm'))
1556
1557 have = get_option('importd').require(
1558 conf.get('HAVE_LIBCURL') == 1 and
1559 conf.get('HAVE_OPENSSL_OR_GCRYPT') == 1 and
1560 conf.get('HAVE_ZLIB') == 1 and
1561 conf.get('HAVE_XZ') == 1,
1562 error_message : 'curl, openssl/grypt, zlib and xz required').allowed()
1563 conf.set10('ENABLE_IMPORTD', have)
1564
1565 have = get_option('homed').require(
1566 conf.get('HAVE_OPENSSL') == 1 and
1567 conf.get('HAVE_LIBFDISK') == 1 and
1568 conf.get('HAVE_LIBCRYPTSETUP') == 1 and
1569 conf.get('HAVE_CRYPT_RESUME_BY_VOLUME_KEY') == 1,
1570 error_message : 'openssl, fdisk and libcryptsetup required').allowed()
1571 conf.set10('ENABLE_HOMED', have)
1572
1573 have = have and conf.get('HAVE_PAM') == 1
1574 conf.set10('ENABLE_PAM_HOME', have)
1575
1576 feature = get_option('remote')
1577 have_deps = [conf.get('HAVE_MICROHTTPD') == 1,
1578 conf.get('HAVE_LIBCURL') == 1]
1579 # sd-j-remote requires µhttpd, and sd-j-upload requires libcurl, so
1580 # it's possible to build one without the other. Complain only if
1581 # support was explicitly requested. The auxiliary files like sysusers
1582 # config should be installed when any of the programs are built.
1583 if feature.enabled() and not (have_deps[0] and have_deps[1])
1584 error('remote support was requested, but dependencies are not available')
1585 endif
1586 have = feature.allowed() and (have_deps[0] or have_deps[1])
1587 conf.set10('ENABLE_REMOTE', have)
1588
1589 feature = get_option('vmspawn').disable_auto_if(conf.get('BUILD_MODE_DEVELOPER') == 0)
1590 conf.set10('ENABLE_VMSPAWN', feature.allowed())
1591
1592 foreach term : ['analyze',
1593 'backlight',
1594 'binfmt',
1595 'compat-mutable-uid-boundaries',
1596 'coredump',
1597 'efi',
1598 'environment-d',
1599 'firstboot',
1600 'gshadow',
1601 'hibernate',
1602 'hostnamed',
1603 'hwdb',
1604 'idn',
1605 'ima',
1606 'initrd',
1607 'kernel-install',
1608 'ldconfig',
1609 'localed',
1610 'logind',
1611 'machined',
1612 'networkd',
1613 'nscd',
1614 'nss-myhostname',
1615 'nss-systemd',
1616 'oomd',
1617 'portabled',
1618 'pstore',
1619 'quotacheck',
1620 'randomseed',
1621 'resolve',
1622 'rfkill',
1623 'smack',
1624 'sysext',
1625 'sysusers',
1626 'timedated',
1627 'timesyncd',
1628 'tmpfiles',
1629 'tpm',
1630 'userdb',
1631 'utmp',
1632 'vconsole',
1633 'xdg-autostart']
1634 have = get_option(term)
1635 name = 'ENABLE_' + term.underscorify().to_upper()
1636 conf.set10(name, have)
1637 endforeach
1638
1639 enable_sysusers = conf.get('ENABLE_SYSUSERS') == 1
1640
1641 foreach tuple : [['nss-mymachines', 'machined'],
1642 ['nss-resolve', 'resolve']]
1643 want = get_option(tuple[0])
1644 if want.allowed()
1645 have = get_option(tuple[1])
1646 if want.enabled() and not have
1647 error('@0@ is requested but @1@ is disabled'.format(tuple[0], tuple[1]))
1648 endif
1649 else
1650 have = false
1651 endif
1652 name = 'ENABLE_' + tuple[0].underscorify().to_upper()
1653 conf.set10(name, have)
1654 endforeach
1655
1656 enable_nss = false
1657 foreach term : ['ENABLE_NSS_MYHOSTNAME',
1658 'ENABLE_NSS_MYMACHINES',
1659 'ENABLE_NSS_RESOLVE',
1660 'ENABLE_NSS_SYSTEMD']
1661 if conf.get(term) == 1
1662 enable_nss = true
1663 endif
1664 endforeach
1665 conf.set10('ENABLE_NSS', enable_nss)
1666
1667 conf.set10('ENABLE_TIMEDATECTL', get_option('timedated') or get_option('timesyncd'))
1668
1669 conf.set10('ENABLE_SSH_PROXY_CONFIG', sshconfdir != 'no')
1670 conf.set10('ENABLE_SSH_USERDB_CONFIG', conf.get('ENABLE_USERDB') == 1 and sshdconfdir != 'no')
1671
1672 conf.set10('SYSTEMD_SLOW_TESTS_DEFAULT', slow_tests)
1673
1674 #####################################################################
1675
1676 pymod = import('python')
1677 python = pymod.find_installation('python3', required : true, modules : ['jinja2'])
1678 python_39 = python.language_version().version_compare('>=3.9')
1679
1680 #####################################################################
1681
1682 if conf.get('BPF_FRAMEWORK') == 1
1683 bpf_clang_flags = [
1684 '-std=gnu11',
1685 '-Wno-compare-distinct-pointer-types',
1686 '-fno-stack-protector',
1687 '-O2',
1688 '-target',
1689 'bpf',
1690 '-g',
1691 '-c',
1692 ]
1693
1694 bpf_gcc_flags = [
1695 '-std=gnu11',
1696 '-fno-stack-protector',
1697 '-O2',
1698 '-mcpu=v3',
1699 '-mco-re',
1700 '-gbtf',
1701 '-c',
1702 ]
1703
1704 # Generate defines that are appropriate to tell the compiler what architecture
1705 # we're compiling for. By default we just map meson's cpu_family to __<cpu_family>__.
1706 # This dictionary contains the exceptions where this doesn't work.
1707 #
1708 # C.f. https://mesonbuild.com/Reference-tables.html#cpu-families
1709 # and src/basic/missing_syscall_def.h.
1710 cpu_arch_defines = {
1711 'ppc' : ['-D__powerpc__'],
1712 'ppc64' : ['-D__powerpc64__', '-D_CALL_ELF=2'],
1713 'riscv32' : ['-D__riscv', '-D__riscv_xlen=32'],
1714 'riscv64' : ['-D__riscv', '-D__riscv_xlen=64'],
1715 'x86' : ['-D__i386__'],
1716
1717 # For arm, assume hardware fp is available.
1718 'arm' : ['-D__arm__', '-D__ARM_PCS_VFP'],
1719 }
1720
1721 bpf_arch_flags = cpu_arch_defines.get(host_machine.cpu_family(),
1722 ['-D__@0@__'.format(host_machine.cpu_family())])
1723 if bpf_compiler == 'gcc'
1724 bpf_arch_flags += ['-m' + host_machine.endian() + '-endian']
1725 endif
1726
1727 libbpf_include_dir = libbpf.get_variable(pkgconfig : 'includedir')
1728
1729 bpf_o_unstripped_cmd = []
1730 if bpf_compiler == 'clang'
1731 bpf_o_unstripped_cmd += [
1732 clang,
1733 bpf_clang_flags,
1734 bpf_arch_flags,
1735 ]
1736 elif bpf_compiler == 'gcc'
1737 bpf_o_unstripped_cmd += [
1738 bpf_gcc,
1739 bpf_gcc_flags,
1740 bpf_arch_flags,
1741 ]
1742 endif
1743
1744 bpf_o_unstripped_cmd += ['-I.']
1745
1746 if not meson.is_cross_build()
1747 target_triplet_cmd = run_command('gcc', '-dumpmachine', check: false)
1748 if target_triplet_cmd.returncode() == 0
1749 target_triplet = target_triplet_cmd.stdout().strip()
1750 bpf_o_unstripped_cmd += [
1751 '-isystem',
1752 '/usr/include/@0@'.format(target_triplet)
1753 ]
1754 endif
1755 endif
1756
1757 bpf_o_unstripped_cmd += [
1758 '-idirafter',
1759 libbpf_include_dir,
1760 '@INPUT@',
1761 '-o',
1762 '@OUTPUT@'
1763 ]
1764
1765 if bpftool_strip
1766 bpf_o_cmd = [
1767 bpftool,
1768 'gen',
1769 'object',
1770 '@OUTPUT@',
1771 '@INPUT@'
1772 ]
1773 elif bpf_compiler == 'clang'
1774 bpf_o_cmd = [
1775 llvm_strip,
1776 '-g',
1777 '@INPUT@',
1778 '-o',
1779 '@OUTPUT@'
1780 ]
1781 endif
1782
1783 skel_h_cmd = [
1784 bpftool,
1785 'gen',
1786 'skeleton',
1787 '@INPUT@'
1788 ]
1789 endif
1790
1791 #####################################################################
1792
1793 efi_arch = {
1794 'aarch64' : 'aa64',
1795 'arm' : 'arm',
1796 'loongarch32' : 'loongarch32',
1797 'loongarch64' : 'loongarch64',
1798 'riscv32' : 'riscv32',
1799 'riscv64' : 'riscv64',
1800 'x86_64' : 'x64',
1801 'x86' : 'ia32',
1802 }.get(host_machine.cpu_family(), '')
1803
1804 pyelftools = pymod.find_installation('python3',
1805 required : get_option('bootloader'),
1806 modules : ['elftools'])
1807
1808 have = get_option('bootloader').require(
1809 pyelftools.found() and get_option('efi') and efi_arch != '',
1810 error_message : 'unsupported EFI arch or EFI support is disabled').allowed()
1811 conf.set10('ENABLE_BOOTLOADER', have)
1812 conf.set_quoted('EFI_MACHINE_TYPE_NAME', have ? efi_arch : '')
1813
1814 efi_arch_alt = ''
1815 efi_cpu_family_alt = ''
1816 if have and efi_arch == 'x64' and cc.links('''
1817 #include <limits.h>
1818 int main(int argc, char *argv[]) {
1819 return __builtin_popcount(argc - CHAR_MAX);
1820 }''', args : ['-m32', '-march=i686'], name : '32bit build possible')
1821 efi_arch_alt = 'ia32'
1822 efi_cpu_family_alt = 'x86'
1823 endif
1824
1825 pefile = pymod.find_installation('python3', required: false, modules : ['pefile'])
1826
1827 want_ukify = get_option('ukify').require(python_39 and (want_tests != 'true' or pefile.found()), error_message : 'Python >= 3.9 and pefile required').allowed()
1828 conf.set10('ENABLE_UKIFY', want_ukify)
1829
1830 #####################################################################
1831
1832 check_efi_alignment_py = find_program('tools/check-efi-alignment.py')
1833 check_version_history_py = find_program('tools/check-version-history.py')
1834 elf2efi_py = find_program('tools/elf2efi.py')
1835 export_dbus_interfaces_py = find_program('tools/dbus_exporter.py')
1836 generate_gperfs = find_program('tools/generate-gperfs.py')
1837 make_autosuspend_rules_py = find_program('tools/make-autosuspend-rules.py')
1838 make_directive_index_py = find_program('tools/make-directive-index.py')
1839 sync_docs_py = find_program('tools/sync-docs.py')
1840 make_man_index_py = find_program('tools/make-man-index.py')
1841 meson_render_jinja2 = find_program('tools/meson-render-jinja2.py')
1842 update_dbus_docs_py = find_program('tools/update-dbus-docs.py')
1843 update_hwdb_autosuspend_sh = find_program('tools/update-hwdb-autosuspend.sh')
1844 update_hwdb_sh = find_program('tools/update-hwdb.sh')
1845 update_man_rules_py = find_program('tools/update-man-rules.py')
1846 update_syscall_tables_sh = find_program('tools/update-syscall-tables.sh')
1847 xml_helper_py = find_program('tools/xml_helper.py')
1848
1849 #####################################################################
1850
1851 version_tag = get_option('version-tag')
1852 if version_tag == ''
1853 version_tag = meson.project_version()
1854 endif
1855
1856 conf.set_quoted('VERSION_TAG', version_tag)
1857
1858 vcs_tag = get_option('vcs-tag')
1859 command = ['sh', '-c',
1860 vcs_tag and fs.exists(project_source_root / '.git') ?
1861 'echo "-g$(git -C . describe --abbrev=7 --match="" --always --dirty=^)"' : ':']
1862 version_h = vcs_tag(
1863 input : 'src/version/version.h.in',
1864 output : 'version.h',
1865 fallback : '',
1866 command : command,
1867 )
1868
1869 shared_lib_tag = get_option('shared-lib-tag')
1870 if shared_lib_tag == ''
1871 shared_lib_tag = meson.project_version().split('~')[0]
1872 endif
1873
1874 #####################################################################
1875
1876 if get_option('b_coverage')
1877 userspace_c_args += ['-include', 'src/basic/coverage.h']
1878 endif
1879
1880 #####################################################################
1881
1882 config_h = configure_file(
1883 output : 'config.h',
1884 configuration : conf)
1885
1886 userspace_c_args += ['-include', 'config.h']
1887
1888 jinja2_cmdline = [meson_render_jinja2, config_h]
1889
1890 userspace = declare_dependency(
1891 compile_args : userspace_c_args,
1892 link_args : userspace_c_ld_args,
1893 sources : version_h,
1894 )
1895
1896 man_page_depends = []
1897
1898 #####################################################################
1899
1900 simple_tests = []
1901 libsystemd_tests = []
1902 simple_fuzzers = []
1903 catalogs = []
1904 modules = [] # nss, pam, and other plugins
1905 executables = []
1906 executables_by_name = {}
1907 fuzzer_exes = []
1908
1909 # binaries that have --help and are intended for use by humans,
1910 # usually, but not always, installed in /bin.
1911 public_programs = []
1912
1913 # D-Bus introspection XML export
1914 dbus_programs = []
1915
1916 # A list of boot stubs. Required for testing of ukify.
1917 boot_stubs = []
1918
1919 build_dir_include = include_directories('.')
1920
1921 basic_includes = include_directories(
1922 'src/basic',
1923 'src/fundamental',
1924 'src/systemd',
1925 '.')
1926
1927 libsystemd_includes = [basic_includes, include_directories(
1928 'src/libsystemd/sd-bus',
1929 'src/libsystemd/sd-device',
1930 'src/libsystemd/sd-event',
1931 'src/libsystemd/sd-hwdb',
1932 'src/libsystemd/sd-id128',
1933 'src/libsystemd/sd-journal',
1934 'src/libsystemd/sd-netlink',
1935 'src/libsystemd/sd-network',
1936 'src/libsystemd/sd-resolve')]
1937
1938 includes = [libsystemd_includes, include_directories('src/shared')]
1939
1940 subdir('po')
1941 subdir('catalog')
1942 subdir('src/fundamental')
1943 subdir('src/basic')
1944 subdir('src/libsystemd')
1945 subdir('src/shared')
1946 subdir('src/libudev')
1947
1948 libsystemd = shared_library(
1949 'systemd',
1950 version : libsystemd_version,
1951 include_directories : libsystemd_includes,
1952 link_args : ['-shared',
1953 '-Wl,--version-script=' + libsystemd_sym_path],
1954 link_with : [libbasic,
1955 libbasic_gcrypt],
1956 link_whole : [libsystemd_static],
1957 dependencies : [librt,
1958 threads,
1959 userspace],
1960 link_depends : libsystemd_sym,
1961 install : true,
1962 install_tag: 'libsystemd',
1963 install_dir : libdir)
1964
1965 alias_target('libsystemd', libsystemd)
1966
1967 install_libsystemd_static = static_library(
1968 'systemd',
1969 libsystemd_sources,
1970 basic_sources,
1971 basic_gcrypt_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_cflags,
1984 libmount,
1985 libopenssl,
1986 librt,
1987 libxz_cflags,
1988 libzstd_cflags,
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')