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