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