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