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