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