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