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