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