diff --git a/meson.build b/meson.build index f0b921879b..599d2a3217 100644 --- a/meson.build +++ b/meson.build @@ -72,7 +72,10 @@ conf.set10('SD_BOOT', false) # Create a title-less summary section early, so it ends up first in the output. # More items are added later after they have been detected. -summary({'build mode' : get_option('mode')}) +summary({ + 'libc' : get_option('libc'), + 'build mode' : get_option('mode'), +}) ##################################################################### @@ -557,6 +560,10 @@ conf.set10('HAVE_WARNING_ZERO_AS_NULL_POINTER_CONSTANT', have) conf.set('_GNU_SOURCE', 1) conf.set('__SANE_USERSPACE_TYPES__', true) +# glibc always defines _LARGEFILE64_SOURCE when _GNU_SOURCE is set, but musl does not do that, +# and it is necessary for making getdents64() and struct dirent64 exist. +conf.set('_LARGEFILE64_SOURCE', 1) + conf.set('SIZEOF_DEV_T', cc.sizeof('dev_t', prefix : '#include ')) conf.set('SIZEOF_INO_T', cc.sizeof('ino_t', prefix : '#include ')) conf.set('SIZEOF_RLIM_T', cc.sizeof('rlim_t', prefix : '#include ')) @@ -572,6 +579,7 @@ assert(long_max > 100000) conf.set_quoted('LONG_MAX_STR', f'@long_max@') foreach ident : [ + ['renameat2', '''#include '''], # since musl-1.2.6 ['set_mempolicy', '''#include '''], # declared at numaif.h provided by libnuma, which we do not use ['get_mempolicy', '''#include '''], # declared at numaif.h provided by libnuma, which we do not use ['strerrorname_np', '''#include '''], # since glibc-2.32 @@ -700,6 +708,8 @@ foreach header : [ endforeach foreach header : [ + 'gshadow.h', + 'nss.h', 'sys/sdt.h', 'threads.h', 'valgrind/memcheck.h', @@ -710,6 +720,20 @@ foreach header : [ cc.has_header(header)) endforeach +foreach ident : [ + ['NI_IDN', 'netdb.h'] + ] + + if meson.version().version_compare('>=1.3.0') + have = cc.has_define(ident[0], + prefix : '''#include <@0@>'''.format(ident[1]), + args : '-D_GNU_SOURCE') + else + have = cc.has_header_symbol(ident[1], ident[0]) + endif + conf.set10('HAVE_' + ident[0], have) +endforeach + ##################################################################### fallback_hostname = get_option('fallback-hostname') @@ -1002,6 +1026,22 @@ librt = cc.find_library('rt') libm = cc.find_library('m') libdl = cc.find_library('dl') +# On some distributions that use musl (e.g. Alpine), libintl.h may be provided by gettext rather than musl. +# In that case, we need to explicitly link with libintl.so. +if cc.has_function('dgettext', + prefix : '''#include ''', + args : '-D_GNU_SOURCE') + libintl = [] +else + libintl = cc.find_library('intl') + if not cc.has_function('dgettext', + prefix : '''#include ''', + args : '-D_GNU_SOURCE', + dependencies : libintl) + error('dgettext() not found') + endif +endif + # On some architectures, libatomic is required. But on some installations, # it is found, but actual linking fails. So let's try to use it opportunistically. # If it is installed, but not needed, it will be dropped because of --as-needed. @@ -1603,52 +1643,60 @@ conf.set10('ENABLE_NSPAWN', feature.allowed()) conf.set10('DEFAULT_MOUNTFSD_TRUSTED_DIRECTORIES', get_option('default-mountfsd-trusted-directories')) -foreach term : ['analyze', - 'backlight', - 'binfmt', - 'compat-mutable-uid-boundaries', - 'coredump', - 'efi', - 'environment-d', - 'firstboot', - 'gshadow', - 'hibernate', - 'hostnamed', - 'hwdb', - 'idn', - 'ima', - 'ipe', - 'initrd', - 'kernel-install', - 'ldconfig', - 'localed', - 'logind', - 'machined', - 'mountfsd', - 'networkd', - 'nsresourced', - 'nss-myhostname', - 'nss-systemd', - 'oomd', - 'portabled', - 'pstore', - 'quotacheck', - 'randomseed', - 'resolve', - 'rfkill', - 'smack', - 'sysext', - 'sysusers', - 'timedated', - 'timesyncd', - 'tmpfiles', - 'tpm', - 'userdb', - 'utmp', - 'vconsole', - 'xdg-autostart'] - have = get_option(term) - name = 'ENABLE_' + term.underscorify().to_upper() +foreach tuple : [ + ['analyze'], + ['backlight'], + ['binfmt'], + ['compat-mutable-uid-boundaries'], + ['coredump'], + ['efi'], + ['environment-d'], + ['firstboot'], + ['gshadow', conf.get('HAVE_GSHADOW_H') == 1, 'gshadow.h not found'], + ['hibernate'], + ['hostnamed'], + ['hwdb'], + ['idn', conf.get('HAVE_NI_IDN') == 1, 'NI_IDN is not defined'], + ['ima'], + ['ipe'], + ['initrd'], + ['kernel-install'], + ['ldconfig'], + ['localed'], + ['logind'], + ['machined'], + ['mountfsd'], + ['networkd'], + ['nsresourced'], + ['nss-myhostname', conf.get('HAVE_NSS_H') == 1, 'nss.h not found'], + ['nss-systemd', conf.get('HAVE_NSS_H') == 1, 'nss.h not found'], + ['oomd'], + ['portabled'], + ['pstore'], + ['quotacheck'], + ['randomseed'], + ['resolve'], + ['rfkill'], + ['smack'], + ['sysext'], + ['sysusers'], + ['timedated'], + ['timesyncd'], + ['tmpfiles'], + ['tpm'], + ['utmp'], + ['userdb'], + ['vconsole'], + ['xdg-autostart'], + ] + + have = get_option(tuple[0]) + if have and tuple.length() >= 3 and not tuple[1] + warning('@0@ support is requested but @1@, disabling it'.format(tuple[0], tuple[2])) + have = false + endif + + name = 'ENABLE_' + tuple[0].underscorify().to_upper() conf.set10(name, have) endforeach @@ -1657,11 +1705,16 @@ enable_sysusers = conf.get('ENABLE_SYSUSERS') == 1 foreach tuple : [['nss-mymachines', 'machined'], ['nss-resolve', 'resolve']] want = get_option(tuple[0]) - if want.allowed() - have = get_option(tuple[1]) - if want.enabled() and not have + if want.enabled() + if conf.get('HAVE_NSS_H') != 1 + error('@0@ is requested but nss.h not found'.format(tuple[0])) + endif + if not get_option(tuple[1]) error('@0@ is requested but @1@ is disabled'.format(tuple[0], tuple[1])) endif + have = true + elif want.allowed() + have = get_option(tuple[1]) and conf.get('HAVE_NSS_H') == 1 else have = false endif @@ -2069,6 +2122,15 @@ system_includes = [ ), ] +if get_option('libc') == 'musl' + system_include_args = [ + '-isystem', meson.project_build_root() / 'src/include/musl', + '-isystem', meson.project_source_root() / 'src/include/musl', + ] + system_include_args + + system_includes += include_directories('src/include/musl', is_system : true) +endif + basic_includes = [ include_directories( 'src/basic', diff --git a/meson_options.txt b/meson_options.txt index 3cc314eacd..1d7c4f4bd2 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -402,6 +402,8 @@ option('ima', type : 'boolean', option('ipe', type : 'boolean', description : 'IPE support') +option('libc', type : 'combo', choices : ['glibc', 'musl'], + description : 'libc implementation to be used') option('acl', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' }, description : 'libacl support') option('audit', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' }, diff --git a/src/boot/meson.build b/src/boot/meson.build index ee86af274e..3d1f66a658 100644 --- a/src/boot/meson.build +++ b/src/boot/meson.build @@ -182,6 +182,11 @@ if get_option('mode') == 'developer' and get_option('debug') efi_c_args += '-DEFI_DEBUG' endif +if get_option('libc') == 'musl' + # To make musl not define wchar_t as int, rather than short. + efi_c_args += '-D__DEFINED_wchar_t' +endif + efi_c_ld_args = [ '-nostdlib', '-static-pie', diff --git a/src/home/meson.build b/src/home/meson.build index ebecc7b9c2..f40f935d55 100644 --- a/src/home/meson.build +++ b/src/home/meson.build @@ -115,6 +115,7 @@ modules += [ 'sources' : pam_systemd_home_sources, 'dependencies' : [ libcrypt, + libintl, libpam_misc, libpam, threads, diff --git a/src/include/musl/stdio.h b/src/include/musl/stdio.h new file mode 100644 index 0000000000..d677201f45 --- /dev/null +++ b/src/include/musl/stdio.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include_next + +#if !HAVE_RENAMEAT2 +# define RENAME_NOREPLACE (1 << 0) +# define RENAME_EXCHANGE (1 << 1) +# define RENAME_WHITEOUT (1 << 2) + +int missing_renameat2(int __oldfd, const char *__old, int __newfd, const char *__new, unsigned __flags); +# define renameat2 missing_renameat2 +#endif diff --git a/src/libc/meson.build b/src/libc/meson.build index eeee98c9d6..306512ffd7 100644 --- a/src/libc/meson.build +++ b/src/libc/meson.build @@ -16,6 +16,8 @@ libc_wrapper_sources = files( 'xattr.c', ) +subdir('musl') + sources += libc_wrapper_sources libc_wrapper_static = static_library( diff --git a/src/libc/musl/meson.build b/src/libc/musl/meson.build new file mode 100644 index 0000000000..8d06d919ef --- /dev/null +++ b/src/libc/musl/meson.build @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +if get_option('libc') != 'musl' + subdir_done() +endif + +libc_wrapper_sources += files( + 'stdio.c', +) diff --git a/src/libc/musl/stdio.c b/src/libc/musl/stdio.c new file mode 100644 index 0000000000..102a22cd5c --- /dev/null +++ b/src/libc/musl/stdio.c @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include +#include +#include + +#if !HAVE_RENAMEAT2 +int missing_renameat2(int __oldfd, const char *__old, int __newfd, const char *__new, unsigned __flags) { + return syscall(__NR_renameat2, __oldfd, __old, __newfd, __new, __flags); +} +#endif