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