]> git.proxmox.com Git - systemd.git/blobdiff - meson.build
New upstream version 250.4
[systemd.git] / meson.build
index 580964c3fad5f91c0a8bf9e535e9019fcde27125..cb9936ee8be3bbfc3ad2d18b8587f5def8a47837 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 project('systemd', 'c',
-        version : '247',
+        version : '250',
         license : 'LGPLv2+',
         default_options: [
                 'c_std=gnu99',
@@ -10,40 +10,33 @@ project('systemd', 'c',
                 'localstatedir=/var',
                 'warning_level=2',
         ],
-        meson_version : '>= 0.46',
+        meson_version : '>= 0.53.2',
        )
 
-libsystemd_version = '0.30.0'
-libudev_version = '1.7.0'
+libsystemd_version = '0.33.0'
+libudev_version = '1.7.3'
 
-# We need the same data in two different formats, ugh!
-# Also, for hysterical reasons, we use different variable
-# names, sometimes. Not all variables are included in every
-# set. Ugh, ugh, ugh!
 conf = configuration_data()
-conf.set('PROJECT_VERSION',        meson.project_version(),
+conf.set_quoted('PROJECT_URL', 'https://www.freedesktop.org/wiki/Software/systemd')
+conf.set('PROJECT_VERSION',    meson.project_version(),
          description : 'Numerical project version (used where a simple number is expected)')
 
-substs = configuration_data()
-substs.set('PROJECT_URL',          'https://www.freedesktop.org/wiki/Software/systemd')
-substs.set('PROJECT_VERSION',      meson.project_version(),
-           description : 'Numerical project version (used where a simple number is expected)')
-
 # This is to be used instead of meson.source_root(), as the latter will return
 # the wrong result when systemd is being built as a meson subproject
 project_source_root = meson.current_source_dir()
 project_build_root = meson.current_build_dir()
 relative_source_path = run_command('realpath',
                                    '--relative-to=@0@'.format(project_build_root),
-                                   project_source_root).stdout().strip()
+                                   project_source_root,
+                                   check : true).stdout().strip()
 conf.set_quoted('RELATIVE_SOURCE_PATH', relative_source_path)
 
-conf.set('BUILD_MODE', 'BUILD_MODE_' + get_option('mode').to_upper(),
-         description : 'tailor build to development or release builds')
+conf.set10('BUILD_MODE_DEVELOPER', get_option('mode') == 'developer',
+           description : 'tailor build to development or release builds')
 
 want_ossfuzz = get_option('oss-fuzz')
 want_libfuzzer = get_option('llvm-fuzz')
-if want_ossfuzz + want_libfuzzer > 1
+if want_ossfuzz and want_libfuzzer
         error('only one of oss-fuzz or llvm-fuzz can be specified')
 endif
 
@@ -55,7 +48,7 @@ fuzzer_build = want_ossfuzz or want_libfuzzer
 # Try to install the git pre-commit hook
 add_git_hook_sh = find_program('tools/add-git-hook.sh', required : false)
 if add_git_hook_sh.found()
-        git_hook = run_command(add_git_hook_sh)
+        git_hook = run_command(add_git_hook_sh, check : false)
         if git_hook.returncode() == 0
                 message(git_hook.stdout().strip())
         endif
@@ -63,16 +56,22 @@ endif
 
 #####################################################################
 
+fs = import('fs')
 if get_option('split-usr') == 'auto'
-        split_usr = run_command('test', '-L', '/bin').returncode() != 0
+        split_usr = not fs.is_symlink('/bin')
 else
         split_usr = get_option('split-usr') == 'true'
 endif
+if split_usr
+        warning('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n\n'
+                + '                    split-usr mode is going to be removed\n' +
+                '\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
+endif
 conf.set10('HAVE_SPLIT_USR', split_usr,
            description : '/usr/bin and /bin directories are separate')
 
 if get_option('split-bin') == 'auto'
-        split_bin = run_command('test', '-L', '/usr/sbin').returncode() != 0
+        split_bin = not fs.is_symlink('/usr/sbin')
 else
         split_bin = get_option('split-bin') == 'true'
 endif
@@ -94,6 +93,7 @@ sysvinit_path = get_option('sysvinit-path')
 sysvrcnd_path = get_option('sysvrcnd-path')
 conf.set10('HAVE_SYSV_COMPAT', sysvinit_path != '' and sysvrcnd_path != '',
            description : 'SysV init scripts and rcN.d links are supported')
+conf.set10('CREATE_LOG_DIRS', get_option('create-log-dirs'))
 
 if get_option('hibernate') and not get_option('initrd')
         error('hibernate depends on initrd')
@@ -103,209 +103,199 @@ conf.set10('BUMP_PROC_SYS_FS_FILE_MAX', get_option('bump-proc-sys-fs-file-max'))
 conf.set10('BUMP_PROC_SYS_FS_NR_OPEN',  get_option('bump-proc-sys-fs-nr-open'))
 conf.set('HIGH_RLIMIT_NOFILE',          512*1024)
 
-# join_paths ignores the preceding arguments if an absolute component is
-# encountered, so this should canonicalize various paths when they are
-# absolute or relative.
+# Meson ignores the preceding arguments when joining paths if an absolute
+# component is encountered, so this should canonicalize various paths when they
+# are absolute or relative.
 prefixdir = get_option('prefix')
 if not prefixdir.startswith('/')
         error('Prefix is not absolute: "@0@"'.format(prefixdir))
 endif
-bindir = join_paths(prefixdir, get_option('bindir'))
-libdir = join_paths(prefixdir, get_option('libdir'))
-sysconfdir = join_paths(prefixdir, get_option('sysconfdir'))
-includedir = join_paths(prefixdir, get_option('includedir'))
-datadir = join_paths(prefixdir, get_option('datadir'))
-localstatedir = join_paths('/', get_option('localstatedir'))
+if prefixdir != rootprefixdir and rootprefixdir != '/' and not prefixdir.strip('/').startswith(rootprefixdir.strip('/') + '/')
+        error('Prefix is not below root prefix (now rootprefix=@0@ prefix=@1@)'.format(
+                rootprefixdir, prefixdir))
+endif
+
+bindir = prefixdir / get_option('bindir')
+libdir = prefixdir / get_option('libdir')
+sysconfdir = prefixdir / get_option('sysconfdir')
+includedir = prefixdir / get_option('includedir')
+datadir = prefixdir / get_option('datadir')
+localstatedir = '/' / get_option('localstatedir')
 
-rootbindir = join_paths(rootprefixdir, 'bin')
-rootsbindir = join_paths(rootprefixdir, split_bin ? 'sbin' : 'bin')
-rootlibexecdir = join_paths(rootprefixdir, 'lib/systemd')
+rootbindir = rootprefixdir / 'bin'
+rootsbindir = rootprefixdir / (split_bin ? 'sbin' : 'bin')
+rootlibexecdir = rootprefixdir / 'lib/systemd'
 
 rootlibdir = get_option('rootlibdir')
 if rootlibdir == ''
-        rootlibdir = join_paths(rootprefixdir, libdir.split('/')[-1])
+        rootlibdir = rootprefixdir / libdir.split('/')[-1]
 endif
 
-install_sysconfdir = get_option('install-sysconfdir')
+install_sysconfdir = get_option('install-sysconfdir') != 'false'
+install_sysconfdir_samples = get_option('install-sysconfdir') == 'true'
 # Dirs of external packages
-pkgconfigdatadir = get_option('pkgconfigdatadir') == '' ? join_paths(datadir, 'pkgconfig') : get_option('pkgconfigdatadir')
-pkgconfiglibdir = get_option('pkgconfiglibdir') == '' ? join_paths(libdir, 'pkgconfig') : get_option('pkgconfiglibdir')
-polkitpolicydir = join_paths(datadir, 'polkit-1/actions')
-polkitrulesdir = join_paths(datadir, 'polkit-1/rules.d')
-polkitpkladir = join_paths(localstatedir, 'lib/polkit-1/localauthority/10-vendor.d')
-xinitrcdir = join_paths(sysconfdir, 'X11/xinit/xinitrc.d')
+pkgconfigdatadir = get_option('pkgconfigdatadir') != '' ? get_option('pkgconfigdatadir') : datadir / 'pkgconfig'
+pkgconfiglibdir = get_option('pkgconfiglibdir') != '' ? get_option('pkgconfiglibdir') : libdir / 'pkgconfig'
+polkitpolicydir = datadir / 'polkit-1/actions'
+polkitrulesdir = datadir / 'polkit-1/rules.d'
+polkitpkladir = localstatedir / 'lib/polkit-1/localauthority/10-vendor.d'
+xinitrcdir = get_option('xinitrcdir') != '' ? get_option('xinitrcdir') : sysconfdir / 'X11/xinit/xinitrc.d'
 rpmmacrosdir = get_option('rpmmacrosdir')
 if rpmmacrosdir != 'no'
-        rpmmacrosdir = join_paths(prefixdir, rpmmacrosdir)
+        rpmmacrosdir = prefixdir / rpmmacrosdir
 endif
-modprobedir = join_paths(rootprefixdir, 'lib/modprobe.d')
+modprobedir = rootprefixdir / 'lib/modprobe.d'
 
 # Our own paths
-pkgdatadir = join_paths(datadir, 'systemd')
-environmentdir = join_paths(prefixdir, 'lib/environment.d')
-pkgsysconfdir = join_paths(sysconfdir, 'systemd')
-userunitdir = join_paths(prefixdir, 'lib/systemd/user')
-userpresetdir = join_paths(prefixdir, 'lib/systemd/user-preset')
-tmpfilesdir = join_paths(prefixdir, 'lib/tmpfiles.d')
-sysusersdir = join_paths(prefixdir, 'lib/sysusers.d')
-sysctldir = join_paths(prefixdir, 'lib/sysctl.d')
-binfmtdir = join_paths(prefixdir, 'lib/binfmt.d')
-modulesloaddir = join_paths(prefixdir, 'lib/modules-load.d')
-networkdir = join_paths(rootprefixdir, 'lib/systemd/network')
-pkgincludedir = join_paths(includedir, 'systemd')
-systemgeneratordir = join_paths(rootlibexecdir, 'system-generators')
-usergeneratordir = join_paths(prefixdir, 'lib/systemd/user-generators')
-systemenvgeneratordir = join_paths(prefixdir, 'lib/systemd/system-environment-generators')
-userenvgeneratordir = join_paths(prefixdir, 'lib/systemd/user-environment-generators')
-systemshutdowndir = join_paths(rootlibexecdir, 'system-shutdown')
-systemsleepdir = join_paths(rootlibexecdir, 'system-sleep')
-systemunitdir = join_paths(rootprefixdir, 'lib/systemd/system')
-systempresetdir = join_paths(rootprefixdir, 'lib/systemd/system-preset')
-udevlibexecdir = join_paths(rootprefixdir, 'lib/udev')
-udevrulesdir = join_paths(udevlibexecdir, 'rules.d')
-udevhwdbdir = join_paths(udevlibexecdir, 'hwdb.d')
-catalogdir = join_paths(prefixdir, 'lib/systemd/catalog')
-kernelinstalldir = join_paths(prefixdir, 'lib/kernel/install.d')
-factorydir = join_paths(datadir, 'factory')
-bootlibdir = join_paths(prefixdir, 'lib/systemd/boot/efi')
-testsdir = join_paths(prefixdir, 'lib/systemd/tests')
-systemdstatedir = join_paths(localstatedir, 'lib/systemd')
-catalogstatedir = join_paths(systemdstatedir, 'catalog')
-randomseeddir = join_paths(localstatedir, 'lib/systemd')
-profiledir = join_paths(rootlibexecdir, 'portable', 'profile')
-ntpservicelistdir = join_paths(rootprefixdir, 'lib/systemd/ntp-units.d')
+pkgdatadir = datadir / 'systemd'
+environmentdir = prefixdir / 'lib/environment.d'
+pkgsysconfdir = sysconfdir / 'systemd'
+userunitdir = prefixdir / 'lib/systemd/user'
+userpresetdir = prefixdir / 'lib/systemd/user-preset'
+tmpfilesdir = prefixdir / 'lib/tmpfiles.d'
+sysusersdir = prefixdir / 'lib/sysusers.d'
+sysctldir = prefixdir / 'lib/sysctl.d'
+binfmtdir = prefixdir / 'lib/binfmt.d'
+modulesloaddir = prefixdir / 'lib/modules-load.d'
+networkdir = rootprefixdir / 'lib/systemd/network'
+pkgincludedir = includedir / 'systemd'
+systemgeneratordir = rootlibexecdir / 'system-generators'
+usergeneratordir = prefixdir / 'lib/systemd/user-generators'
+systemenvgeneratordir = prefixdir / 'lib/systemd/system-environment-generators'
+userenvgeneratordir = prefixdir / 'lib/systemd/user-environment-generators'
+systemshutdowndir = rootlibexecdir / 'system-shutdown'
+systemsleepdir = rootlibexecdir / 'system-sleep'
+systemunitdir = rootprefixdir / 'lib/systemd/system'
+systempresetdir = rootprefixdir / 'lib/systemd/system-preset'
+udevlibexecdir = rootprefixdir / 'lib/udev'
+udevrulesdir = udevlibexecdir / 'rules.d'
+udevhwdbdir = udevlibexecdir / 'hwdb.d'
+catalogdir = prefixdir / 'lib/systemd/catalog'
+kerneldir = prefixdir / 'lib/kernel'
+kernelinstalldir = kerneldir / 'install.d'
+factorydir = datadir / 'factory'
+bootlibdir = prefixdir / 'lib/systemd/boot/efi'
+testsdir = prefixdir / 'lib/systemd/tests'
+systemdstatedir = localstatedir / 'lib/systemd'
+catalogstatedir = systemdstatedir / 'catalog'
+randomseeddir = localstatedir / 'lib/systemd'
+profiledir = rootlibexecdir / 'portable' / 'profile'
+ntpservicelistdir = rootprefixdir / 'lib/systemd/ntp-units.d'
 
 docdir = get_option('docdir')
 if docdir == ''
-        docdir = join_paths(datadir, 'doc/systemd')
+        docdir = datadir / 'doc/systemd'
 endif
 
 dbuspolicydir = get_option('dbuspolicydir')
 if dbuspolicydir == ''
-        dbuspolicydir = join_paths(datadir, 'dbus-1/system.d')
+        dbuspolicydir = datadir / 'dbus-1/system.d'
 endif
 
 dbussessionservicedir = get_option('dbussessionservicedir')
 if dbussessionservicedir == ''
-        dbussessionservicedir = join_paths(datadir, 'dbus-1/services')
+        dbussessionservicedir = datadir / 'dbus-1/services'
 endif
 
 dbussystemservicedir = get_option('dbussystemservicedir')
 if dbussystemservicedir == ''
-        dbussystemservicedir = join_paths(datadir, 'dbus-1/system-services')
+        dbussystemservicedir = datadir / 'dbus-1/system-services'
 endif
 
 pamlibdir = get_option('pamlibdir')
 if pamlibdir == ''
-        pamlibdir = join_paths(rootlibdir, 'security')
+        pamlibdir = rootlibdir / 'security'
 endif
 
 pamconfdir = get_option('pamconfdir')
 if pamconfdir == ''
-        pamconfdir = join_paths(prefixdir, 'lib/pam.d')
+        pamconfdir = prefixdir / 'lib/pam.d'
+endif
+
+libcryptsetup_plugins_dir = get_option('libcryptsetup-plugins-dir')
+if libcryptsetup_plugins_dir == ''
+        libcryptsetup_plugins_dir = rootlibdir / 'cryptsetup'
 endif
 
 memory_accounting_default = get_option('memory-accounting-default')
 status_unit_format_default = get_option('status-unit-format-default')
 
+conf.set_quoted('BINFMT_DIR',                                 binfmtdir)
+conf.set_quoted('BOOTLIBDIR',                                 bootlibdir)
+conf.set_quoted('CATALOG_DATABASE',                           catalogstatedir / 'database')
+conf.set_quoted('CERTIFICATE_ROOT',                           get_option('certificate-root'))
+conf.set_quoted('DOC_DIR',                                    docdir)
+conf.set_quoted('DOCUMENT_ROOT',                              pkgdatadir / 'gatewayd')
+conf.set_quoted('ENVIRONMENT_DIR',                            environmentdir)
+conf.set_quoted('INCLUDE_DIR',                                includedir)
+conf.set_quoted('LIBDIR',                                     libdir)
+conf.set_quoted('MODPROBE_DIR',                               modprobedir)
+conf.set_quoted('MODULESLOAD_DIR',                            modulesloaddir)
 conf.set_quoted('PKGSYSCONFDIR',                              pkgsysconfdir)
-conf.set_quoted('SYSTEM_CONFIG_UNIT_DIR',                     join_paths(pkgsysconfdir, 'system'))
-conf.set_quoted('SYSTEM_DATA_UNIT_PATH',                      systemunitdir)
-conf.set_quoted('SYSTEM_SYSVINIT_PATH',                       sysvinit_path)
-conf.set_quoted('SYSTEM_SYSVRCND_PATH',                       sysvrcnd_path)
+conf.set_quoted('POLKIT_AGENT_BINARY_PATH',                   bindir / 'pkttyagent')
+conf.set_quoted('PREFIX',                                     prefixdir)
+conf.set_quoted('RANDOM_SEED',                                randomseeddir / 'random-seed')
+conf.set_quoted('RANDOM_SEED_DIR',                            randomseeddir)
 conf.set_quoted('RC_LOCAL_PATH',                              get_option('rc-local'))
-
-conf.set('ANSI_OK_COLOR',                                     'ANSI_' + get_option('ok-color').underscorify().to_upper())
-
-conf.set_quoted('USER_CONFIG_UNIT_DIR',                       join_paths(pkgsysconfdir, 'user'))
-conf.set_quoted('USER_DATA_UNIT_DIR',                         userunitdir)
-conf.set_quoted('CERTIFICATE_ROOT',                           get_option('certificate-root'))
-conf.set_quoted('CATALOG_DATABASE',                           join_paths(catalogstatedir, 'database'))
-conf.set_quoted('SYSTEMD_CGROUP_AGENT_PATH',                  join_paths(rootlibexecdir, 'systemd-cgroups-agent'))
-conf.set_quoted('SYSTEMD_BINARY_PATH',                        join_paths(rootlibexecdir, 'systemd'))
-conf.set_quoted('SYSTEMD_FSCK_PATH',                          join_paths(rootlibexecdir, 'systemd-fsck'))
-conf.set_quoted('SYSTEMD_MAKEFS_PATH',                        join_paths(rootlibexecdir, 'systemd-makefs'))
-conf.set_quoted('SYSTEMD_GROWFS_PATH',                        join_paths(rootlibexecdir, 'systemd-growfs'))
-conf.set_quoted('SYSTEMD_SHUTDOWN_BINARY_PATH',               join_paths(rootlibexecdir, 'systemd-shutdown'))
-conf.set_quoted('SYSTEMCTL_BINARY_PATH',                      join_paths(rootbindir, 'systemctl'))
-conf.set_quoted('SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH', join_paths(rootbindir, 'systemd-tty-ask-password-agent'))
-conf.set_quoted('SYSTEMD_STDIO_BRIDGE_BINARY_PATH',           join_paths(bindir, 'systemd-stdio-bridge'))
+conf.set_quoted('ROOTBINDIR',                                 rootbindir)
+conf.set_quoted('ROOTLIBDIR',                                 rootlibdir)
+conf.set_quoted('ROOTLIBEXECDIR',                             rootlibexecdir)
 conf.set_quoted('ROOTPREFIX',                                 rootprefixdir)
 conf.set_quoted('ROOTPREFIX_NOSLASH',                         rootprefixdir_noslash)
-conf.set_quoted('RANDOM_SEED_DIR',                            randomseeddir)
-conf.set_quoted('RANDOM_SEED',                                join_paths(randomseeddir, 'random-seed'))
-conf.set_quoted('SYSTEMD_CRYPTSETUP_PATH',                    join_paths(rootlibexecdir, 'systemd-cryptsetup'))
-conf.set_quoted('SYSTEM_GENERATOR_DIR',                       systemgeneratordir)
-conf.set_quoted('USER_GENERATOR_DIR',                         usergeneratordir)
+conf.set_quoted('SYSCONF_DIR',                                sysconfdir)
+conf.set_quoted('SYSCTL_DIR',                                 sysctldir)
+conf.set_quoted('SYSTEMCTL_BINARY_PATH',                      rootbindir / 'systemctl')
+conf.set_quoted('SYSTEMD_BINARY_PATH',                        rootlibexecdir / 'systemd')
+conf.set_quoted('SYSTEMD_CATALOG_DIR',                        catalogdir)
+conf.set_quoted('SYSTEMD_CGROUPS_AGENT_PATH',                 rootlibexecdir / 'systemd-cgroups-agent')
+conf.set_quoted('SYSTEMD_CRYPTSETUP_PATH',                    rootlibexecdir / 'systemd-cryptsetup')
+conf.set_quoted('SYSTEMD_EXPORT_PATH',                        rootlibexecdir / 'systemd-export')
+conf.set_quoted('SYSTEMD_FSCK_PATH',                          rootlibexecdir / 'systemd-fsck')
+conf.set_quoted('SYSTEMD_GROWFS_PATH',                        rootlibexecdir / 'systemd-growfs')
+conf.set_quoted('SYSTEMD_HOMEWORK_PATH',                      rootlibexecdir / 'systemd-homework')
+conf.set_quoted('SYSTEMD_IMPORT_FS_PATH',                     rootlibexecdir / 'systemd-import-fs')
+conf.set_quoted('SYSTEMD_IMPORT_PATH',                        rootlibexecdir / 'systemd-import')
+conf.set_quoted('SYSTEMD_INTEGRITYSETUP_PATH',                rootlibexecdir / 'systemd-integritysetup')
+conf.set_quoted('SYSTEMD_KBD_MODEL_MAP',                      pkgdatadir / 'kbd-model-map')
+conf.set_quoted('SYSTEMD_LANGUAGE_FALLBACK_MAP',              pkgdatadir / 'language-fallback-map')
+conf.set_quoted('SYSTEMD_MAKEFS_PATH',                        rootlibexecdir / 'systemd-makefs')
+conf.set_quoted('SYSTEMD_PULL_PATH',                          rootlibexecdir / 'systemd-pull')
+conf.set_quoted('SYSTEMD_SHUTDOWN_BINARY_PATH',               rootlibexecdir / 'systemd-shutdown')
+conf.set_quoted('SYSTEMD_STDIO_BRIDGE_BINARY_PATH',           bindir / 'systemd-stdio-bridge')
+conf.set_quoted('SYSTEMD_TEST_DATA',                          testsdir / 'testdata')
+conf.set_quoted('SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH', rootbindir / 'systemd-tty-ask-password-agent')
+conf.set_quoted('SYSTEMD_UPDATE_HELPER_PATH',                 rootlibexecdir / 'systemd-update-helper')
+conf.set_quoted('SYSTEMD_USERWORK_PATH',                      rootlibexecdir / 'systemd-userwork')
+conf.set_quoted('SYSTEMD_VERITYSETUP_PATH',                   rootlibexecdir / 'systemd-veritysetup')
+conf.set_quoted('SYSTEM_CONFIG_UNIT_DIR',                     pkgsysconfdir / 'system')
+conf.set_quoted('SYSTEM_DATA_UNIT_DIR',                       systemunitdir)
 conf.set_quoted('SYSTEM_ENV_GENERATOR_DIR',                   systemenvgeneratordir)
-conf.set_quoted('USER_ENV_GENERATOR_DIR',                     userenvgeneratordir)
+conf.set_quoted('SYSTEM_GENERATOR_DIR',                       systemgeneratordir)
+conf.set_quoted('SYSTEM_PRESET_DIR',                          systempresetdir)
 conf.set_quoted('SYSTEM_SHUTDOWN_PATH',                       systemshutdowndir)
 conf.set_quoted('SYSTEM_SLEEP_PATH',                          systemsleepdir)
-conf.set_quoted('SYSTEMD_KBD_MODEL_MAP',                      join_paths(pkgdatadir, 'kbd-model-map'))
-conf.set_quoted('SYSTEMD_LANGUAGE_FALLBACK_MAP',              join_paths(pkgdatadir, 'language-fallback-map'))
-conf.set_quoted('SYSTEMD_TEST_DATA',                          join_paths(testsdir, 'testdata'))
-conf.set_quoted('SYSTEMD_CATALOG_DIR',                        catalogdir)
+conf.set_quoted('SYSTEM_SYSVINIT_PATH',                       sysvinit_path)
+conf.set_quoted('SYSTEM_SYSVRCND_PATH',                       sysvrcnd_path)
+conf.set_quoted('SYSUSERS_DIR',                               sysusersdir)
+conf.set_quoted('TMPFILES_DIR',                               tmpfilesdir)
 conf.set_quoted('UDEVLIBEXECDIR',                             udevlibexecdir)
-conf.set_quoted('POLKIT_AGENT_BINARY_PATH',                   join_paths(bindir, 'pkttyagent'))
-conf.set_quoted('LIBDIR',                                     libdir)
-conf.set_quoted('ROOTLIBDIR',                                 rootlibdir)
-conf.set_quoted('ROOTLIBEXECDIR',                             rootlibexecdir)
-conf.set_quoted('BOOTLIBDIR',                                 bootlibdir)
-conf.set_quoted('SYSTEMD_PULL_PATH',                          join_paths(rootlibexecdir, 'systemd-pull'))
-conf.set_quoted('SYSTEMD_IMPORT_PATH',                        join_paths(rootlibexecdir, 'systemd-import'))
-conf.set_quoted('SYSTEMD_IMPORT_FS_PATH',                     join_paths(rootlibexecdir, 'systemd-import-fs'))
-conf.set_quoted('SYSTEMD_EXPORT_PATH',                        join_paths(rootlibexecdir, 'systemd-export'))
-conf.set_quoted('VENDOR_KEYRING_PATH',                        join_paths(rootlibexecdir, 'import-pubring.gpg'))
-conf.set_quoted('USER_KEYRING_PATH',                          join_paths(pkgsysconfdir, 'import-pubring.gpg'))
-conf.set_quoted('DOCUMENT_ROOT',                              join_paths(pkgdatadir, 'gatewayd'))
-conf.set_quoted('SYSTEMD_HOMEWORK_PATH',                      join_paths(rootlibexecdir, 'systemd-homework'))
-conf.set_quoted('SYSTEMD_USERWORK_PATH',                      join_paths(rootlibexecdir, 'systemd-userwork'))
+conf.set_quoted('UDEV_HWDB_DIR',                              udevhwdbdir)
+conf.set_quoted('UDEV_RULES_DIR',                             udevrulesdir)
+conf.set_quoted('UPDATE_HELPER_USER_TIMEOUT',                 get_option('update-helper-user-timeout'))
+conf.set_quoted('USER_CONFIG_UNIT_DIR',                       pkgsysconfdir / 'user')
+conf.set_quoted('USER_DATA_UNIT_DIR',                         userunitdir)
+conf.set_quoted('USER_ENV_GENERATOR_DIR',                     userenvgeneratordir)
+conf.set_quoted('USER_GENERATOR_DIR',                         usergeneratordir)
+conf.set_quoted('USER_KEYRING_PATH',                          pkgsysconfdir / 'import-pubring.gpg')
+conf.set_quoted('USER_PRESET_DIR',                            userpresetdir)
+conf.set_quoted('VENDOR_KEYRING_PATH',                        rootlibexecdir / 'import-pubring.gpg')
+
+conf.set('ANSI_OK_COLOR',                                     'ANSI_' + get_option('ok-color').underscorify().to_upper())
+conf.set10('ENABLE_URLIFY',                                   get_option('urlify'))
+conf.set10('ENABLE_FEXECVE',                                  get_option('fexecve'))
 conf.set10('MEMORY_ACCOUNTING_DEFAULT',                       memory_accounting_default)
-conf.set_quoted('MEMORY_ACCOUNTING_DEFAULT_YES_NO',           memory_accounting_default ? 'yes' : 'no')
 conf.set('STATUS_UNIT_FORMAT_DEFAULT',                        'STATUS_UNIT_FORMAT_' + status_unit_format_default.to_upper())
-
-substs.set('prefix',                                          prefixdir)
-substs.set('rootprefix',                                      rootprefixdir)
-substs.set('rootprefix_noslash',                              rootprefixdir_noslash)
-substs.set('exec_prefix',                                     prefixdir)
-substs.set('libdir',                                          libdir)
-substs.set('rootlibdir',                                      rootlibdir)
-substs.set('includedir',                                      includedir)
-substs.set('sysconfdir',                                      sysconfdir)
-substs.set('bindir',                                          bindir)
-substs.set('rootbindir',                                      rootbindir)
-substs.set('rootlibexecdir',                                  rootlibexecdir)
-substs.set('systemunitdir',                                   systemunitdir)
-substs.set('userunitdir',                                     userunitdir)
-substs.set('systempresetdir',                                 systempresetdir)
-substs.set('userpresetdir',                                   userpresetdir)
-substs.set('udevhwdbdir',                                     udevhwdbdir)
-substs.set('udevrulesdir',                                    udevrulesdir)
-substs.set('udevlibexecdir',                                  udevlibexecdir)
-substs.set('environmentdir',                                  environmentdir)
-substs.set('catalogdir',                                      catalogdir)
-substs.set('tmpfilesdir',                                     tmpfilesdir)
-substs.set('sysusersdir',                                     sysusersdir)
-substs.set('sysctldir',                                       sysctldir)
-substs.set('binfmtdir',                                       binfmtdir)
-substs.set('modulesloaddir',                                  modulesloaddir)
-substs.set('modprobedir',                                     modprobedir)
-substs.set('systemgeneratordir',                              systemgeneratordir)
-substs.set('usergeneratordir',                                usergeneratordir)
-substs.set('systemenvgeneratordir',                           systemenvgeneratordir)
-substs.set('userenvgeneratordir',                             userenvgeneratordir)
-substs.set('systemshutdowndir',                               systemshutdowndir)
-substs.set('systemsleepdir',                                  systemsleepdir)
-substs.set('CERTIFICATEROOT',                                 get_option('certificate-root'))
-substs.set('RANDOM_SEED',                                     join_paths(randomseeddir, 'random-seed'))
-substs.set('SYSTEM_SYSVINIT_PATH',                            sysvinit_path)
-substs.set('SYSTEM_SYSVRCND_PATH',                            sysvrcnd_path)
-substs.set('SYSTEMD_TEST_DATA',                               join_paths(testsdir, 'testdata'))
-substs.set('RC_LOCAL_PATH',                                   get_option('rc-local'))
-substs.set('MEMORY_ACCOUNTING_DEFAULT',                       memory_accounting_default ? 'yes' : 'no')
-substs.set('STATUS_UNIT_FORMAT_DEFAULT',                      status_unit_format_default)
-substs.set('HIGH_RLIMIT_NOFILE',                              conf.get('HIGH_RLIMIT_NOFILE'))
-substs.set('BUILD_ROOT',                                      project_build_root)
+conf.set_quoted('STATUS_UNIT_FORMAT_DEFAULT_STR',             status_unit_format_default)
 
 #####################################################################
 
@@ -343,74 +333,93 @@ endif
 # Those generate many false positives, and we do not want to change the code to
 # avoid them.
 basic_disabled_warnings = [
-        '-Wno-unused-parameter',
-        '-Wno-missing-field-initializers',
-        '-Wno-unused-result',
         '-Wno-format-signedness',
+        '-Wno-missing-field-initializers',
+        '-Wno-unused-parameter',
 ]
 
-possible_cc_flags = [
+possible_common_cc_flags = [
+        '-Wdate-time',
+        '-Wendif-labels',
+        '-Werror=format=2',
+        '-Werror=implicit-function-declaration',
+        '-Werror=incompatible-pointer-types',
+        '-Werror=int-conversion',
+        '-Werror=overflow',
+        '-Werror=override-init',
+        '-Werror=return-type',
+        '-Werror=shift-count-overflow',
+        '-Werror=shift-overflow=2',
         '-Werror=undef',
+        '-Wfloat-equal',
+        '-Wimplicit-fallthrough=5',
+        '-Winit-self',
         '-Wlogical-op',
         '-Wmissing-include-dirs',
+        '-Wmissing-noreturn',
+        '-Wnested-externs',
         '-Wold-style-definition',
         '-Wpointer-arith',
-        '-Winit-self',
-        '-Wfloat-equal',
-        '-Wsuggest-attribute=noreturn',
-        '-Werror=missing-prototypes',
-        '-Werror=implicit-function-declaration',
-        '-Werror=missing-declarations',
-        '-Werror=return-type',
-        '-Werror=incompatible-pointer-types',
-        '-Werror=format=2',
-        '-Wstrict-prototypes',
         '-Wredundant-decls',
-        '-Wmissing-noreturn',
-        '-Wimplicit-fallthrough=5',
         '-Wshadow',
-        '-Wendif-labels',
         '-Wstrict-aliasing=2',
+        '-Wstrict-prototypes',
+        '-Wsuggest-attribute=noreturn',
+        '-Wunused-function',
         '-Wwrite-strings',
-        '-Werror=overflow',
-        '-Werror=shift-count-overflow',
-        '-Werror=shift-overflow=2',
-        '-Wdate-time',
-        '-Wnested-externs',
 
         # negative arguments are correctly detected starting with meson 0.46.
         '-Wno-error=#warnings',  # clang
         '-Wno-string-plus-int',  # clang
+]
 
-        # Disable -Wmaybe-uninitialized, since it's noisy on gcc 8 with
-        # optimizations enabled, producing essentially false positives.
-        '-Wno-maybe-uninitialized',
+# Disable -Wmaybe-unitialized when compiling with -Os/-O1/-O3/etc. There are
+# too many false positives with gcc >= 8. Effectively, we only test with -O0
+# and -O2; this should be enough to catch most important cases without too much
+# busywork. See https://github.com/systemd/systemd/pull/19226.
+if cc.get_id() == 'gcc' and (not '02'.contains(get_option('optimization')) or
+                             cc.version().version_compare('<10'))
+        possible_common_cc_flags += '-Wno-maybe-uninitialized'
+endif
 
-        '-ffast-math',
-        '-fno-common',
-        '-fdiagnostics-show-option',
-        '-fno-strict-aliasing',
-        '-fvisibility=hidden',
-        '-fstack-protector',
-        '-fstack-protector-strong',
-        '--param=ssp-buffer-size=4',
-]
+# Disable -Wno-unused-result with gcc, see
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425.
+if cc.get_id() == 'gcc'
+        possible_common_cc_flags += '-Wno-unused-result'
+endif
 
 # --as-needed and --no-undefined are provided by meson by default,
-# run mesonconf to see what is enabled
+# run 'meson configure' to see what is enabled
 possible_link_flags = [
-        '-Wl,-z,relro',
+        '-Wl,--fatal-warnings',
         '-Wl,-z,now',
+        '-Wl,-z,relro',
         '-fstack-protector',
 ]
 
+if get_option('b_sanitize') == 'none'
+        possible_link_flags += '-Wl,--warn-common'
+endif
+
 if cc.get_id() == 'clang'
-        possible_cc_flags += [
+        possible_common_cc_flags += [
                 '-Wno-typedef-redefinition',
                 '-Wno-gnu-variable-sized-type-not-at-end',
         ]
 endif
 
+possible_cc_flags = possible_common_cc_flags + [
+        '-Werror=missing-declarations',
+        '-Werror=missing-prototypes',
+        '-fdiagnostics-show-option',
+        '-fno-common',
+        '-fno-strict-aliasing',
+        '-fstack-protector',
+        '-fstack-protector-strong',
+        '-fvisibility=hidden',
+        '--param=ssp-buffer-size=4',
+]
+
 if get_option('buildtype') != 'debug'
         possible_cc_flags += [
                 '-ffunction-sections',
@@ -459,14 +468,18 @@ conf.set('SIZEOF_DEV_T', cc.sizeof('dev_t', prefix : '#include <sys/types.h>'))
 conf.set('SIZEOF_INO_T', cc.sizeof('ino_t', prefix : '#include <sys/types.h>'))
 conf.set('SIZEOF_TIME_T', cc.sizeof('time_t', prefix : '#include <sys/time.h>'))
 conf.set('SIZEOF_RLIM_T', cc.sizeof('rlim_t', prefix : '#include <sys/resource.h>'))
+conf.set('SIZEOF_TIMEX_MEMBER', cc.sizeof('typeof(((struct timex *)0)->freq)', prefix : '#include <sys/timex.h>'))
 
 decl_headers = '''
 #include <uchar.h>
+#include <sys/mount.h>
 #include <sys/stat.h>
+#include <linux/fs.h>
 '''
 
 foreach decl : ['char16_t',
                 'char32_t',
+                'struct mount_attr',
                 'struct statx',
                ]
 
@@ -499,6 +512,8 @@ foreach ident : [
                                  #include <unistd.h>'''],
         ['pivot_root',        '''#include <stdlib.h>
                                  #include <unistd.h>'''],     # no known header declares pivot_root
+        ['ioprio_get',        '''#include <sched.h>'''],      # no known header declares ioprio_get
+        ['ioprio_set',        '''#include <sched.h>'''],      # no known header declares ioprio_set
         ['name_to_handle_at', '''#include <sys/types.h>
                                  #include <sys/stat.h>
                                  #include <fcntl.h>'''],
@@ -534,7 +549,14 @@ foreach ident : [
                                  #include <signal.h>
                                  #include <sys/wait.h>'''],
         ['mallinfo',          '''#include <malloc.h>'''],
+        ['mallinfo2',         '''#include <malloc.h>'''],
+        ['execveat',          '''#include <unistd.h>'''],
         ['close_range',       '''#include <unistd.h>'''],
+        ['epoll_pwait2',      '''#include <sys/epoll.h>'''],
+        ['mount_setattr',     '''#include <sys/mount.h>'''],
+        ['move_mount',        '''#include <sys/mount.h>'''],
+        ['open_tree',         '''#include <sys/mount.h>'''],
+        ['getdents64',        '''#include <dirent.h>'''],
 ]
 
         have = cc.has_function(ident[0], prefix : ident[1], args : '-D_GNU_SOURCE')
@@ -552,32 +574,44 @@ endif
 
 #####################################################################
 
-vcs_tagger = [project_source_root + '/tools/meson-vcs-tag.sh',
-              project_source_root,
-              get_option('version-tag'),
-              meson.project_version()]
+version_tag = get_option('version-tag')
+if version_tag != ''
+        vcs_data = configuration_data()
+        vcs_data.set('VCS_TAG', version_tag)
+        version_h = configure_file(configuration : vcs_data,
+                                   input : 'src/version/version.h.in',
+                                   output : 'version.h')
+else
+        vcs_tagger = [
+                project_source_root + '/tools/meson-vcs-tag.sh',
+                project_source_root,
+                meson.project_version()]
 
-version_h = vcs_tag(
-        input : 'src/version/version.h.in',
-        output : 'version.h',
-        command: vcs_tagger)
+        version_h = vcs_tag(
+                input : 'src/version/version.h.in',
+                output : 'version.h',
+                command: vcs_tagger)
+endif
 
 versiondep = declare_dependency(sources: version_h)
 
+sh = find_program('sh')
+echo = find_program('echo')
 sed = find_program('sed')
 awk = find_program('awk')
-m4 = find_program('m4')
 stat = find_program('stat')
+ln = find_program('ln')
 git = find_program('git', required : false)
 env = find_program('env')
 perl = find_program('perl', required : false)
-
+rsync = find_program('rsync', required : false)
 meson_make_symlink = project_source_root + '/tools/meson-make-symlink.sh'
-mkdir_p = 'mkdir -p $DESTDIR/@0@'
 test_efi_create_disk_sh = find_program('test/test-efi-create-disk.sh')
+
+mkdir_p = 'mkdir -p $DESTDIR/@0@'
 splash_bmp = files('test/splash.bmp')
 
-# if -Dxxx-path option is found, use that. Otherwise, check in $PATH,
+# If -Dxxx-path option is found, use that. Otherwise, check in $PATH,
 # /usr/sbin, /sbin, and fall back to the default from middle column.
 progs = [['quotaon',    '/usr/sbin/quotaon'    ],
          ['quotacheck', '/usr/sbin/quotacheck' ],
@@ -603,17 +637,22 @@ foreach prog : progs
         endif
         name = prog.length() > 2 ? prog[2] : prog[0].to_upper()
         conf.set_quoted(name, path)
-        substs.set(name, path)
 endforeach
 
 conf.set_quoted('TELINIT', get_option('telinit-path'))
 
-if run_command('ln', '--relative', '--help').returncode() != 0
+if run_command(ln, '--relative', '--help', check : false).returncode() != 0
         error('ln does not support --relative (added in coreutils 8.16)')
 endif
 
 ############################################################
 
+if run_command('python3', '-c', 'import jinja2', check : false).returncode() != 0
+        error('python3 jinja2 missing')
+endif
+
+############################################################
+
 gperf = find_program('gperf')
 
 gperf_test_format = '''
@@ -622,7 +661,8 @@ const char * in_word_set(const char *, @0@);
 @1@
 '''
 gperf_snippet_format = 'echo foo,bar | @0@ -L ANSI-C'
-gperf_snippet = run_command('sh', '-c', gperf_snippet_format.format(gperf.path()))
+gperf_snippet = run_command(sh, '-c', gperf_snippet_format.format(gperf.path()),
+                            check : true)
 gperf_test = gperf_test_format.format('size_t', gperf_snippet.stdout())
 if cc.compiles(gperf_test)
         gperf_len_type = 'size_t'
@@ -649,6 +689,8 @@ foreach header : ['crypt.h',
                   'sys/auxv.h',
                   'valgrind/memcheck.h',
                   'valgrind/valgrind.h',
+                  'linux/time_types.h',
+                  'sys/sdt.h',
                  ]
 
         conf.set10('HAVE_' + header.underscorify().to_upper(),
@@ -665,9 +707,6 @@ if fallback_hostname == '' or fallback_hostname[0] == '.' or fallback_hostname[0
 endif
 conf.set_quoted('FALLBACK_HOSTNAME', fallback_hostname)
 
-conf.set10('ENABLE_COMPAT_GATEWAY_HOSTNAME', get_option('compat-gateway-hostname'))
-gateway_hostnames = ['_gateway'] + (conf.get('ENABLE_COMPAT_GATEWAY_HOSTNAME') == 1 ? ['gateway'] : [])
-
 default_hierarchy = get_option('default-hierarchy')
 conf.set_quoted('DEFAULT_HIERARCHY_NAME', default_hierarchy,
                 description : 'default cgroup hierarchy as string')
@@ -679,25 +718,56 @@ else
         conf.set('DEFAULT_HIERARCHY', 'CGROUP_UNIFIED_ALL')
 endif
 
+extra_net_naming_schemes = []
+extra_net_naming_map = []
+foreach scheme: get_option('extra-net-naming-schemes').split(',')
+        if scheme != ''
+                name = scheme.split('=')[0]
+                value = scheme.split('=')[1]
+                NAME = name.underscorify().to_upper()
+                VALUE = []
+                foreach field: value.split('+')
+                        VALUE += 'NAMING_' + field.underscorify().to_upper()
+                endforeach
+                extra_net_naming_schemes += 'NAMING_@0@ = @1@,'.format(NAME, '|'.join(VALUE))
+                extra_net_naming_map += '{ "@0@", NAMING_@1@ },'.format(name, NAME)
+        endif
+endforeach
+conf.set('EXTRA_NET_NAMING_SCHEMES', ' '.join(extra_net_naming_schemes))
+conf.set('EXTRA_NET_NAMING_MAP', ' '.join(extra_net_naming_map))
+
 default_net_naming_scheme = get_option('default-net-naming-scheme')
 conf.set_quoted('DEFAULT_NET_NAMING_SCHEME', default_net_naming_scheme)
+if default_net_naming_scheme != 'latest'
+        conf.set('_DEFAULT_NET_NAMING_SCHEME_TEST',
+                 'NAMING_' + default_net_naming_scheme.underscorify().to_upper())
+endif
 
 time_epoch = get_option('time-epoch')
 if time_epoch == -1
-        time_epoch = run_command('sh', ['-c', 'echo "$SOURCE_DATE_EPOCH"']).stdout().strip()
-        if time_epoch == '' and git.found() and run_command('test', '-e', '.git').returncode() == 0
+        time_epoch = run_command(sh, '-c', 'echo "$SOURCE_DATE_EPOCH"', check : true).stdout().strip()
+        if time_epoch == '' and git.found() and fs.exists('.git')
                 # If we're in a git repository, use the creation time of the latest git tag.
-                latest_tag = run_command('git', 'describe', '--abbrev=0', '--tags').stdout().strip()
-                time_epoch = run_command('git', 'log', '-1', '--format=%at', latest_tag).stdout()
+                latest_tag = run_command(git, 'describe', '--abbrev=0', '--tags',
+                                         check : false)
+                if latest_tag.returncode() == 0
+                        time_epoch = run_command(
+                                git, 'log', '--no-show-signature', '-1', '--format=%at',
+                                     latest_tag.stdout().strip(),
+                                check : false).stdout()
+                endif
         endif
         if time_epoch == ''
                 NEWS = files('NEWS')
-                time_epoch = run_command(stat, '-c', '%Y', NEWS).stdout()
+                time_epoch = run_command(stat, '-c', '%Y', NEWS,
+                                         check : true).stdout()
         endif
         time_epoch = time_epoch.to_int()
 endif
 conf.set('TIME_EPOCH', time_epoch)
 
+conf.set('CLOCK_VALID_RANGE_USEC_MAX', get_option('clock-valid-range-usec-max'))
+
 foreach tuple : [['system-alloc-uid-min', 'SYS_UID_MIN', 1],  # Also see login.defs(5).
                  ['system-uid-max',       'SYS_UID_MAX', 999],
                  ['system-alloc-gid-min', 'SYS_GID_MIN', 1],
@@ -707,7 +777,8 @@ foreach tuple : [['system-alloc-uid-min', 'SYS_UID_MIN', 1],  # Also see login.d
                 v = run_command(
                         awk,
                         '/^\s*@0@\s+/ { uid=$2 } END { print uid }'.format(tuple[1]),
-                        '/etc/login.defs').stdout().strip()
+                        '/etc/login.defs',
+                        check : false).stdout().strip()
                 if v == ''
                         v = tuple[2]
                 else
@@ -715,7 +786,6 @@ foreach tuple : [['system-alloc-uid-min', 'SYS_UID_MIN', 1],  # Also see login.d
                 endif
         endif
         conf.set(tuple[0].underscorify().to_upper(), v)
-        substs.set(tuple[0].underscorify().to_upper(), v)
 endforeach
 if conf.get('SYSTEM_ALLOC_UID_MIN') >= conf.get('SYSTEM_UID_MAX')
         error('Invalid uid allocation range')
@@ -728,21 +798,17 @@ dynamic_uid_min = get_option('dynamic-uid-min')
 dynamic_uid_max = get_option('dynamic-uid-max')
 conf.set('DYNAMIC_UID_MIN', dynamic_uid_min)
 conf.set('DYNAMIC_UID_MAX', dynamic_uid_max)
-substs.set('dynamicuidmin', dynamic_uid_min)
-substs.set('dynamicuidmax', dynamic_uid_max)
 
 container_uid_base_min = get_option('container-uid-base-min')
 container_uid_base_max = get_option('container-uid-base-max')
 conf.set('CONTAINER_UID_BASE_MIN', container_uid_base_min)
 conf.set('CONTAINER_UID_BASE_MAX', container_uid_base_max)
-substs.set('containeruidbasemin', container_uid_base_min)
-substs.set('containeruidbasemax', container_uid_base_max)
 
 nobody_user = get_option('nobody-user')
 nobody_group = get_option('nobody-group')
 
 if not meson.is_cross_build()
-        getent_result = run_command('getent', 'passwd', '65534')
+        getent_result = run_command('getent', 'passwd', '65534', check : false)
         if getent_result.returncode() == 0
                 name = getent_result.stdout().split(':')[0]
                 if name != nobody_user
@@ -751,7 +817,7 @@ if not meson.is_cross_build()
                                 'Your build will result in an user table setup that is incompatible with the local system.')
                 endif
         endif
-        id_result = run_command('id', '-u', nobody_user)
+        id_result = run_command('id', '-u', nobody_user, check : false)
         if id_result.returncode() == 0
                 id = id_result.stdout().to_int()
                 if id != 65534
@@ -761,7 +827,7 @@ if not meson.is_cross_build()
                 endif
         endif
 
-        getent_result = run_command('getent', 'group', '65534')
+        getent_result = run_command('getent', 'group', '65534', check : false)
         if getent_result.returncode() == 0
                 name = getent_result.stdout().split(':')[0]
                 if name != nobody_group
@@ -770,12 +836,12 @@ if not meson.is_cross_build()
                                 'Your build will result in an group table setup that is incompatible with the local system.')
                 endif
         endif
-        id_result = run_command('id', '-g', nobody_group)
+        id_result = run_command('id', '-g', nobody_group, check : false)
         if id_result.returncode() == 0
                 id = id_result.stdout().to_int()
                 if id != 65534
                         warning('\n' +
-                                'The local group with the configured group name "@0@" of the nobody group does not have UID 65534 (it has @1@).\n'.format(nobody_group, id) +
+                                '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) +
                                 'Your build will result in an group table setup that is incompatible with the local system.')
                 endif
         endif
@@ -788,59 +854,83 @@ endif
 
 conf.set_quoted('NOBODY_USER_NAME', nobody_user)
 conf.set_quoted('NOBODY_GROUP_NAME', nobody_group)
-substs.set('NOBODY_USER_NAME', nobody_user)
-substs.set('NOBODY_GROUP_NAME', nobody_group)
-
-tty_gid = get_option('tty-gid')
-conf.set('TTY_GID', tty_gid)
-substs.set('TTY_GID', tty_gid)
 
-# Ensure provided GID argument is numeric, otherwise fall back to default assignment
-users_gid = get_option('users-gid')
-substs.set('USERS_GID', users_gid < 0 ? '-' : users_gid)
+static_ugids = []
+foreach option : ['adm-gid',
+                  'audio-gid',
+                  'cdrom-gid',
+                  'dialout-gid',
+                  'disk-gid',
+                  'input-gid',
+                  'kmem-gid',
+                  'kvm-gid',
+                  'lp-gid',
+                  'render-gid',
+                  'sgx-gid',
+                  'tape-gid',
+                  'tty-gid',
+                  'users-gid',
+                  'utmp-gid',
+                  'video-gid',
+                  'wheel-gid',
+                  'systemd-journal-gid',
+                  'systemd-network-uid',
+                  'systemd-resolve-uid',
+                  'systemd-timesync-uid']
+        name = option.underscorify().to_upper()
+        val = get_option(option)
+
+        # Ensure provided GID argument is numeric, otherwise fall back to default assignment
+        conf.set(name, val >= 0 ? val : '-')
+        if val >= 0
+                static_ugids += '@0@:@1@'.format(option, val)
+        endif
+endforeach
 
 conf.set10('ENABLE_ADM_GROUP', get_option('adm-group'))
 conf.set10('ENABLE_WHEEL_GROUP', get_option('wheel-group'))
 
 dev_kvm_mode = get_option('dev-kvm-mode')
-substs.set('DEV_KVM_MODE', dev_kvm_mode)
+conf.set_quoted('DEV_KVM_MODE', dev_kvm_mode) # FIXME: convert to 0o… notation
 conf.set10('DEV_KVM_UACCESS', dev_kvm_mode != '0666')
 group_render_mode = get_option('group-render-mode')
-substs.set('GROUP_RENDER_MODE', group_render_mode)
+conf.set_quoted('GROUP_RENDER_MODE', group_render_mode)
 conf.set10('GROUP_RENDER_UACCESS', group_render_mode != '0666')
 
 kill_user_processes = get_option('default-kill-user-processes')
 conf.set10('KILL_USER_PROCESSES', kill_user_processes)
-conf.set_quoted('KILL_USER_PROCESSES_YES_NO', kill_user_processes ? 'yes' : 'no')
-substs.set('KILL_USER_PROCESSES', kill_user_processes ? 'yes' : 'no')
 
 dns_servers = get_option('dns-servers')
 conf.set_quoted('DNS_SERVERS', dns_servers)
-substs.set('DNS_SERVERS', dns_servers)
 
 ntp_servers = get_option('ntp-servers')
 conf.set_quoted('NTP_SERVERS', ntp_servers)
-substs.set('NTP_SERVERS', ntp_servers)
 
 default_locale = get_option('default-locale')
 if default_locale == ''
         if not meson.is_cross_build()
                 choose_default_locale_sh = find_program('tools/choose-default-locale.sh')
-                default_locale = run_command(choose_default_locale_sh).stdout().strip()
+                default_locale = run_command(choose_default_locale_sh,
+                                             check : true).stdout().strip()
         else
                 default_locale = 'C.UTF-8'
         endif
 endif
 conf.set_quoted('SYSTEMD_DEFAULT_LOCALE', default_locale)
 
+localegen_path = get_option('localegen-path')
+if localegen_path != ''
+        conf.set_quoted('LOCALEGEN_PATH', localegen_path)
+endif
+conf.set10('HAVE_LOCALEGEN', localegen_path != '')
+
 conf.set_quoted('GETTEXT_PACKAGE', meson.project_name())
 
 service_watchdog = get_option('service-watchdog')
 watchdog_value = service_watchdog == '' ? '' : 'WatchdogSec=' + service_watchdog
-substs.set('SERVICE_WATCHDOG', watchdog_value)
+conf.set_quoted('SERVICE_WATCHDOG', watchdog_value)
 
-substs.set('SUSHELL', get_option('debug-shell'))
-substs.set('DEBUGTTY', get_option('debug-tty'))
+conf.set_quoted('SUSHELL', get_option('debug-shell'))
 conf.set_quoted('DEBUGTTY', get_option('debug-tty'))
 
 enable_debug_hashmap = false
@@ -867,10 +957,6 @@ conf.set10('LOG_TRACE', get_option('log-trace'))
 default_user_path = get_option('user-path')
 if default_user_path != ''
         conf.set_quoted('DEFAULT_USER_PATH', default_user_path)
-        default_user_path_display = default_user_path
-else
-        # meson 0.49 fails when ?: is used in .format()
-        default_user_path_display = '(same as system services)'
 endif
 
 
@@ -899,13 +985,46 @@ if not libcap.found()
         libcap = cc.find_library('cap')
 endif
 
+want_bpf_framework = get_option('bpf-framework')
+bpf_framework_required = want_bpf_framework == 'true'
+
+libbpf = dependency('libbpf', required : bpf_framework_required, version : '>= 0.2')
+conf.set10('HAVE_LIBBPF', libbpf.found())
+
+if want_bpf_framework == 'false'
+        conf.set10('BPF_FRAMEWORK', 0)
+else
+        # Support 'versioned' clang/llvm-strip binaries, as seen on Debian/Ubuntu
+        # (like clang-10/llvm-strip-10)
+        clang_bin = cc.get_id() == 'clang' ? cc.cmd_array()[0] : 'clang'
+        if meson.is_cross_build() or clang_bin.contains('afl-clang') or clang_bin.contains('hfuzz-clang')
+                clang_bin = 'clang'
+        endif
+        clang = find_program(clang_bin, required : bpf_framework_required)
+        if not meson.is_cross_build() and clang.found()
+                llvm_strip_bin = run_command(clang, '--print-prog-name', 'llvm-strip',
+                                             check : true).stdout().strip()
+        else
+                llvm_strip_bin = 'llvm-strip'
+        endif
+        llvm_strip = find_program(llvm_strip_bin, required : bpf_framework_required)
+
+        # Debian installs this in /usr/sbin/ which is not in $PATH.
+        # We check for 'bpftool' first, honouring $PATH, and in /usr/sbin/ for Debian.
+        bpftool = find_program('bpftool', '/usr/sbin/bpftool', required : bpf_framework_required)
+
+        deps_found = libbpf.found() and clang.found() and llvm_strip.found() and bpftool.found()
+        # Can build BPF program from source code in restricted C
+        conf.set10('BPF_FRAMEWORK', deps_found)
+endif
+
 libmount = dependency('mount',
                       version : fuzzer_build ? '>= 0' : '>= 2.30')
 
 want_libfdisk = get_option('fdisk')
 if want_libfdisk != 'false' and not skip_deps
         libfdisk = dependency('fdisk',
-                              version : '>= 2.33',
+                              version : '>= 2.32',
                               required : want_libfdisk == 'true')
         have = libfdisk.found()
 else
@@ -960,9 +1079,10 @@ else
 endif
 conf.set10('HAVE_APPARMOR', have)
 
-smack_run_label = get_option('smack-run-label')
-if smack_run_label != ''
-        conf.set_quoted('SMACK_RUN_LABEL', smack_run_label)
+have = get_option('smack') and get_option('smack-run-label') != ''
+conf.set10('HAVE_SMACK_RUN_LABEL', have)
+if have
+        conf.set_quoted('SMACK_RUN_LABEL', get_option('smack-run-label'))
 endif
 
 want_polkit = get_option('polkit')
@@ -1004,6 +1124,9 @@ want_blkid = get_option('blkid')
 if want_blkid != 'false' and not skip_deps
         libblkid = dependency('blkid', required : want_blkid == 'true')
         have = libblkid.found()
+
+        conf.set10('HAVE_BLKID_PROBE_SET_HINT',
+                   have and cc.has_function('blkid_probe_set_hint', dependencies : libblkid))
 else
         have = false
         libblkid = []
@@ -1047,22 +1170,47 @@ endif
 conf.set10('HAVE_MICROHTTPD', have)
 
 want_libcryptsetup = get_option('libcryptsetup')
+want_libcryptsetup_plugins = get_option('libcryptsetup-plugins')
+
+if want_libcryptsetup_plugins == 'true' and want_libcryptsetup == 'false'
+        error('libcryptsetup-plugins can not be requested without libcryptsetup')
+endif
+
 if want_libcryptsetup != 'false' and not skip_deps
         libcryptsetup = dependency('libcryptsetup',
-                                   version : '>= 2.0.1',
-                                   required : want_libcryptsetup == 'true')
+                                   version : want_libcryptsetup_plugins == 'true' ? '>= 2.4.0' : '>= 2.0.1',
+                                   required : want_libcryptsetup == 'true' or want_libcryptsetup_plugins == 'true')
         have = libcryptsetup.found()
 
-        conf.set10('HAVE_CRYPT_SET_METADATA_SIZE',
-                   have and cc.has_function('crypt_set_metadata_size', dependencies : libcryptsetup))
-        conf.set10('HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY',
-                   have and cc.has_function('crypt_activate_by_signed_key', dependencies : libcryptsetup))
+        foreach ident : ['crypt_set_metadata_size',
+                         'crypt_activate_by_signed_key',
+                         'crypt_token_max']
+                have_ident = have and cc.has_function(
+                        ident,
+                        prefix : '#include <libcryptsetup.h>',
+                        dependencies : libcryptsetup)
+                conf.set10('HAVE_' + ident.to_upper(), have_ident)
+        endforeach
 else
         have = false
         libcryptsetup = []
 endif
 conf.set10('HAVE_LIBCRYPTSETUP', have)
 
+if want_libcryptsetup_plugins != 'false' and not skip_deps
+        have = (cc.has_function(
+                        'crypt_activate_by_token_pin',
+                        prefix : '#include <libcryptsetup.h>',
+                        dependencies : libcryptsetup) and
+                cc.has_function(
+                        'crypt_token_external_path',
+                        prefix : '#include <libcryptsetup.h>',
+                        dependencies : libcryptsetup))
+else
+        have = false
+endif
+conf.set10('HAVE_LIBCRYPTSETUP_PLUGINS', have)
+
 want_libcurl = get_option('libcurl')
 if want_libcurl != 'false' and not skip_deps
         libcurl = dependency('libcurl',
@@ -1074,7 +1222,7 @@ else
         libcurl = []
 endif
 conf.set10('HAVE_LIBCURL', have)
-conf.set10('CURL_NO_OLDIES', get_option('mode') == 'developer')
+conf.set10('CURL_NO_OLDIES', conf.get('BUILD_MODE_DEVELOPER') == 1)
 
 want_libidn = get_option('libidn')
 want_libidn2 = get_option('libidn2')
@@ -1186,11 +1334,26 @@ else
 endif
 conf.set10('HAVE_LIBFIDO2', have)
 
+want_tpm2 = get_option('tpm2')
+if want_tpm2 != 'false' and not skip_deps
+        tpm2 = dependency('tss2-esys tss2-rc tss2-mu',
+                          required : want_tpm2 == 'true')
+        have = tpm2.found()
+else
+        have = false
+        tpm2 = []
+endif
+conf.set10('HAVE_TPM2', have)
+
 want_elfutils = get_option('elfutils')
 if want_elfutils != 'false' and not skip_deps
         libdw = dependency('libdw',
                            required : want_elfutils == 'true')
         have = libdw.found()
+
+        # New in elfutils 0.177
+        conf.set10('HAVE_DWELF_ELF_E_MACHINE_STRING',
+                   have and cc.has_function('dwelf_elf_e_machine_string', dependencies : libdw))
 else
         have = false
         libdw = []
@@ -1310,21 +1473,25 @@ else
 endif
 conf.set10('HAVE_DBUS', have)
 
-default_dnssec = get_option('default-dnssec')
-if skip_deps
-        default_dnssec = 'no'
-endif
-if default_dnssec != 'no' and conf.get('HAVE_GCRYPT') == 0
-        message('default-dnssec cannot be set to yes or allow-downgrade when gcrypt is disabled. Setting default-dnssec to no.')
-        default_dnssec = 'no'
+# We support one or the other. If gcrypt is available, we assume it's there to
+# be used, and use it in preference.
+opt = get_option('cryptolib')
+if opt == 'openssl' and conf.get('HAVE_OPENSSL') == 0
+        error('openssl requested as the default cryptolib, but not available')
 endif
-conf.set('DEFAULT_DNSSEC_MODE',
-         'DNSSEC_' + default_dnssec.underscorify().to_upper())
-substs.set('DEFAULT_DNSSEC_MODE', default_dnssec)
+conf.set10('PREFER_OPENSSL',
+           opt == 'openssl' or (opt == 'auto' and conf.get('HAVE_OPENSSL') == 1 and conf.get('HAVE_GCRYPT') == 0))
+conf.set10('HAVE_OPENSSL_OR_GCRYPT',
+           conf.get('HAVE_OPENSSL') == 1 or conf.get('HAVE_GCRYPT') == 1)
+lib_openssl_or_gcrypt = conf.get('PREFER_OPENSSL') == 1 ? [libopenssl] : [libgcrypt, libgpg_error]
 
 dns_over_tls = get_option('dns-over-tls')
 if dns_over_tls != 'false'
-        if dns_over_tls == 'openssl'
+        if dns_over_tls == 'gnutls' and conf.get('PREFER_OPENSSL') == 1
+                error('Sorry, -Ddns-over-tls=gnutls is not supported when openssl is used as the cryptolib')
+        endif
+
+        if dns_over_tls == 'openssl' or conf.get('PREFER_OPENSSL') == 1
                 have_gnutls = false
         else
                 have_gnutls = (conf.get('HAVE_GNUTLS') == 1 and libgnutls.version().version_compare('>= 3.6.0'))
@@ -1361,22 +1528,21 @@ if default_dns_over_tls != 'no' and conf.get('ENABLE_DNS_OVER_TLS') == 0
 endif
 conf.set('DEFAULT_DNS_OVER_TLS_MODE',
          'DNS_OVER_TLS_' + default_dns_over_tls.underscorify().to_upper())
-substs.set('DEFAULT_DNS_OVER_TLS_MODE', default_dns_over_tls)
+conf.set_quoted('DEFAULT_DNS_OVER_TLS_MODE_STR', default_dns_over_tls)
 
 default_mdns = get_option('default-mdns')
 conf.set('DEFAULT_MDNS_MODE',
          'RESOLVE_SUPPORT_' + default_mdns.to_upper())
-substs.set('DEFAULT_MDNS_MODE', default_mdns)
+conf.set_quoted('DEFAULT_MDNS_MODE_STR', default_mdns)
 
 default_llmnr = get_option('default-llmnr')
 conf.set('DEFAULT_LLMNR_MODE',
          'RESOLVE_SUPPORT_' + default_llmnr.to_upper())
-substs.set('DEFAULT_LLMNR_MODE', default_llmnr)
+conf.set_quoted('DEFAULT_LLMNR_MODE_STR', default_llmnr)
 
 want_repart = get_option('repart')
 if want_repart != 'false'
-        have = (conf.get('HAVE_OPENSSL') == 1 and
-                conf.get('HAVE_LIBFDISK') == 1)
+        have = conf.get('HAVE_LIBFDISK') == 1
         if want_repart == 'true' and not have
                 error('repart support was requested, but dependencies are not available')
         endif
@@ -1385,12 +1551,24 @@ else
 endif
 conf.set10('ENABLE_REPART', have)
 
+default_dnssec = get_option('default-dnssec')
+if skip_deps
+        default_dnssec = 'no'
+endif
+if default_dnssec != 'no' and conf.get('HAVE_OPENSSL_OR_GCRYPT') == 0
+        message('default-dnssec cannot be set to yes or allow-downgrade openssl and gcrypt are disabled. Setting default-dnssec to no.')
+        default_dnssec = 'no'
+endif
+conf.set('DEFAULT_DNSSEC_MODE',
+         'DNSSEC_' + default_dnssec.underscorify().to_upper())
+conf.set_quoted('DEFAULT_DNSSEC_MODE_STR', default_dnssec)
+
 want_importd = get_option('importd')
 if want_importd != 'false'
         have = (conf.get('HAVE_LIBCURL') == 1 and
+                conf.get('HAVE_OPENSSL_OR_GCRYPT') == 1 and
                 conf.get('HAVE_ZLIB') == 1 and
-                conf.get('HAVE_XZ') == 1 and
-                conf.get('HAVE_GCRYPT') == 1)
+                conf.get('HAVE_XZ') == 1)
         if want_importd == 'true' and not have
                 error('importd support was requested, but dependencies are not available')
         endif
@@ -1416,16 +1594,7 @@ have = have and conf.get('HAVE_PAM') == 1
 conf.set10('ENABLE_PAM_HOME', have)
 
 have = get_option('oomd')
-if have == 'auto'
-        have = get_option('mode') == 'developer'
-else
-        have = have == 'true'
-        if have and get_option('mode') != 'developer'
-                warning('oomd is not ready for release mode (yet)')
-        endif
-endif
 conf.set10('ENABLE_OOMD', have)
-substs.set10('ENABLE_OOMD', have)
 
 want_remote = get_option('remote')
 if want_remote != 'false'
@@ -1459,6 +1628,7 @@ foreach term : ['analyze',
                 'ima',
                 'initrd',
                 'compat-mutable-uid-boundaries',
+                'nscd',
                 'ldconfig',
                 'localed',
                 'logind',
@@ -1467,6 +1637,7 @@ foreach term : ['analyze',
                 'nss-myhostname',
                 'nss-systemd',
                 'portabled',
+                'sysext',
                 'pstore',
                 'quotacheck',
                 'randomseed',
@@ -1485,7 +1656,6 @@ foreach term : ['analyze',
         have = get_option(term)
         name = 'ENABLE_' + term.underscorify().to_upper()
         conf.set10(name, have)
-        substs.set10(name, have)
 endforeach
 
 enable_sysusers = conf.get('ENABLE_SYSUSERS') == 1
@@ -1518,111 +1688,99 @@ conf.set10('ENABLE_NSS', enable_nss)
 
 conf.set10('ENABLE_TIMEDATECTL', get_option('timedated') or get_option('timesyncd'))
 
+conf.set10('SYSTEMD_SLOW_TESTS_DEFAULT', slow_tests)
+
+############################################################
+
 tests = []
 fuzzers = []
 
-conf.set10('SYSTEMD_SLOW_TESTS_DEFAULT', slow_tests)
-
-#####################################################################
+############################################################
 
-if get_option('efi')
-        efi_arch = host_machine.cpu_family()
-
-        if efi_arch == 'x86'
-                EFI_MACHINE_TYPE_NAME = 'ia32'
-                gnu_efi_arch = 'ia32'
-        elif efi_arch == 'x86_64'
-                EFI_MACHINE_TYPE_NAME = 'x64'
-                gnu_efi_arch = 'x86_64'
-        elif efi_arch == 'arm'
-                EFI_MACHINE_TYPE_NAME = 'arm'
-                gnu_efi_arch = 'arm'
-        elif efi_arch == 'aarch64'
-                EFI_MACHINE_TYPE_NAME = 'aa64'
-                gnu_efi_arch = 'aarch64'
-        else
-                EFI_MACHINE_TYPE_NAME = ''
-                gnu_efi_arch = ''
-        endif
+# Include these now as they provide gnu-efi detection.
+subdir('src/fundamental')
+subdir('src/boot/efi')
 
-        have = true
-        conf.set_quoted('EFI_MACHINE_TYPE_NAME', EFI_MACHINE_TYPE_NAME)
+############################################################
 
-        conf.set('SD_TPM_PCR', get_option('tpm-pcrindex'))
-else
-        have = false
-endif
-conf.set10('ENABLE_EFI', have)
+generate_gperfs = find_program('tools/generate-gperfs.py')
+make_autosuspend_rules_py = find_program('tools/make-autosuspend-rules.py')
+make_directive_index_py = find_program('tools/make-directive-index.py')
+make_man_index_py = find_program('tools/make-man-index.py')
+meson_render_jinja2 = find_program('tools/meson-render-jinja2.py')
+update_dbus_docs_py = find_program('tools/update-dbus-docs.py')
+update_hwdb_sh = find_program('tools/update-hwdb.sh')
+update_hwdb_autosuspend_sh = find_program('tools/update-hwdb-autosuspend.sh')
+update_syscall_tables_sh = find_program('tools/update-syscall-tables.sh')
+xml_helper_py = find_program('tools/xml_helper.py')
+export_dbus_interfaces_py = find_program('tools/dbus_exporter.py')
 
-#####################################################################
+############################################################
 
 config_h = configure_file(
         output : 'config.h',
         configuration : conf)
 
-meson_apply_m4 = find_program('tools/meson-apply-m4.sh')
-
-includes = include_directories('src/basic',
-                               'src/boot',
-                               'src/core',
-                               'src/home',
-                               'src/journal',
-                               'src/journal-remote',
-                               'src/libsystemd-network',
-                               'src/libsystemd/sd-bus',
-                               'src/libsystemd/sd-device',
-                               'src/libsystemd/sd-event',
-                               'src/libsystemd/sd-hwdb',
-                               'src/libsystemd/sd-id128',
-                               'src/libsystemd/sd-netlink',
-                               'src/libsystemd/sd-network',
-                               'src/libsystemd/sd-resolve',
-                               'src/libudev',
-                               'src/login',
-                               'src/nspawn',
-                               'src/resolve',
-                               'src/shared',
-                               'src/shutdown',
-                               'src/systemd',
-                               'src/time-wait-sync',
-                               'src/timesync',
-                               'src/udev',
-                               'src/xdg-autostart-generator',
-                               '.')
-
 add_project_arguments('-include', 'config.h', language : 'c')
 
-generate_gperfs = find_program('tools/generate-gperfs.py')
+############################################################
+
+# binaries that have --help and are intended for use by humans,
+# usually, but not always, installed in /bin.
+public_programs = []
+
+# D-Bus introspection XML export
+dbus_programs = []
+dbus_interfaces_dir = get_option('dbus-interfaces-dir')
+if dbus_interfaces_dir == ''
+        if not meson.is_cross_build()
+                dbus_interfaces_dir = datadir / 'dbus-1'
+        else
+                message('D-Bus interfaces export is disabled during cross build. Pass path or yes to force enable.')
+                dbus_interfaces_dir = 'no'
+        endif
+elif dbus_interfaces_dir == 'yes'
+        dbus_interfaces_dir = datadir / 'dbus-1'
+endif
+
+basic_includes = include_directories(
+        'src/basic',
+        'src/fundamental',
+        'src/systemd',
+        '.')
+
+libsystemd_includes = [basic_includes, include_directories(
+        'src/libsystemd/sd-bus',
+        'src/libsystemd/sd-device',
+        'src/libsystemd/sd-event',
+        'src/libsystemd/sd-hwdb',
+        'src/libsystemd/sd-id128',
+        'src/libsystemd/sd-journal',
+        'src/libsystemd/sd-netlink',
+        'src/libsystemd/sd-network',
+        'src/libsystemd/sd-resolve')]
+
+includes = [libsystemd_includes, include_directories('src/shared')]
 
 subdir('po')
 subdir('catalog')
-subdir('src/libudev')
-subdir('src/systemd')
 subdir('src/basic')
 subdir('src/libsystemd')
-subdir('src/libsystemd-network')
-subdir('src/journal')
-subdir('src/login')
-
-libjournal_core = static_library(
-        'journal-core',
-        libjournal_core_sources,
-        journald_gperf_c,
-        include_directories : includes,
-        install : false)
+subdir('src/shared')
+subdir('src/udev')
+subdir('src/libudev')
+subdir('src/cryptsetup/cryptsetup-tokens')
 
-libsystemd_sym_path = '@0@/@1@'.format(project_source_root, libsystemd_sym)
 libsystemd = shared_library(
         'systemd',
         disable_mempool_c,
         version : libsystemd_version,
-        include_directories : includes,
+        include_directories : libsystemd_includes,
         link_args : ['-shared',
                      '-Wl,--version-script=' + libsystemd_sym_path],
         link_with : [libbasic,
                      libbasic_gcrypt],
-        link_whole : [libsystemd_static,
-                      libjournal_client],
+        link_whole : [libsystemd_static],
         dependencies : [threads,
                         librt,
                         libxz,
@@ -1632,77 +1790,159 @@ libsystemd = shared_library(
         install : true,
         install_dir : rootlibdir)
 
-static_libsystemd = get_option('static-libsystemd')
-static_libsystemd_pic = static_libsystemd == 'true' or static_libsystemd == 'pic'
-
 install_libsystemd_static = static_library(
         'systemd',
         libsystemd_sources,
-        journal_client_sources,
         basic_sources,
         basic_gcrypt_sources,
+        fundamental_sources,
         disable_mempool_c,
-        include_directories : includes,
+        include_directories : libsystemd_includes,
         build_by_default : static_libsystemd != 'false',
         install : static_libsystemd != 'false',
         install_dir : rootlibdir,
-        pic : static_libsystemd == 'true' or static_libsystemd == 'pic',
+        pic : static_libsystemd_pic,
         dependencies : [threads,
                         librt,
                         libxz,
                         libzstd,
                         liblz4,
+                        libdl,
                         libcap,
                         libblkid,
                         libmount,
-                        libselinux,
-                        libgcrypt],
+                        libgcrypt,
+                        libopenssl],
         c_args : libsystemd_c_args + (static_libsystemd_pic ? [] : ['-fno-PIC']))
 
-############################################################
+libudev = shared_library(
+        'udev',
+        disable_mempool_c,
+        version : libudev_version,
+        include_directories : includes,
+        link_args : ['-shared',
+                     '-Wl,--version-script=' + libudev_sym_path],
+        link_with : [libsystemd_static, libshared_static],
+        link_whole : libudev_basic,
+        dependencies : [threads],
+        link_depends : libudev_sym,
+        install : true,
+        install_dir : rootlibdir)
 
-autosuspend_update_sh = find_program('tools/autosuspend-update.sh')
-hwdb_update_sh = find_program('tools/hwdb-update.sh')
-make_autosuspend_rules_py = find_program('tools/make-autosuspend-rules.py')
-make_directive_index_py = find_program('tools/make-directive-index.py')
-make_man_index_py = find_program('tools/make-man-index.py')
-syscall_names_update_sh = find_program('tools/syscall-names-update.sh')
-xml_helper_py = find_program('tools/xml_helper.py')
-update_dbus_docs_py = find_program('tools/update-dbus-docs.py')
+install_libudev_static = static_library(
+        'udev',
+        basic_sources,
+        fundamental_sources,
+        shared_sources,
+        libsystemd_sources,
+        libudev_sources,
+        disable_mempool_c,
+        include_directories : includes,
+        build_by_default : static_libudev != 'false',
+        install : static_libudev != 'false',
+        install_dir : rootlibdir,
+        link_depends : libudev_sym,
+        dependencies : libshared_deps + [libmount],
+        c_args : static_libudev_pic ? [] : ['-fno-PIC'],
+        pic : static_libudev_pic)
+
+if conf.get('HAVE_LIBCRYPTSETUP_PLUGINS') == 1
+        if conf.get('HAVE_TPM2') == 1
+                cryptsetup_token_systemd_tpm2 = shared_library(
+                        'cryptsetup-token-systemd-tpm2',
+                        cryptsetup_token_systemd_tpm2_sources,
+                        include_directories : includes,
+                        link_args : ['-shared',
+                                     '-Wl,--version-script=' + cryptsetup_token_sym_path],
+                        link_with : [lib_cryptsetup_token_common,
+                                     libshared],
+                        dependencies : [libcryptsetup,
+                                        tpm2,
+                                        versiondep],
+                        link_depends : cryptsetup_token_sym,
+                        install_rpath : rootlibexecdir,
+                        install : true,
+                        install_dir : libcryptsetup_plugins_dir)
+        endif
 
-############################################################
+        if conf.get('HAVE_LIBFIDO2') == 1
+                cryptsetup_token_systemd_fido2 = shared_library(
+                        'cryptsetup-token-systemd-fido2',
+                        cryptsetup_token_systemd_fido2_sources,
+                        include_directories : includes,
+                        link_args : ['-shared',
+                                     '-Wl,--version-script=' + cryptsetup_token_sym_path],
+                        link_with : [lib_cryptsetup_token_common,
+                                     libshared],
+                        dependencies : [libcryptsetup,
+                                        libfido2,
+                                        versiondep],
+                        link_depends : cryptsetup_token_sym,
+                        install_rpath : rootlibexecdir,
+                        install : true,
+                        install_dir : libcryptsetup_plugins_dir)
+        endif
 
-# binaries that have --help and are intended for use by humans,
-# usually, but not always, installed in /bin.
-public_programs = []
+        if conf.get('HAVE_P11KIT') == 1
+                cryptsetup_token_systemd_pkcs11 = shared_library(
+                        'cryptsetup-token-systemd-pkcs11',
+                        cryptsetup_token_systemd_pkcs11_sources,
+                        include_directories : includes,
+                        link_args : ['-shared',
+                                     '-Wl,--version-script=' + cryptsetup_token_sym_path],
+                        link_with : [lib_cryptsetup_token_common,
+                                     libshared],
+                        dependencies : [libcryptsetup,
+                                        libp11kit,
+                                        versiondep],
+                        link_depends : cryptsetup_token_sym,
+                        install_rpath : rootlibexecdir,
+                        install : true,
+                        install_dir : libcryptsetup_plugins_dir)
+        endif
+endif
 
-subdir('src/shared')
+############################################################
+
+# systemd-analyze requires 'libcore'
 subdir('src/core')
-subdir('src/shutdown')
-subdir('src/udev')
-subdir('src/network')
+# systemd-journal-remote requires 'libjournal_core'
+subdir('src/journal')
+# systemd-networkd requires 'libsystemd_network'
+subdir('src/libsystemd-network')
 
 subdir('src/analyze')
-subdir('src/journal-remote')
+subdir('src/busctl')
 subdir('src/coredump')
-subdir('src/pstore')
-subdir('src/oom')
+subdir('src/cryptenroll')
+subdir('src/cryptsetup')
+subdir('src/home')
 subdir('src/hostname')
 subdir('src/import')
-subdir('src/partition')
+subdir('src/journal-remote')
 subdir('src/kernel-install')
 subdir('src/locale')
+subdir('src/login')
 subdir('src/machine')
-subdir('src/portable')
-subdir('src/userdb')
-subdir('src/home')
+subdir('src/network')
 subdir('src/nspawn')
+subdir('src/oom')
+subdir('src/partition')
+subdir('src/portable')
+subdir('src/pstore')
 subdir('src/resolve')
+subdir('src/rpm')
+subdir('src/shutdown')
+subdir('src/sysext')
+subdir('src/systemctl')
 subdir('src/timedate')
 subdir('src/timesync')
 subdir('src/tmpfiles')
+subdir('src/userdb')
 subdir('src/vconsole')
-subdir('src/boot/efi')
+subdir('src/xdg-autostart-generator')
+
+subdir('src/systemd')
 
 subdir('src/test')
 subdir('src/fuzz')
@@ -1723,28 +1963,32 @@ test_dlopen = executable(
         build_by_default : want_tests != 'false')
 
 foreach tuple : [['myhostname', 'ENABLE_NSS_MYHOSTNAME'],
-                 ['systemd',    'ENABLE_NSS_SYSTEMD', 'src/nss-systemd/userdb-glue.c src/nss-systemd/userdb-glue.h src/nss-systemd/nss-systemd.h'],
+                 ['systemd',    'ENABLE_NSS_SYSTEMD', ['nss-systemd.h', 'userdb-glue.c', 'userdb-glue.h']],
                  ['mymachines', 'ENABLE_NSS_MYMACHINES'],
-                 ['resolve',    'ENABLE_NSS_RESOLVE']]
+                 ['resolve',    'ENABLE_NSS_RESOLVE', [], resolve_includes]]
 
         condition = tuple[1] == '' or conf.get(tuple[1]) == 1
         if condition
                 module = tuple[0]
 
                 sym = 'src/nss-@0@/nss-@0@.sym'.format(module)
-                version_script_arg = join_paths(project_source_root, sym)
+                version_script_arg = project_source_root / sym
 
                 sources = ['src/nss-@0@/nss-@0@.c'.format(module)]
                 if tuple.length() > 2
-                        sources += tuple[2].split()
+                        foreach s : tuple[2]
+                                sources += ['src/nss-@0@/@1@'.format(module, s)]
+                        endforeach
                 endif
 
+                incs = tuple.length() > 3 ? tuple[3] : includes
+
                 nss = shared_library(
                         'nss_' + module,
                         sources,
                         disable_mempool_c,
                         version : '2',
-                        include_directories : includes,
+                        include_directories : incs,
                         # Note that we link NSS modules with '-z nodelete' so that mempools never get orphaned
                         link_args : ['-Wl,-z,nodelete',
                                      '-shared',
@@ -1775,7 +2019,7 @@ endforeach
 
 ############################################################
 
-executable(
+dbus_programs += executable(
         'systemd',
         systemd_sources,
         include_directories : includes,
@@ -1793,13 +2037,13 @@ executable(
         install_dir : rootlibexecdir)
 
 meson.add_install_script(meson_make_symlink,
-                         join_paths(rootlibexecdir, 'systemd'),
-                         join_paths(rootsbindir, 'init'))
+                         rootlibexecdir / 'systemd',
+                         rootsbindir / 'init')
 
 public_programs += executable(
         'systemd-analyze',
         systemd_analyze_sources,
-        include_directories : includes,
+        include_directories : core_includes,
         link_with : [libcore,
                      libshared],
         dependencies : [versiondep,
@@ -1879,16 +2123,22 @@ executable(
         install : true,
         install_dir : systemgeneratordir)
 
-executable(
+exe = executable(
         'systemd-fstab-generator',
         'src/fstab-generator/fstab-generator.c',
         include_directories : includes,
-        link_with : [libcore_shared,
-                     libshared],
+        link_with : [libshared],
         install_rpath : rootlibexecdir,
         install : true,
         install_dir : systemgeneratordir)
 
+if want_tests != 'false'
+        test('test-fstab-generator',
+             test_fstab_generator_sh,
+             # https://github.com/mesonbuild/meson/issues/2681
+             args : exe.full_path())
+endif
+
 if conf.get('ENABLE_ENVIRONMENT_D') == 1
         executable(
                 '30-systemd-environment-d-generator',
@@ -1900,8 +2150,8 @@ if conf.get('ENABLE_ENVIRONMENT_D') == 1
                 install_dir : userenvgeneratordir)
 
         meson.add_install_script(meson_make_symlink,
-                                 join_paths(sysconfdir, 'environment'),
-                                 join_paths(environmentdir, '99-environment.conf'))
+                                 sysconfdir / 'environment',
+                                 environmentdir / '99-environment.conf')
 endif
 
 if conf.get('ENABLE_HIBERNATE') == 1
@@ -1928,7 +2178,6 @@ if conf.get('HAVE_BLKID') == 1
         executable(
                 'systemd-gpt-auto-generator',
                 'src/gpt-auto-generator/gpt-auto-generator.c',
-                'src/shared/blkid-util.h',
                 include_directories : includes,
                 link_with : [libshared],
                 dependencies : libblkid,
@@ -1946,10 +2195,10 @@ if conf.get('HAVE_BLKID') == 1
 endif
 
 if conf.get('ENABLE_RESOLVE') == 1
-        executable(
+        dbus_programs += executable(
                 'systemd-resolved',
                 systemd_resolved_sources,
-                include_directories : includes,
+                include_directories : resolve_includes,
                 link_with : [libshared,
                              libbasic_gcrypt,
                              libsystemd_resolve_core],
@@ -1966,23 +2215,23 @@ if conf.get('ENABLE_RESOLVE') == 1
                              libbasic_gcrypt,
                              libsystemd_resolve_core],
                 dependencies : [threads,
-                                libgpg_error,
+                                lib_openssl_or_gcrypt,
                                 libm,
                                 libidn],
                 install_rpath : rootlibexecdir,
                 install : true)
 
         meson.add_install_script(meson_make_symlink,
-                                 join_paths(bindir, 'resolvectl'),
-                                 join_paths(rootsbindir, 'resolvconf'))
+                                 bindir / 'resolvectl',
+                                 rootsbindir / 'resolvconf')
 
         meson.add_install_script(meson_make_symlink,
-                                 join_paths(bindir, 'resolvectl'),
-                                 join_paths(bindir, 'systemd-resolve'))
+                                 bindir / 'resolvectl',
+                                 bindir / 'systemd-resolve')
 endif
 
 if conf.get('ENABLE_LOGIND') == 1
-        executable(
+        dbus_programs += executable(
                 'systemd-logind',
                 systemd_logind_sources,
                 include_directories : includes,
@@ -2017,7 +2266,7 @@ if conf.get('ENABLE_LOGIND') == 1
                 install_dir : rootbindir)
 
         if conf.get('HAVE_PAM') == 1
-                version_script_arg = join_paths(project_source_root, pam_systemd_sym)
+                version_script_arg = project_source_root / pam_systemd_sym
                 pam_systemd = shared_library(
                         'pam_systemd',
                         pam_systemd_c,
@@ -2063,12 +2312,18 @@ if conf.get('HAVE_PAM') == 1
                 install_dir : rootlibexecdir)
 endif
 
-if conf.get('ENABLE_EFI') == 1 and conf.get('HAVE_BLKID') == 1
+if conf.get('HAVE_BLKID') == 1 and conf.get('HAVE_GNU_EFI') == 1
+        if get_option('link-boot-shared')
+                boot_link_with = [libshared]
+        else
+                boot_link_with = [libsystemd_static, libshared_static]
+        endif
+
         public_programs += executable(
                 'bootctl',
                 'src/boot/bootctl.c',
                 include_directories : includes,
-                link_with : [libshared],
+                link_with : [boot_link_with],
                 dependencies : [libblkid],
                 install_rpath : rootlibexecdir,
                 install : true)
@@ -2077,7 +2332,7 @@ if conf.get('ENABLE_EFI') == 1 and conf.get('HAVE_BLKID') == 1
                 'systemd-bless-boot',
                 'src/boot/bless-boot.c',
                 include_directories : includes,
-                link_with : [libshared],
+                link_with : [boot_link_with],
                 dependencies : [libblkid],
                 install_rpath : rootlibexecdir,
                 install : true,
@@ -2087,7 +2342,7 @@ if conf.get('ENABLE_EFI') == 1 and conf.get('HAVE_BLKID') == 1
                 'systemd-bless-boot-generator',
                 'src/boot/bless-boot-generator.c',
                 include_directories : includes,
-                link_with : [libshared],
+                link_with : [boot_link_with],
                 install_rpath : rootlibexecdir,
                 install : true,
                 install_dir : systemgeneratordir)
@@ -2112,88 +2367,9 @@ public_programs += executable(
         install_rpath : rootlibexecdir,
         install : true)
 
-if get_option('link-systemctl-shared')
-        systemctl_link_with = [libshared]
-else
-        systemctl_link_with = [libsystemd_static,
-                               libshared_static,
-                               libjournal_client,
-                               libbasic_gcrypt]
-endif
-
 public_programs += executable(
         'systemctl',
-        'src/systemctl/systemctl-add-dependency.c',
-        'src/systemctl/systemctl-add-dependency.h',
-        'src/systemctl/systemctl-cancel-job.c',
-        'src/systemctl/systemctl-cancel-job.h',
-        'src/systemctl/systemctl-clean-or-freeze.c',
-        'src/systemctl/systemctl-clean-or-freeze.h',
-        'src/systemctl/systemctl-compat-halt.c',
-        'src/systemctl/systemctl-compat-halt.h',
-        'src/systemctl/systemctl-compat-runlevel.c',
-        'src/systemctl/systemctl-compat-runlevel.h',
-        'src/systemctl/systemctl-compat-shutdown.c',
-        'src/systemctl/systemctl-compat-shutdown.h',
-        'src/systemctl/systemctl-compat-telinit.c',
-        'src/systemctl/systemctl-compat-telinit.h',
-        'src/systemctl/systemctl-daemon-reload.c',
-        'src/systemctl/systemctl-daemon-reload.h',
-        'src/systemctl/systemctl-edit.c',
-        'src/systemctl/systemctl-edit.h',
-        'src/systemctl/systemctl-enable.c',
-        'src/systemctl/systemctl-enable.h',
-        'src/systemctl/systemctl-is-active.c',
-        'src/systemctl/systemctl-is-active.h',
-        'src/systemctl/systemctl-is-enabled.c',
-        'src/systemctl/systemctl-is-enabled.h',
-        'src/systemctl/systemctl-is-system-running.c',
-        'src/systemctl/systemctl-is-system-running.h',
-        'src/systemctl/systemctl-kill.c',
-        'src/systemctl/systemctl-kill.h',
-        'src/systemctl/systemctl-list-dependencies.c',
-        'src/systemctl/systemctl-list-dependencies.h',
-        'src/systemctl/systemctl-list-jobs.c',
-        'src/systemctl/systemctl-list-jobs.h',
-        'src/systemctl/systemctl-list-machines.c',
-        'src/systemctl/systemctl-list-machines.h',
-        'src/systemctl/systemctl-list-unit-files.c',
-        'src/systemctl/systemctl-list-unit-files.h',
-        'src/systemctl/systemctl-list-units.c',
-        'src/systemctl/systemctl-list-units.h',
-        'src/systemctl/systemctl-log-setting.c',
-        'src/systemctl/systemctl-log-setting.h',
-        'src/systemctl/systemctl-logind.c',
-        'src/systemctl/systemctl-logind.h',
-        'src/systemctl/systemctl-preset-all.c',
-        'src/systemctl/systemctl-preset-all.h',
-        'src/systemctl/systemctl-reset-failed.c',
-        'src/systemctl/systemctl-reset-failed.h',
-        'src/systemctl/systemctl-service-watchdogs.c',
-        'src/systemctl/systemctl-service-watchdogs.h',
-        'src/systemctl/systemctl-set-default.c',
-        'src/systemctl/systemctl-set-default.h',
-        'src/systemctl/systemctl-set-environment.c',
-        'src/systemctl/systemctl-set-environment.h',
-        'src/systemctl/systemctl-set-property.c',
-        'src/systemctl/systemctl-set-property.h',
-        'src/systemctl/systemctl-show.c',
-        'src/systemctl/systemctl-show.h',
-        'src/systemctl/systemctl-start-special.c',
-        'src/systemctl/systemctl-start-special.h',
-        'src/systemctl/systemctl-start-unit.c',
-        'src/systemctl/systemctl-start-unit.h',
-        'src/systemctl/systemctl-switch-root.c',
-        'src/systemctl/systemctl-switch-root.h',
-        'src/systemctl/systemctl-sysv-compat.c',
-        'src/systemctl/systemctl-sysv-compat.h',
-        'src/systemctl/systemctl-trivial-method.c',
-        'src/systemctl/systemctl-trivial-method.h',
-        'src/systemctl/systemctl-util.c',
-        'src/systemctl/systemctl-util.c',
-        'src/systemctl/systemctl-util.h',
-        'src/systemctl/systemctl.c',
-        'src/systemctl/systemctl.h',
+        systemctl_sources,
         include_directories : includes,
         link_with : systemctl_link_with,
         dependencies : [threads,
@@ -2207,12 +2383,12 @@ public_programs += executable(
         install_dir : rootbindir)
 
 if conf.get('ENABLE_PORTABLED') == 1
-        executable(
+        dbus_programs += executable(
                 'systemd-portabled',
                 systemd_portabled_sources,
                 include_directories : includes,
                 link_with : [libshared],
-                dependencies : [threads],
+                dependencies : [threads, libselinux],
                 install_rpath : rootlibexecdir,
                 install : true,
                 install_dir : rootlibexecdir)
@@ -2228,6 +2404,17 @@ if conf.get('ENABLE_PORTABLED') == 1
                 install_dir : rootbindir)
 endif
 
+if conf.get('ENABLE_SYSEXT') == 1
+        public_programs += executable(
+                'systemd-sysext',
+                systemd_sysext_sources,
+                include_directories : includes,
+                link_with : [libshared],
+                install_rpath : rootlibexecdir,
+                install : true,
+                install_dir : rootbindir)
+endif
+
 if conf.get('ENABLE_USERDB') == 1
         executable(
                 'systemd-userwork',
@@ -2267,25 +2454,24 @@ if conf.get('ENABLE_HOMED') == 1
                 include_directories : includes,
                 link_with : [libshared],
                 dependencies : [threads,
-                                libcryptsetup,
                                 libblkid,
                                 libcrypt,
                                 libopenssl,
                                 libfdisk,
-                                libp11kit,
-                                libfido2],
+                                libp11kit],
                 install_rpath : rootlibexecdir,
                 install : true,
                 install_dir : rootlibexecdir)
 
-        executable(
+        dbus_programs += executable(
                 'systemd-homed',
                 systemd_homed_sources,
-                include_directories : includes,
+                include_directories : home_includes,
                 link_with : [libshared],
                 dependencies : [threads,
                                 libcrypt,
-                                libopenssl],
+                                libopenssl,
+                                libm],
                 install_rpath : rootlibexecdir,
                 install : true,
                 install_dir : rootlibexecdir)
@@ -2299,14 +2485,13 @@ if conf.get('ENABLE_HOMED') == 1
                                 libcrypt,
                                 libopenssl,
                                 libp11kit,
-                                libfido2,
                                 libdl],
                 install_rpath : rootlibexecdir,
                 install : true,
                 install_dir : rootbindir)
 
         if conf.get('HAVE_PAM') == 1
-                version_script_arg = join_paths(project_source_root, pam_systemd_home_sym)
+                version_script_arg = project_source_root / pam_systemd_home_sym
                 pam_systemd = shared_library(
                         'pam_systemd_home',
                         pam_systemd_home_c,
@@ -2327,15 +2512,15 @@ if conf.get('ENABLE_HOMED') == 1
 endif
 
 foreach alias : (['halt', 'poweroff', 'reboot', 'shutdown'] +
-                (conf.get('HAVE_SYSV_COMPAT') == 1 ? ['runlevel', 'telinit'] : []))
+                 (conf.get('HAVE_SYSV_COMPAT') == 1 ? ['runlevel', 'telinit'] : []))
         meson.add_install_script(meson_make_symlink,
-                                 join_paths(rootbindir, 'systemctl'),
-                                 join_paths(rootsbindir, alias))
+                                 rootbindir / 'systemctl',
+                                 rootsbindir / alias)
 endforeach
 
 meson.add_install_script(meson_make_symlink,
-                         join_paths(rootbindir, 'udevadm'),
-                         join_paths(rootlibexecdir, 'systemd-udevd'))
+                         rootbindir / 'udevadm',
+                         rootlibexecdir / 'systemd-udevd')
 
 if conf.get('ENABLE_BACKLIGHT') == 1
         executable(
@@ -2369,17 +2554,6 @@ executable(
         install_dir : systemgeneratordir)
 
 if conf.get('HAVE_LIBCRYPTSETUP') == 1
-        systemd_cryptsetup_sources = files('''
-                src/cryptsetup/cryptsetup-pkcs11.h
-                src/cryptsetup/cryptsetup-keyfile.c
-                src/cryptsetup/cryptsetup-keyfile.h
-                src/cryptsetup/cryptsetup.c
-'''.split())
-
-        if conf.get('HAVE_P11KIT') == 1
-                systemd_cryptsetup_sources += files('src/cryptsetup/cryptsetup-pkcs11.c')
-        endif
-
         executable(
                 'systemd-cryptsetup',
                 systemd_cryptsetup_sources,
@@ -2418,6 +2592,37 @@ if conf.get('HAVE_LIBCRYPTSETUP') == 1
                 install_rpath : rootlibexecdir,
                 install : true,
                 install_dir : systemgeneratordir)
+
+        executable(
+                'systemd-cryptenroll',
+                systemd_cryptenroll_sources,
+                include_directories : includes,
+                link_with : [libshared],
+                dependencies : [libcryptsetup,
+                                libdl,
+                                libopenssl,
+                                libp11kit],
+                install_rpath : rootlibexecdir,
+                install : true)
+
+        executable(
+                'systemd-integritysetup',
+                ['src/integritysetup/integritysetup.c', 'src/integritysetup/integrity-util.c'],
+                include_directories : includes,
+                link_with : [libshared],
+                dependencies : [libcryptsetup],
+                install_rpath : rootlibexecdir,
+                install : true,
+                install_dir : rootlibexecdir)
+
+        executable(
+                'systemd-integritysetup-generator',
+                ['src/integritysetup/integritysetup-generator.c', 'src/integritysetup/integrity-util.c'],
+                include_directories : includes,
+                link_with : [libshared],
+                install_rpath : rootlibexecdir,
+                install : true,
+                install_dir : systemgeneratordir)
 endif
 
 if conf.get('HAVE_SYSV_COMPAT') == 1
@@ -2443,8 +2648,7 @@ endif
 if conf.get('ENABLE_XDG_AUTOSTART') == 1
         executable(
                 'systemd-xdg-autostart-generator',
-                'src/xdg-autostart-generator/xdg-autostart-generator.c',
-                'src/xdg-autostart-generator/xdg-autostart-service.c',
+                systemd_xdg_autostart_generator_sources,
                 include_directories : includes,
                 link_with : [libshared],
                 install_rpath : rootlibexecdir,
@@ -2462,7 +2666,7 @@ if conf.get('ENABLE_XDG_AUTOSTART') == 1
 endif
 
 if conf.get('ENABLE_HOSTNAMED') == 1
-        executable(
+        dbus_programs += executable(
                 'systemd-hostnamed',
                 'src/hostname/hostnamed.c',
                 include_directories : includes,
@@ -2482,13 +2686,14 @@ endif
 
 if conf.get('ENABLE_LOCALED') == 1
         if conf.get('HAVE_XKBCOMMON') == 1
-                # logind will load libxkbcommon.so dynamically on its own
-                deps = [libdl]
+                # logind will load libxkbcommon.so dynamically on its own, but we still
+                # need to specify where the headers are
+                deps = [libdl, libxkbcommon.partial_dependency(compile_args: true)]
         else
                 deps = []
         endif
 
-        executable(
+        dbus_programs += executable(
                 'systemd-localed',
                 systemd_localed_sources,
                 include_directories : includes,
@@ -2508,7 +2713,7 @@ if conf.get('ENABLE_LOCALED') == 1
 endif
 
 if conf.get('ENABLE_TIMEDATED') == 1
-        executable(
+        dbus_programs += executable(
                 'systemd-timedated',
                 'src/timedate/timedated.c',
                 include_directories : includes,
@@ -2530,20 +2735,11 @@ if conf.get('ENABLE_TIMEDATECTL') == 1
 endif
 
 if conf.get('ENABLE_TIMESYNCD') == 1
-        if get_option('link-timesyncd-shared')
-                timesyncd_link_with = [libshared]
-        else
-                timesyncd_link_with = [libsystemd_static,
-                                       libshared_static,
-                                       libjournal_client,
-                                       libbasic_gcrypt]
-        endif
-
         executable(
                 'systemd-timesyncd',
                 systemd_timesyncd_sources,
                 include_directories : includes,
-                link_with : [timesyncd_link_with],
+                link_with : [libtimesyncd_core],
                 dependencies : [threads,
                                 libm],
                 install_rpath : rootlibexecdir,
@@ -2552,16 +2748,16 @@ if conf.get('ENABLE_TIMESYNCD') == 1
 
         executable(
                 'systemd-time-wait-sync',
-                'src/time-wait-sync/time-wait-sync.c',
+                'src/timesync/wait-sync.c',
                 include_directories : includes,
-                link_with : [timesyncd_link_with],
+                link_with : [libtimesyncd_core],
                 install_rpath : rootlibexecdir,
                 install : true,
                 install_dir : rootlibexecdir)
 endif
 
 if conf.get('ENABLE_MACHINED') == 1
-        executable(
+        dbus_programs += executable(
                 'systemd-machined',
                 systemd_machined_sources,
                 include_directories : includes,
@@ -2586,7 +2782,7 @@ if conf.get('ENABLE_MACHINED') == 1
 endif
 
 if conf.get('ENABLE_IMPORTD') == 1
-        executable(
+        dbus_programs += executable(
                 'systemd-importd',
                 systemd_importd_sources,
                 include_directories : includes,
@@ -2600,13 +2796,14 @@ if conf.get('ENABLE_IMPORTD') == 1
                 'systemd-pull',
                 systemd_pull_sources,
                 include_directories : includes,
-                link_with : [libshared],
+                link_with : [libshared,
+                             lib_import_common],
                 dependencies : [versiondep,
                                 libcurl,
+                                lib_openssl_or_gcrypt,
                                 libz,
                                 libbzip2,
-                                libxz,
-                                libgcrypt],
+                                libxz],
                 install_rpath : rootlibexecdir,
                 install : true,
                 install_dir : rootlibexecdir)
@@ -2615,7 +2812,8 @@ if conf.get('ENABLE_IMPORTD') == 1
                 'systemd-import',
                 systemd_import_sources,
                 include_directories : includes,
-                link_with : [libshared],
+                link_with : [libshared,
+                             lib_import_common],
                 dependencies : [libcurl,
                                 libz,
                                 libbzip2,
@@ -2628,7 +2826,8 @@ if conf.get('ENABLE_IMPORTD') == 1
                 'systemd-import-fs',
                 systemd_import_fs_sources,
                 include_directories : includes,
-                link_with : [libshared],
+                link_with : [libshared,
+                             lib_import_common],
                 install_rpath : rootlibexecdir,
                 install : true,
                 install_dir : rootlibexecdir)
@@ -2637,7 +2836,8 @@ if conf.get('ENABLE_IMPORTD') == 1
                 'systemd-export',
                 systemd_export_sources,
                 include_directories : includes,
-                link_with : [libshared],
+                link_with : [libshared,
+                             lib_import_common],
                 dependencies : [libcurl,
                                 libz,
                                 libbzip2,
@@ -2671,7 +2871,7 @@ if conf.get('ENABLE_REMOTE') == 1 and conf.get('HAVE_MICROHTTPD') == 1
         public_programs += executable(
                 'systemd-journal-remote',
                 systemd_journal_remote_sources,
-                include_directories : includes,
+                include_directories : journal_includes,
                 link_with : [libshared,
                              libsystemd_journal_remote],
                 dependencies : [threads,
@@ -2687,7 +2887,7 @@ if conf.get('ENABLE_REMOTE') == 1 and conf.get('HAVE_MICROHTTPD') == 1
         public_programs += executable(
                 'systemd-journal-gatewayd',
                 systemd_journal_gatewayd_sources,
-                include_directories : includes,
+                include_directories : journal_includes,
                 link_with : [libshared],
                 dependencies : [threads,
                                 libmicrohttpd,
@@ -2708,7 +2908,6 @@ if conf.get('ENABLE_COREDUMP') == 1
                 link_with : [libshared],
                 dependencies : [threads,
                                 libacl,
-                                libdw,
                                 libxz,
                                 liblz4,
                                 libzstd],
@@ -2737,7 +2936,6 @@ if conf.get('ENABLE_PSTORE') == 1
                 link_with : [libshared],
                 dependencies : [threads,
                                 libacl,
-                                libdw,
                                 libxz,
                                 liblz4,
                                 libzstd],
@@ -2747,7 +2945,7 @@ if conf.get('ENABLE_PSTORE') == 1
 endif
 
 if conf.get('ENABLE_OOMD') == 1
-        executable('systemd-oomd',
+        dbus_programs += executable('systemd-oomd',
                    systemd_oomd_sources,
                    include_directories : includes,
                    link_with : [libshared],
@@ -2757,14 +2955,14 @@ if conf.get('ENABLE_OOMD') == 1
                    install_dir : rootlibexecdir)
 
         public_programs += executable(
-                   'oomctl',
-                   oomctl_sources,
-                   include_directories : includes,
-                   link_with : [libshared],
-                   dependencies : [],
-                   install_rpath : rootlibexecdir,
-                   install : true,
-                   install_dir : rootbindir)
+                'oomctl',
+                oomctl_sources,
+                include_directories : includes,
+                link_with : [libshared],
+                dependencies : [],
+                install_rpath : rootlibexecdir,
+                install : true,
+                install_dir : rootbindir)
 endif
 
 if conf.get('ENABLE_BINFMT') == 1
@@ -2781,7 +2979,7 @@ if conf.get('ENABLE_BINFMT') == 1
                                  mkdir_p.format(binfmtdir))
         if install_sysconfdir
                 meson.add_install_script('sh', '-c',
-                                         mkdir_p.format(join_paths(sysconfdir, 'binfmt.d')))
+                                         mkdir_p.format(sysconfdir / 'binfmt.d'))
         endif
 endif
 
@@ -2793,8 +2991,7 @@ if conf.get('ENABLE_REPART') == 1
                 link_with : [libshared],
                 dependencies : [threads,
                                 libblkid,
-                                libfdisk,
-                                libopenssl],
+                                libfdisk],
                 install_rpath : rootlibexecdir,
                 install : true,
                 install_dir : rootbindir)
@@ -2845,8 +3042,7 @@ executable(
         'systemd-remount-fs',
         'src/remount-fs/remount-fs.c',
         include_directories : includes,
-        link_with : [libcore_shared,
-                     libshared],
+        link_with : [libshared],
         install_rpath : rootlibexecdir,
         install : true,
         install_dir : rootlibexecdir)
@@ -2855,8 +3051,7 @@ executable(
         'systemd-machine-id-setup',
         'src/machine-id-setup/machine-id-setup-main.c',
         include_directories : includes,
-        link_with : [libcore_shared,
-                     libshared],
+        link_with : [libshared],
         install_rpath : rootlibexecdir,
         install : true,
         install_dir : rootbindir)
@@ -2896,7 +3091,7 @@ executable(
         install : true,
         install_dir : rootlibexecdir)
 
-if install_sysconfdir
+if install_sysconfdir_samples
         install_data('src/sleep/sleep.conf',
                      install_dir : pkgsysconfdir)
 endif
@@ -2953,6 +3148,17 @@ public_programs += executable(
         install : true,
         install_dir : rootbindir)
 
+public_programs += executable(
+        'systemd-creds',
+        'src/creds/creds.c',
+        include_directories : includes,
+        link_with : [libshared],
+        dependencies : [threads,
+                        libopenssl],
+        install_rpath : rootlibexecdir,
+        install : true,
+        install_dir : rootbindir)
+
 executable(
         'systemd-volatile-root',
         'src/volatile-root/volatile-root.c',
@@ -3049,7 +3255,7 @@ public_programs += executable(
         install : true)
 
 meson.add_install_script(meson_make_symlink,
-                         'systemd-mount', join_paths(bindir, 'systemd-umount'))
+                         'systemd-mount', bindir / 'systemd-umount')
 
 public_programs += executable(
         'systemd-run',
@@ -3070,9 +3276,7 @@ public_programs += executable(
 
 public_programs += executable(
         'busctl',
-        'src/busctl/busctl.c',
-        'src/busctl/busctl-introspect.c',
-        'src/busctl/busctl-introspect.h',
+        busctl_sources,
         include_directories : includes,
         link_with : [libshared],
         install_rpath : rootlibexecdir,
@@ -3105,8 +3309,7 @@ if enable_sysusers
                         link_with : [libshared_static,
                                      libbasic,
                                      libbasic_gcrypt,
-                                     libsystemd_static,
-                                     libjournal_client],
+                                     libsystemd_static],
                         install : true,
                         install_dir : rootbindir)
                 public_programs += exe
@@ -3148,8 +3351,7 @@ if conf.get('ENABLE_TMPFILES') == 1
                         link_with : [libshared_static,
                                      libbasic,
                                      libbasic_gcrypt,
-                                     libsystemd_static,
-                                     libjournal_client],
+                                     libsystemd_static],
                         dependencies : [libacl],
                         install : true,
                         install_dir : rootbindir)
@@ -3157,15 +3359,22 @@ if conf.get('ENABLE_TMPFILES') == 1
 endif
 
 if conf.get('ENABLE_HWDB') == 1
-        public_programs += executable(
+        systemd_hwdb = executable(
                 'systemd-hwdb',
                 'src/hwdb/hwdb.c',
-                'src/libsystemd/sd-hwdb/hwdb-internal.h',
                 include_directories : includes,
-                link_with : [libudev_static],
+                link_with : udev_link_with,
                 install_rpath : udev_rpath,
                 install : true,
                 install_dir : rootbindir)
+        public_programs += systemd_hwdb
+
+        if want_tests != 'false'
+                test('hwdb-test',
+                     hwdb_test_sh,
+                     args : [systemd_hwdb.full_path()],
+                     timeout : 90)
+        endif
 endif
 
 if conf.get('ENABLE_QUOTACHECK') == 1
@@ -3192,11 +3401,8 @@ public_programs += executable(
 public_programs += executable(
         'udevadm',
         udevadm_sources,
-        c_args : '-DLOG_REALM=LOG_REALM_UDEV',
         include_directories : includes,
-        link_with : [libudev_core,
-                     libsystemd_network,
-                     libudev_static],
+        link_with : [libudevd_core],
         dependencies : [versiondep,
                         threads,
                         libkmod,
@@ -3211,8 +3417,7 @@ executable(
         'systemd-shutdown',
         systemd_shutdown_sources,
         include_directories : includes,
-        link_with : [libcore_shared,
-                     libshared],
+        link_with : [libshared],
         dependencies : [libmount],
         install_rpath : rootlibexecdir,
         install : true,
@@ -3252,7 +3457,7 @@ if conf.get('HAVE_KMOD') == 1
                                  mkdir_p.format(modulesloaddir))
         if install_sysconfdir
                 meson.add_install_script('sh', '-c',
-                                         mkdir_p.format(join_paths(sysconfdir, 'modules-load.d')))
+                                         mkdir_p.format(sysconfdir / 'modules-load.d'))
         endif
 endif
 
@@ -3260,8 +3465,7 @@ public_programs += executable(
         'systemd-nspawn',
         systemd_nspawn_sources,
         include_directories : includes,
-        link_with : [libcore_shared,
-                     libnspawn_core,
+        link_with : [libnspawn_core,
                      libshared],
         dependencies : [libblkid,
                         libseccomp],
@@ -3269,13 +3473,12 @@ public_programs += executable(
         install : true)
 
 if conf.get('ENABLE_NETWORKD') == 1
-        executable(
+        dbus_programs += executable(
                 'systemd-networkd',
                 systemd_networkd_sources,
-                include_directories : network_include_dir,
+                include_directories : network_includes,
                 link_with : [libnetworkd_core,
                              libsystemd_network,
-                             libudev_static,
                              networkd_link_with],
                 dependencies : [threads],
                 install_rpath : rootlibexecdir,
@@ -3286,8 +3489,7 @@ if conf.get('ENABLE_NETWORKD') == 1
                 'systemd-networkd-wait-online',
                 systemd_networkd_wait_online_sources,
                 include_directories : includes,
-                link_with : [libnetworkd_core,
-                             networkd_link_with],
+                link_with : [networkd_link_with],
                 install_rpath : rootlibexecdir,
                 install : true,
                 install_dir : rootlibexecdir)
@@ -3295,33 +3497,33 @@ if conf.get('ENABLE_NETWORKD') == 1
         public_programs += executable(
                 'networkctl',
                 networkctl_sources,
-                include_directories : includes,
+                include_directories : libsystemd_network_includes,
                 link_with : [libsystemd_network,
                              networkd_link_with],
                 install_rpath : rootlibexecdir,
                 install : true,
                 install_dir : rootbindir)
+endif
 
-        exe = executable(
-                'systemd-network-generator',
-                network_generator_sources,
-                include_directories : includes,
-                link_with : [networkd_link_with],
-                install_rpath : rootlibexecdir,
-                install : true,
-                install_dir : rootlibexecdir)
+exe = executable(
+        'systemd-network-generator',
+        network_generator_sources,
+        include_directories : includes,
+        link_with : [networkd_link_with],
+        install_rpath : rootlibexecdir,
+        install : true,
+        install_dir : rootlibexecdir)
 
-        if want_tests != 'false'
-                test('test-network-generator-conversion',
-                     test_network_generator_conversion_sh,
-                     # https://github.com/mesonbuild/meson/issues/2681
-                     args : exe.full_path())
-        endif
+if want_tests != 'false'
+        test('test-network-generator-conversion',
+             test_network_generator_conversion_sh,
+             # https://github.com/mesonbuild/meson/issues/2681
+             args : exe.full_path())
 endif
 
 executable(
         'systemd-sulogin-shell',
-        ['src/sulogin-shell/sulogin-shell.c'],
+        'src/sulogin-shell/sulogin-shell.c',
         include_directories : includes,
         link_with : [libshared],
         install_rpath : rootlibexecdir,
@@ -3333,21 +3535,31 @@ executable(
 custom_target(
         'systemd-runtest.env',
         output : 'systemd-runtest.env',
-        command : ['sh', '-c', '{ ' +
-                   'echo SYSTEMD_TEST_DATA=@0@; '.format(join_paths(project_source_root, 'test')) +
-                   'echo SYSTEMD_CATALOG_DIR=@0@; '.format(join_paths(project_build_root, 'catalog')) +
-                   '} >@OUTPUT@'],
+        command : [sh, '-c',
+                   '{ echo SYSTEMD_TEST_DATA=@0@; echo SYSTEMD_CATALOG_DIR=@1@; } >@OUTPUT@'.format(
+                           project_source_root / 'test',
+                           project_build_root / 'catalog')],
         build_by_default : true)
 
+test_cflags = ['-DTEST_CODE=1']
+# We intentionally do not do inline initializations with definitions for a
+# bunch of _cleanup_ variables in tests, to ensure valgrind is triggered if we
+# use the variable unexpectedly. This triggers a lot of maybe-uninitialized
+# false positives when the combination of -O2 and -flto is used. Suppress them.
+if '-O2' in get_option('c_args') and '-flto=auto' in get_option('c_args')
+        test_cflags += cc.first_supported_argument('-Wno-maybe-uninitialized')
+endif
+
 foreach tuple : tests
         sources = tuple[0]
-        link_with = tuple[1].length() > 0 ? tuple[1] : [libshared]
-        dependencies = tuple[2]
-        condition = tuple.length() >= 4 ? tuple[3] : ''
-        type = tuple.length() >= 5 ? tuple[4] : ''
-        defs = tuple.length() >= 6 ? tuple[5] : []
-        incs = tuple.length() >= 7 ? tuple[6] : includes
-        parallel = tuple.length() >= 8 ? tuple[7] : true
+        link_with = tuple.length() > 1 and tuple[1].length() > 0 ? tuple[1] : [libshared]
+        dependencies = tuple.length() > 2 ? tuple[2] : []
+        incs = tuple.length() > 3 and tuple[3].length() > 0 ? tuple[3] : includes
+        condition = tuple.length() > 4 ? tuple[4] : ''
+        type = tuple.length() > 5 ? tuple[5] : ''
+        defs = tuple.length() > 6 ? tuple[6] : []
+        defs += test_cflags
+        parallel = tuple.length() > 7 ? tuple[7] : true
         timeout = 30
 
         name = sources[0].split('/')[-1].split('.')[0]
@@ -3368,7 +3580,7 @@ foreach tuple : tests
                         build_by_default : want_tests != 'false',
                         install_rpath : rootlibexecdir,
                         install : install_tests,
-                        install_dir : join_paths(testsdir, type))
+                        install_dir : testsdir / type)
 
                 if type == 'manual'
                         message('@0@ is a manual test'.format(name))
@@ -3413,8 +3625,8 @@ endif
 exe = executable(
         'test-libudev-sym',
         test_libudev_sym_c,
-        include_directories : includes,
-        c_args : '-Wno-deprecated-declarations',
+        include_directories : libudev_includes,
+        c_args : ['-Wno-deprecated-declarations'] + test_cflags,
         link_with : [libudev],
         build_by_default : want_tests != 'false',
         install : install_tests,
@@ -3426,8 +3638,8 @@ endif
 exe = executable(
         'test-libudev-static-sym',
         test_libudev_sym_c,
-        include_directories : includes,
-        c_args : '-Wno-deprecated-declarations',
+        include_directories : libudev_includes,
+        c_args : ['-Wno-deprecated-declarations'] + test_cflags,
         link_with : [install_libudev_static],
         build_by_default : want_tests != 'false' and static_libudev_pic,
         install : install_tests and static_libudev_pic,
@@ -3440,48 +3652,61 @@ endif
 
 fuzzer_exes = []
 
-if fuzz_tests or fuzzer_build
-        foreach tuple : fuzzers
-                sources = tuple[0]
-                link_with = tuple[1].length() > 0 ? tuple[1] : [libshared]
-                dependencies = tuple[2]
-                defs = tuple.length() >= 4 ? tuple[3] : []
-                incs = tuple.length() >= 5 ? tuple[4] : includes
-                link_args = []
-
-                if want_ossfuzz
+foreach tuple : fuzzers
+        sources = tuple[0]
+        link_with = tuple.length() > 1 and tuple[1].length() > 0 ? tuple[1] : [libshared]
+        dependencies = tuple.length() > 2 ? tuple[2] : []
+        incs = tuple.length() > 3 and tuple[3].length() > 0 ? tuple[3] : includes
+        defs = tuple.length() > 4 ? tuple[4] : []
+        link_args = []
+
+        if want_ossfuzz
+                dependencies += fuzzing_engine
+        elif want_libfuzzer
+                if fuzzing_engine.found()
                         dependencies += fuzzing_engine
-                elif want_libfuzzer
-                        if fuzzing_engine.found()
-                                dependencies += fuzzing_engine
-                        else
-                                link_args += ['-fsanitize=fuzzer']
-                        endif
                 else
-                        sources += 'src/fuzz/fuzz-main.c'
+                        link_args += ['-fsanitize=fuzzer']
                 endif
+        else
+                sources += 'src/fuzz/fuzz-main.c'
+        endif
 
-                name = sources[0].split('/')[-1].split('.')[0]
+        name = sources[0].split('/')[-1].split('.')[0]
 
-                fuzzer_exes += executable(
-                        name,
-                        sources,
-                        include_directories : [incs, include_directories('src/fuzz')],
-                        link_with : link_with,
-                        dependencies : dependencies,
-                        c_args : defs,
-                        link_args: link_args,
-                        install : false)
-        endforeach
-endif
+        exe = executable(
+                name,
+                sources,
+                include_directories : [incs, include_directories('src/fuzz')],
+                link_with : link_with,
+                dependencies : dependencies,
+                c_args : defs + test_cflags,
+                link_args: link_args,
+                install : false,
+                build_by_default : fuzzer_build)
+        fuzzer_exes += exe
 
-run_target(
-        'fuzzers',
-        depends : fuzzer_exes,
-        command : ['true'])
+        if want_tests != 'false'
+                # Run the fuzz regression tests without any sanitizers enabled.
+                # Additional invocations with sanitizers may be added below.
+                foreach p : fuzz_regression_tests
+                        b = p.split('/')[-2]
+                        c = p.split('/')[-1]
+
+                        if b == name
+                                test('@0@_@1@'.format(b, c),
+                                     exe,
+                                     args : [project_source_root / p])
+                        endif
+                endforeach
+        endif
+endforeach
+
+alias_target('fuzzers', fuzzer_exes)
 
 ############################################################
 
+subdir('modprobe.d')
 subdir('sysctl.d')
 subdir('sysusers.d')
 subdir('tmpfiles.d')
@@ -3502,8 +3727,6 @@ if install_sysconfdir
         install_data('xorg/50-systemd-user.sh',
                      install_dir : xinitrcdir)
 endif
-install_data('modprobe.d/systemd.conf',
-             install_dir : modprobedir)
 install_data('LICENSE.GPL2',
              'LICENSE.LGPL2.1',
              'NEWS',
@@ -3515,14 +3738,32 @@ install_data('LICENSE.GPL2',
              'docs/TRANSIENT-SETTINGS.md',
              'docs/TRANSLATORS.md',
              'docs/UIDS-GIDS.md',
-             'src/libsystemd/sd-bus/GVARIANT-SERIALIZATION',
+             'docs/GVARIANT-SERIALIZATION.md',
              install_dir : docdir)
 
+install_subdir('LICENSES',
+               install_dir : docdir)
+
 meson.add_install_script('sh', '-c', mkdir_p.format(systemdstatedir))
 meson.add_install_script('sh', '-c', 'touch $DESTDIR@0@'.format(prefixdir))
 
 ############################################################
 
+# Ensure that changes to the docs/ directory do not break the
+# basic Github pages build. But only run it in developer mode,
+# as it might be fragile due to changes in the tooling, and it is
+# not generally useful for users.
+jekyll = find_program('jekyll', required : false)
+if get_option('mode') == 'developer' and want_tests != 'false' and jekyll.found()
+        test('github-pages',
+             jekyll,
+             args : ['build',
+                     '--source', project_source_root / 'docs',
+                     '--destination', project_build_root / '_site'])
+endif
+
+############################################################
+
 check_help = find_program('tools/check-help.sh')
 
 foreach exec : public_programs
@@ -3541,7 +3782,7 @@ check_directives_sh = find_program('tools/check-directives.sh')
 if want_tests != 'false'
         test('check-directives',
              check_directives_sh,
-             args : project_source_root)
+             args : [project_source_root, project_build_root])
 endif
 
 ############################################################
@@ -3567,8 +3808,8 @@ foreach tuple : sanitizers
                                                 name,
                                                 output : name,
                                                 depends : build,
-                                                command : [env, 'ln', '-fs',
-                                                           join_paths(build.full_path(), b),
+                                                command : [ln, '-fs',
+                                                           build.full_path() / b,
                                                            '@OUTPUT@'],
                                                 build_by_default : true)
                                 else
@@ -3583,7 +3824,7 @@ foreach tuple : sanitizers
                                      env : ['UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1'],
                                      timeout : 60,
                                      args : [exe.full_path(),
-                                             join_paths(project_source_root, p)])
+                                             project_source_root / p])
                         endif
                 endforeach
         endif
@@ -3594,19 +3835,21 @@ endforeach
 
 if git.found()
         all_files = run_command(
-                git,
-                ['--git-dir=@0@/.git'.format(project_source_root),
-                 'ls-files',
-                 ':/*.[ch]'])
-        all_files = files(all_files.stdout().split())
-
-        custom_target(
-                'tags',
-                output : 'tags',
-                command : [env, 'etags', '-o', '@0@/TAGS'.format(project_source_root)] + all_files)
-        run_target(
-                'ctags',
-                command : [env, 'ctags', '-o', '@0@/tags'.format(project_source_root)] + all_files)
+                env, '-u', 'GIT_WORK_TREE',
+                git, '--git-dir=@0@/.git'.format(project_source_root),
+                     'ls-files', ':/*.[ch]',
+                check : false)
+        if all_files.returncode() == 0
+                all_files = files(all_files.stdout().split())
+
+                custom_target(
+                        'tags',
+                        output : 'tags',
+                        command : [env, 'etags', '-o', '@0@/TAGS'.format(project_source_root)] + all_files)
+                run_target(
+                        'ctags',
+                        command : [env, 'ctags', '-o', '@0@/tags'.format(project_source_root)] + all_files)
+        endif
 endif
 
 if git.found()
@@ -3618,17 +3861,17 @@ endif
 
 if git.found()
         git_head = run_command(
-                git,
-                ['--git-dir=@0@/.git'.format(project_source_root),
-                 'rev-parse', 'HEAD']).stdout().strip()
+                git, '--git-dir=@0@/.git'.format(project_source_root),
+                     'rev-parse', 'HEAD',
+                check : false).stdout().strip()
         git_head_short = run_command(
-                git,
-                ['--git-dir=@0@/.git'.format(project_source_root),
-                 'rev-parse', '--short=7', 'HEAD']).stdout().strip()
+                git, '--git-dir=@0@/.git'.format(project_source_root),
+                     'rev-parse', '--short=7', 'HEAD',
+                check : false).stdout().strip()
 
         run_target(
                 'git-snapshot',
-                command : ['git', 'archive',
+                command : [git, 'archive',
                            '-o', '@0@/systemd-@1@.tar.gz'.format(project_source_root,
                                                                  git_head_short),
                            '--prefix', 'systemd-@0@/'.format(git_head),
@@ -3643,198 +3886,209 @@ run_target(
         depends : [man, libsystemd, libudev],
         command : [check_api_docs_sh, libsystemd.full_path(), libudev.full_path()])
 
+alias_target('update-dbus-docs', update_dbus_docs)
+alias_target('update-man-rules', update_man_rules)
+
+if not meson.is_cross_build()
+        custom_target(
+                'export-dbus-interfaces',
+                output : 'interfaces',
+                install : dbus_interfaces_dir != 'no',
+                install_dir : dbus_interfaces_dir,
+                command : [export_dbus_interfaces_py, '@OUTPUT@', dbus_programs])
+endif
+
 ############################################################
-watchdog_opt = service_watchdog == '' ? 'disabled' : service_watchdog
-
-status = [
-        '@0@ @1@'.format(meson.project_name(), meson.project_version()),
-
-        'build mode:                        @0@'.format(get_option('mode')),
-        'split /usr:                        @0@'.format(split_usr),
-        'split bin-sbin:                    @0@'.format(split_bin),
-        'prefix directory:                  @0@'.format(prefixdir),
-        'rootprefix directory:              @0@'.format(rootprefixdir),
-        'sysconf directory:                 @0@'.format(sysconfdir),
-        'include directory:                 @0@'.format(includedir),
-        'lib directory:                     @0@'.format(libdir),
-        'rootlib directory:                 @0@'.format(rootlibdir),
-        'SysV init scripts:                 @0@'.format(sysvinit_path),
-        'SysV rc?.d directories:            @0@'.format(sysvrcnd_path),
-        'PAM modules directory:             @0@'.format(pamlibdir),
-        'PAM configuration directory:       @0@'.format(pamconfdir),
-        'RPM macros directory:              @0@'.format(rpmmacrosdir),
-        'modprobe.d directory:              @0@'.format(modprobedir),
-        'D-Bus policy directory:            @0@'.format(dbuspolicydir),
-        'D-Bus session directory:           @0@'.format(dbussessionservicedir),
-        'D-Bus system directory:            @0@'.format(dbussystemservicedir),
-        'bash completions directory:        @0@'.format(bashcompletiondir),
-        'zsh completions directory:         @0@'.format(zshcompletiondir),
-        'extra start script:                @0@'.format(get_option('rc-local')),
-        'debug shell:                       @0@ @ @1@'.format(get_option('debug-shell'),
-                                                              get_option('debug-tty')),
-        'TTY GID:                           @0@'.format(tty_gid),
-        'users GID:                         @0@'.format(substs.get('USERS_GID')),
-        'system UIDs:                       <=@0@ (alloc >=@1@)'.format(conf.get('SYSTEM_UID_MAX'),
-                                                                        conf.get('SYSTEM_ALLOC_UID_MIN')),
-        'system GIDs:                       <=@0@ (alloc >=@1@)'.format(conf.get('SYSTEM_GID_MAX'),
-                                                                        conf.get('SYSTEM_ALLOC_GID_MIN')),
-        'dynamic UIDs:                      @0@–@1@'.format(dynamic_uid_min, dynamic_uid_max),
-        'container UID bases:               @0@–@1@'.format(container_uid_base_min, container_uid_base_max),
-        '/dev/kvm access mode:              @0@'.format(get_option('dev-kvm-mode')),
-        'render group access mode:          @0@'.format(get_option('group-render-mode')),
-        'certificate root directory:        @0@'.format(get_option('certificate-root')),
-        'support URL:                       @0@'.format(support_url),
-        'nobody user name:                  @0@'.format(nobody_user),
-        'nobody group name:                 @0@'.format(nobody_group),
-        'fallback hostname:                 @0@'.format(get_option('fallback-hostname')),
-        'symbolic gateway hostnames:        @0@'.format(', '.join(gateway_hostnames)),
-
-        'default DNSSEC mode:               @0@'.format(default_dnssec),
-        'default DNS-over-TLS mode:         @0@'.format(default_dns_over_tls),
-        'default mDNS mode:                 @0@'.format(default_mdns),
-        'default LLMNR mode:                @0@'.format(default_llmnr),
-        'default cgroup hierarchy:          @0@'.format(default_hierarchy),
-        'default net.naming-scheme setting: @0@'.format(default_net_naming_scheme),
-        'default KillUserProcesses setting: @0@'.format(kill_user_processes),
-        'default locale:                    @0@'.format(default_locale),
-        'default user $PATH:                @0@'.format(default_user_path_display),
-        'systemd service watchdog:          @0@'.format(watchdog_opt)]
-
-alt_dns_servers = '\n                                            '.join(dns_servers.split(' '))
-alt_ntp_servers = '\n                                            '.join(ntp_servers.split(' '))
-status += [
-        'default DNS servers:               @0@'.format(alt_dns_servers),
-        'default NTP servers:               @0@'.format(alt_ntp_servers)]
-
-alt_time_epoch = run_command('date', '-Is', '-u', '-d',
-                             '@@0@'.format(time_epoch)).stdout().strip()
-status += [
-        'time epoch:                        @0@ (@1@)'.format(time_epoch, alt_time_epoch)]
-
-status += [
-        'static libsystemd:                 @0@'.format(static_libsystemd),
-        'static libudev:                    @0@'.format(static_libudev)]
+
+alt_time_epoch = run_command('date', '-Is', '-u', '-d', '@@0@'.format(time_epoch),
+                             check : true).stdout().strip()
+
+summary({
+        'build mode' :                      get_option('mode'),
+        'split /usr' :                      split_usr,
+        'split bin-sbin' :                  split_bin,
+        'prefix directory' :                prefixdir,
+        'rootprefix directory' :            rootprefixdir,
+        'sysconf directory' :               sysconfdir,
+        'include directory' :               includedir,
+        'lib directory' :                   libdir,
+        'rootlib directory' :               rootlibdir,
+        'SysV init scripts' :               sysvinit_path,
+        'SysV rc?.d directories' :          sysvrcnd_path,
+        'PAM modules directory' :           pamlibdir,
+        'PAM configuration directory' :     pamconfdir,
+        'libcryptsetup plugins directory' : libcryptsetup_plugins_dir,
+        'RPM macros directory' :            rpmmacrosdir,
+        'modprobe.d directory' :            modprobedir,
+        'D-Bus policy directory' :          dbuspolicydir,
+        'D-Bus session directory' :         dbussessionservicedir,
+        'D-Bus system directory' :          dbussystemservicedir,
+        'bash completions directory' :      bashcompletiondir,
+        'zsh completions directory' :       zshcompletiondir,
+        'extra start script' :              get_option('rc-local'),
+        'debug shell' :                     '@0@ @ @1@'.format(get_option('debug-shell'),
+                                                               get_option('debug-tty')),
+        'system UIDs' :                     '<=@0@ (alloc >=@1@)'.format(conf.get('SYSTEM_UID_MAX'),
+                                                                         conf.get('SYSTEM_ALLOC_UID_MIN')),
+        'system GIDs' :                     '<=@0@ (alloc >=@1@)'.format(conf.get('SYSTEM_GID_MAX'),
+                                                                         conf.get('SYSTEM_ALLOC_GID_MIN')),
+        'dynamic UIDs' :                    '@0@…@1@'.format(dynamic_uid_min, dynamic_uid_max),
+        'container UID bases' :             '@0@…@1@'.format(container_uid_base_min, container_uid_base_max),
+        'static UID/GID allocations' :      ' '.join(static_ugids),
+        '/dev/kvm access mode' :            get_option('dev-kvm-mode'),
+        'render group access mode' :        get_option('group-render-mode'),
+        'certificate root directory' :      get_option('certificate-root'),
+        'support URL' :                     support_url,
+        'nobody user name' :                nobody_user,
+        'nobody group name' :               nobody_group,
+        'fallback hostname' :               get_option('fallback-hostname'),
+        'default DNSSEC mode' :             default_dnssec,
+        'default DNS-over-TLS mode' :       default_dns_over_tls,
+        'default mDNS mode' :               default_mdns,
+        'default LLMNR mode' :              default_llmnr,
+        'default DNS servers' :             dns_servers.split(' '),
+        'default NTP servers' :             ntp_servers.split(' '),
+        'default cgroup hierarchy' :        default_hierarchy,
+        'default net.naming-scheme value' : default_net_naming_scheme,
+        'default KillUserProcesses value' : kill_user_processes,
+        'default locale' :                  default_locale,
+        'default user $PATH' :
+                default_user_path != '' ? default_user_path : '(same as system services)',
+        'systemd service watchdog' :        service_watchdog == '' ? 'disabled' : service_watchdog,
+        'time epoch' :                      '@0@ (@1@)'.format(time_epoch, alt_time_epoch)})
 
 # TODO:
 # CFLAGS:   ${OUR_CFLAGS} ${CFLAGS}
 # CPPFLAGS: ${OUR_CPPFLAGS} ${CPPFLAGS}
 # LDFLAGS:  ${OUR_LDFLAGS} ${LDFLAGS}
 
-if conf.get('ENABLE_EFI') == 1
-        status += 'efi arch:                          @0@'.format(efi_arch)
-
-        if have_gnu_efi
-                status += [
-                        'EFI machine type:                  @0@'.format(EFI_MACHINE_TYPE_NAME),
-                        'EFI CC                             @0@'.format(' '.join(efi_cc)),
-                        'EFI lds:                           @0@'.format(efi_lds),
-                        'EFI crt0:                          @0@'.format(efi_crt0),
-                        'EFI include directory:             @0@'.format(efi_incdir)]
-        endif
+if conf.get('ENABLE_EFI') == 1 and conf.get('HAVE_GNU_EFI') == 1
+        summary({
+                'EFI machine type' :                efi_arch[0],
+                'EFI CC' :                          '@0@'.format(' '.join(efi_cc)),
+                'EFI LD' :                          efi_ld,
+                'EFI lds' :                         efi_lds,
+                'EFI crt0' :                        efi_crt0,
+                'EFI include directory' :           efi_incdir},
+                section : 'Extensible Firmware Interface')
 endif
 
 found = []
 missing = []
 
 foreach tuple : [
-        ['libcryptsetup'],
-        ['PAM'],
-        ['pwquality'],
-        ['libfdisk'],
-        ['p11kit'],
-        ['libfido2'],
+        # dependencies
+        ['ACL'],
         ['AUDIT'],
-        ['IMA'],
         ['AppArmor'],
-        ['SELinux'],
+        ['IMA'],
+        ['PAM'],
         ['SECCOMP'],
+        ['SELinux'],
         ['SMACK'],
-        ['zlib'],
-        ['xz'],
-        ['zstd'],
-        ['lz4'],
-        ['bzip2'],
-        ['ACL'],
+        ['blkid'],
+        ['elfutils'],
         ['gcrypt'],
-        ['qrencode'],
-        ['microhttpd'],
         ['gnutls'],
-        ['openssl'],
+        ['libbpf'],
+        ['libcryptsetup'],
+        ['libcryptsetup-plugins'],
         ['libcurl'],
-        ['idn'],
-        ['initrd'],
-        ['compat-mutable-uid-boundaries'],
-        ['libidn2'],
+        ['libfdisk'],
+        ['libfido2'],
         ['libidn'],
+        ['libidn2'],
         ['libiptc'],
-        ['elfutils'],
+        ['microhttpd'],
+        ['openssl'],
+        ['p11kit'],
+        ['pcre2'],
+        ['pwquality'],
+        ['qrencode'],
+        ['tpm2'],
+        ['xkbcommon'],
+
+        # compression libs
+        ['zstd'],
+        ['lz4'],
+        ['xz'],
+        ['zlib'],
+        ['bzip2'],
+
+        # components
+        ['backlight'],
         ['binfmt'],
-        ['repart'],
-        ['vconsole'],
-        ['quotacheck'],
-        ['tmpfiles'],
+        ['bpf-framework',         conf.get('BPF_FRAMEWORK') == 1],
+        ['coredump'],
         ['environment.d'],
-        ['sysusers'],
+        ['efi'],
+        ['gnu-efi'],
         ['firstboot'],
-        ['randomseed'],
-        ['backlight'],
-        ['rfkill'],
-        ['xdg-autostart'],
-        ['logind'],
-        ['machined'],
-        ['portabled'],
-        ['userdb'],
+        ['hibernate'],
         ['homed'],
-        ['importd'],
         ['hostnamed'],
-        ['timedated'],
-        ['timesyncd'],
+        ['hwdb'],
+        ['importd'],
+        ['initrd'],
+        ['kernel-install',        get_option('kernel-install')],
         ['localed'],
+        ['logind'],
+        ['machined'],
         ['networkd'],
-        ['resolve'],
-        ['DNS-over-TLS(gnutls)',  conf.get('DNS_OVER_TLS_USE_GNUTLS') == 1],
-        ['DNS-over-TLS(openssl)', conf.get('DNS_OVER_TLS_USE_OPENSSL') == 1],
-        ['coredump'],
-        ['pstore'],
+        ['nss-myhostname'],
+        ['nss-mymachines'],
+        ['nss-resolve'],
+        ['nss-systemd'],
         ['oomd'],
+        ['portabled'],
+        ['pstore'],
+        ['quotacheck'],
+        ['randomseed'],
+        ['repart'],
+        ['resolve'],
+        ['rfkill'],
+        ['sysext'],
+        ['systemd-analyze',       conf.get('ENABLE_ANALYZE') == 1],
+        ['sysusers'],
+        ['timedated'],
+        ['timesyncd'],
+        ['tmpfiles'],
+        ['userdb'],
+        ['vconsole'],
+        ['xdg-autostart'],
+
+        # optional features
+        ['idn'],
         ['polkit'],
-        ['legacy pkla',      install_polkit_pkla],
-        ['efi'],
-        ['gnu-efi',          have_gnu_efi],
+        ['nscd'],
+        ['legacy-pkla',           install_polkit_pkla],
         ['kmod'],
-        ['xkbcommon'],
-        ['pcre2'],
-        ['blkid'],
         ['dbus'],
         ['glib'],
-        ['nss-myhostname'],
-        ['nss-mymachines'],
-        ['nss-resolve'],
-        ['nss-systemd'],
-        ['hwdb'],
         ['tpm'],
-        ['man pages',        want_man],
-        ['html pages',       want_html],
-        ['man page indices', want_man and have_lxml],
+        ['man pages',             want_man],
+        ['html pages',            want_html],
+        ['man page indices',      want_man and have_lxml],
         ['SysV compat'],
+        ['compat-mutable-uid-boundaries'],
         ['utmp'],
         ['ldconfig'],
-        ['hibernate'],
-        ['adm group',        get_option('adm-group')],
-        ['wheel group',      get_option('wheel-group')],
+        ['adm group',             get_option('adm-group')],
+        ['wheel group',           get_option('wheel-group')],
         ['gshadow'],
         ['debug hashmap'],
         ['debug mmap cache'],
         ['debug siphash'],
-        ['valgrind',         conf.get('VALGRIND') == 1],
-        ['trace logging',    conf.get('LOG_TRACE') == 1],
-        ['install tests',    install_tests],
+        ['valgrind',              conf.get('VALGRIND') == 1],
+        ['trace logging',         conf.get('LOG_TRACE') == 1],
+        ['install tests',         install_tests],
         ['link-udev-shared',      get_option('link-udev-shared')],
         ['link-systemctl-shared', get_option('link-systemctl-shared')],
         ['link-networkd-shared',  get_option('link-networkd-shared')],
         ['link-timesyncd-shared', get_option('link-timesyncd-shared')],
-        ['kernel-install',        get_option('kernel-install')],
-        ['systemd-analyze',  conf.get('ENABLE_ANALYZE') == 1],
+        ['link-boot-shared',      get_option('link-boot-shared')],
+        ['fexecve'],
+        ['standalone-binaries',   get_option('standalone-binaries')],
 ]
 
         if tuple.length() >= 2
@@ -3851,13 +4105,38 @@ foreach tuple : [
         endif
 endforeach
 
-status += [
-        '',
-        'enabled features: @0@'.format(', '.join(found)),
-        '',
-        'disabled features: @0@'.format(', '.join(missing)),
-        '']
-message('\n         '.join(status))
+if static_libsystemd == 'false'
+        missing += 'static-libsystemd'
+else
+        found += 'static-libsystemd(@0@)'.format(static_libsystemd)
+endif
+
+if static_libudev == 'false'
+        missing += 'static-libudev'
+else
+        found += 'static-libudev(@0@)'.format(static_libudev)
+endif
+
+if conf.get('HAVE_OPENSSL_OR_GCRYPT') == 1 and conf.get('PREFER_OPENSSL') == 1
+        found += 'cryptolib(openssl)'
+elif conf.get('HAVE_OPENSSL_OR_GCRYPT') == 1
+        found += 'cryptolib(gcrypt)'
+else
+        missing += 'cryptolib'
+endif
+
+if conf.get('DNS_OVER_TLS_USE_GNUTLS') == 1
+        found += 'DNS-over-TLS(gnutls)'
+elif conf.get('DNS_OVER_TLS_USE_OPENSSL') == 1
+        found += 'DNS-over-TLS(openssl)'
+else
+        missing += 'DNS-over-TLS'
+endif
+
+summary({
+        'enabled' :  ', '.join(found),
+        'disabled' : ', '.join(missing)},
+        section : 'Features')
 
 if rootprefixdir != rootprefix_default
         warning('\n' +