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