From e5b3467412874d27c311253e3d5d7e65a61d12a4 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Tue, 1 Mar 2022 13:25:02 -0500 Subject: [PATCH 1/4] local-display-factory: Stall startup until main graphics card is ready At the moment, GDM waits until systemd says the system supports graphics (via the CanGraphical logind property). Unfortunately, this property isn't really what we need, since it flips to true when *any* graphics are available, not when the main graphics for the system are ready. This is a problem on hybrid graphics systems, if one card is slower to load than another. In particular, the vendor nvidia driver can be slow to load because it has multiple kernel modules it loads in series. Indeed on fast systems, that use the vendor nvidia driver, it's not unusual for boot to get to a point where all of userspace up to and including GDM is executed before the graphics are ready to go. This commit tries to mitigate the situation by adding an additional, check aside from CanGraphical to test if the system is ready. This check waits for the graphics card associated with boot to be fully up and running before proceeding to start a login screen. Closes: https://gitlab.gnome.org/GNOME/gdm/-/issues/763 --- daemon/gdm-local-display-factory.c | 164 ++++++++++++++++++++++++++--- daemon/meson.build | 4 + meson.build | 2 + 4 files changed, 159 insertions(+), 12 deletions(-) diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c index c00e1c47..0b1d3482 100644 --- a/daemon/gdm-local-display-factory.c +++ b/daemon/gdm-local-display-factory.c @@ -1,100 +1,112 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include "config.h" #include #include #include #include #include #include +#ifdef HAVE_UDEV +#include +#endif + #include #include "gdm-common.h" #include "gdm-manager.h" #include "gdm-display-factory.h" #include "gdm-local-display-factory.h" #include "gdm-local-display-factory-glue.h" #include "gdm-settings-keys.h" #include "gdm-settings-direct.h" #include "gdm-display-store.h" #include "gdm-local-display.h" #include "gdm-legacy-display.h" #define GDM_DBUS_PATH "/org/gnome/DisplayManager" #define GDM_LOCAL_DISPLAY_FACTORY_DBUS_PATH GDM_DBUS_PATH "/LocalDisplayFactory" #define GDM_MANAGER_DBUS_NAME "org.gnome.DisplayManager.LocalDisplayFactory" #define MAX_DISPLAY_FAILURES 5 #define WAIT_TO_FINISH_TIMEOUT 10 /* seconds */ #define SEAT0_GRAPHICS_CHECK_TIMEOUT 10 /* seconds */ struct _GdmLocalDisplayFactory { - GdmDisplayFactory parent; + GdmDisplayFactory parent; +#ifdef HAVE_UDEV + GUdevClient *gudev_client; +#endif GdmDBusLocalDisplayFactory *skeleton; GDBusConnection *connection; GHashTable *used_display_numbers; /* FIXME: this needs to be per seat? */ guint num_failures; guint seat_new_id; guint seat_removed_id; guint seat_properties_changed_id; + gboolean seat0_has_platform_graphics; + gboolean seat0_has_boot_up_graphics; + gboolean seat0_graphics_check_timed_out; guint seat0_graphics_check_timeout_id; + gulong uevent_handler_id; + #if defined(ENABLE_USER_DISPLAY_SERVER) unsigned int active_vt; guint active_vt_watch_id; guint wait_to_finish_timeout_id; #endif gboolean is_started; }; enum { PROP_0, }; static void gdm_local_display_factory_class_init (GdmLocalDisplayFactoryClass *klass); static void gdm_local_display_factory_init (GdmLocalDisplayFactory *factory); static void gdm_local_display_factory_finalize (GObject *object); static void ensure_display_for_seat (GdmLocalDisplayFactory *factory, const char *seat_id); static void on_display_status_changed (GdmDisplay *display, GParamSpec *arg1, GdmLocalDisplayFactory *factory); static gboolean gdm_local_display_factory_sync_seats (GdmLocalDisplayFactory *factory); static gpointer local_display_factory_object = NULL; static gboolean lookup_by_session_id (const char *id, GdmDisplay *display, gpointer user_data); @@ -594,142 +606,236 @@ lookup_by_seat_id (const char *id, gpointer user_data) { const char *looking_for = user_data; char *current; gboolean res; g_object_get (G_OBJECT (display), "seat-id", ¤t, NULL); res = g_strcmp0 (current, looking_for) == 0; g_free(current); return res; } static gboolean lookup_prepared_display_by_seat_id (const char *id, GdmDisplay *display, gpointer user_data) { int status; status = gdm_display_get_status (display); if (status != GDM_DISPLAY_PREPARED) return FALSE; return lookup_by_seat_id (id, display, user_data); } +#ifdef HAVE_UDEV +static gboolean +udev_is_settled (GdmLocalDisplayFactory *factory) +{ + g_autoptr (GUdevEnumerator) enumerator = NULL; + GList *devices; + GList *node; + + gboolean is_settled = FALSE; + + if (factory->seat0_has_platform_graphics) { + g_debug ("GdmLocalDisplayFactory: udev settled, platform graphics enabled."); + return TRUE; + } + + if (factory->seat0_has_boot_up_graphics) { + g_debug ("GdmLocalDisplayFactory: udev settled, boot up graphics available."); + return TRUE; + } + + if (factory->seat0_graphics_check_timed_out) { + g_debug ("GdmLocalDisplayFactory: udev timed out, proceeding anyway."); + return TRUE; + } + + g_debug ("GdmLocalDisplayFactory: Checking if udev has settled enough to support graphics."); + + enumerator = g_udev_enumerator_new (factory->gudev_client); + + g_udev_enumerator_add_match_name (enumerator, "card*"); + g_udev_enumerator_add_match_tag (enumerator, "master-of-seat"); + g_udev_enumerator_add_match_subsystem (enumerator, "drm"); + + devices = g_udev_enumerator_execute (enumerator); + if (!devices) { + g_debug ("GdmLocalDisplayFactory: udev has no candidate graphics devices available yet."); + return FALSE; + } + + node = devices; + while (node != NULL) { + GUdevDevice *device = node->data; + GList *next_node = node->next; + g_autoptr (GUdevDevice) platform_device = NULL; + g_autoptr (GUdevDevice) pci_device = NULL; + + platform_device = g_udev_device_get_parent_with_subsystem (device, "platform", NULL); + + if (platform_device != NULL) { + g_debug ("GdmLocalDisplayFactory: Found embedded platform graphics, proceeding."); + factory->seat0_has_platform_graphics = TRUE; + is_settled = TRUE; + break; + } + + pci_device = g_udev_device_get_parent_with_subsystem (device, "pci", NULL); + + if (pci_device != NULL) { + gboolean boot_vga; + + boot_vga = g_udev_device_get_sysfs_attr_as_int (pci_device, "boot_vga"); + + if (boot_vga == 1) { + g_debug ("GdmLocalDisplayFactory: Found primary PCI graphics adapter, proceeding."); + factory->seat0_has_boot_up_graphics = TRUE; + is_settled = TRUE; + break; + } else { + g_debug ("GdmLocalDisplayFactory: Found secondary PCI graphics adapter, not proceeding yet."); + } + } + node = next_node; + } + + g_debug ("GdmLocalDisplayFactory: udev has %ssettled enough for graphics.", is_settled? "" : "not "); + g_list_free_full (devices, g_object_unref); + + if (is_settled) + g_clear_signal_handler (&factory->uevent_handler_id, factory->gudev_client); + + return is_settled; +} +#endif + static int on_seat0_graphics_check_timeout (gpointer user_data) { GdmLocalDisplayFactory *factory = user_data; factory->seat0_graphics_check_timeout_id = 0; /* Simply try to re-add seat0. If it is there already (i.e. CanGraphical * turned TRUE, then we'll find it and it will not be created again). */ factory->seat0_graphics_check_timed_out = TRUE; ensure_display_for_seat (factory, "seat0"); return G_SOURCE_REMOVE; } static void ensure_display_for_seat (GdmLocalDisplayFactory *factory, const char *seat_id) { int ret; gboolean seat_supports_graphics; gboolean is_seat0; g_auto (GStrv) session_types = NULL; const char *legacy_session_types[] = { "x11", NULL }; GdmDisplayStore *store; GdmDisplay *display = NULL; g_autofree char *login_session_id = NULL; gboolean wayland_enabled = FALSE, xorg_enabled = FALSE; g_autofree gchar *preferred_display_server = NULL; gboolean falling_back = FALSE; + gboolean waiting_on_udev = FALSE; gdm_settings_direct_get_boolean (GDM_KEY_WAYLAND_ENABLE, &wayland_enabled); gdm_settings_direct_get_boolean (GDM_KEY_XORG_ENABLE, &xorg_enabled); preferred_display_server = get_preferred_display_server (factory); if (g_strcmp0 (preferred_display_server, "none") == 0) { g_debug ("GdmLocalDisplayFactory: Preferred display server is none, so not creating display"); return; } - ret = sd_seat_can_graphical (seat_id); +#ifdef HAVE_UDEV + waiting_on_udev = !udev_is_settled (factory); +#endif - if (ret < 0) { - g_critical ("Failed to query CanGraphical information for seat %s", seat_id); - return; - } + if (!waiting_on_udev) { + ret = sd_seat_can_graphical (seat_id); - if (ret == 0) { - g_debug ("GdmLocalDisplayFactory: System doesn't currently support graphics"); - seat_supports_graphics = FALSE; + if (ret < 0) { + g_critical ("Failed to query CanGraphical information for seat %s", seat_id); + return; + } + + if (ret == 0) { + g_debug ("GdmLocalDisplayFactory: System doesn't currently support graphics"); + seat_supports_graphics = FALSE; + } else { + g_debug ("GdmLocalDisplayFactory: System supports graphics"); + seat_supports_graphics = TRUE; + } } else { - g_debug ("GdmLocalDisplayFactory: System supports graphics"); - seat_supports_graphics = TRUE; + g_debug ("GdmLocalDisplayFactory: udev is still settling, so not creating display yet"); + seat_supports_graphics = FALSE; } if (g_strcmp0 (seat_id, "seat0") == 0) { is_seat0 = TRUE; falling_back = factory->num_failures > 0; session_types = gdm_local_display_factory_get_session_types (factory, falling_back); if (session_types == NULL) { g_debug ("GdmLocalDisplayFactory: Both Wayland and Xorg are unavailable"); seat_supports_graphics = FALSE; } else { g_debug ("GdmLocalDisplayFactory: New displays on seat0 will use %s%s", session_types[0], falling_back? " fallback" : ""); } } else { is_seat0 = FALSE; g_debug ("GdmLocalDisplayFactory: New displays on seat %s will use X11 fallback", seat_id); /* Force legacy X11 for all auxiliary seats */ seat_supports_graphics = TRUE; session_types = g_strdupv ((char **) legacy_session_types); } /* For seat0, we have a fallback logic to still try starting it after * SEAT0_GRAPHICS_CHECK_TIMEOUT seconds. i.e. we simply continue even if - * CanGraphical is unset. + * CanGraphical is unset or udev otherwise never finds a suitable graphics card. * This is ugly, but it means we'll come up eventually in some * scenarios where no master device is present. * Note that we'll force an X11 fallback even though there might be * cases where an wayland capable device is present and simply not marked as * master-of-seat. In these cases, this should likely be fixed in the * udev rules. * * At the moment, systemd always sets CanGraphical for non-seat0 seats. * This is because non-seat0 seats are defined by having master-of-seat * set. This means we can avoid the fallback check for non-seat0 seats, * which simplifies the code. */ if (is_seat0) { if (!seat_supports_graphics) { if (!factory->seat0_graphics_check_timed_out) { if (factory->seat0_graphics_check_timeout_id == 0) { g_debug ("GdmLocalDisplayFactory: seat0 doesn't yet support graphics. Waiting %d seconds to try again.", SEAT0_GRAPHICS_CHECK_TIMEOUT); factory->seat0_graphics_check_timeout_id = g_timeout_add_seconds (SEAT0_GRAPHICS_CHECK_TIMEOUT, on_seat0_graphics_check_timeout, factory); } else { /* It is not yet time to force X11 fallback. */ g_debug ("GdmLocalDisplayFactory: seat0 display requested when there is no graphics support before graphics check timeout."); } return; } g_debug ("GdmLocalDisplayFactory: Assuming we can use seat0 for X11 even though system says it doesn't support graphics!"); @@ -1138,113 +1240,151 @@ on_vt_changed (GIOChannel *source, if (factory->wait_to_finish_timeout_id != 0) { g_debug ("GdmLocalDisplayFactory: deferring previous login screen clean up operation"); g_source_remove (factory->wait_to_finish_timeout_id); } factory->wait_to_finish_timeout_id = g_timeout_add_seconds (WAIT_TO_FINISH_TIMEOUT, (GSourceFunc) on_finish_waiting_for_seat0_displays_timeout, factory); } } } /* if user jumped back to initial vt and it's empty put a login screen * on it (unless a login screen is already running elsewhere, then * jump to that login screen) */ if (factory->active_vt != GDM_INITIAL_VT) { g_debug ("GdmLocalDisplayFactory: active VT is not initial VT, so ignoring"); return G_SOURCE_CONTINUE; } g_debug ("GdmLocalDisplayFactory: creating new display on seat0 because of VT change"); ensure_display_for_seat (factory, "seat0"); return G_SOURCE_CONTINUE; } #endif +#ifdef HAVE_UDEV +static void +on_uevent (GUdevClient *client, + const char *action, + GUdevDevice *device, + GdmLocalDisplayFactory *factory) +{ + if (!g_udev_device_get_device_file (device)) + return; + + if (g_strcmp0 (action, "add") != 0 && + g_strcmp0 (action, "change") != 0) + return; + + if (!udev_is_settled (factory)) + return; + + g_signal_handler_disconnect (factory->gudev_client, factory->uevent_handler_id); + factory->uevent_handler_id = 0; + + ensure_display_for_seat (factory, "seat0"); +} +#endif + static void gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory) { g_autoptr (GIOChannel) io_channel = NULL; + const char *subsystems[] = { "drm", NULL }; factory->seat_new_id = g_dbus_connection_signal_subscribe (factory->connection, "org.freedesktop.login1", "org.freedesktop.login1.Manager", "SeatNew", "/org/freedesktop/login1", NULL, G_DBUS_SIGNAL_FLAGS_NONE, on_seat_new, g_object_ref (factory), g_object_unref); factory->seat_removed_id = g_dbus_connection_signal_subscribe (factory->connection, "org.freedesktop.login1", "org.freedesktop.login1.Manager", "SeatRemoved", "/org/freedesktop/login1", NULL, G_DBUS_SIGNAL_FLAGS_NONE, on_seat_removed, g_object_ref (factory), g_object_unref); factory->seat_properties_changed_id = g_dbus_connection_signal_subscribe (factory->connection, "org.freedesktop.login1", "org.freedesktop.DBus.Properties", "PropertiesChanged", NULL, "org.freedesktop.login1.Seat", G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE, on_seat_properties_changed, g_object_ref (factory), g_object_unref); +#ifdef HAVE_UDEV + factory->gudev_client = g_udev_client_new (subsystems); + factory->uevent_handler_id = g_signal_connect (factory->gudev_client, + "uevent", + G_CALLBACK (on_uevent), + factory); +#endif #if defined(ENABLE_USER_DISPLAY_SERVER) io_channel = g_io_channel_new_file ("/sys/class/tty/tty0/active", "r", NULL); if (io_channel != NULL) { factory->active_vt_watch_id = g_io_add_watch (io_channel, G_IO_PRI, (GIOFunc) on_vt_changed, factory); } #endif } static void gdm_local_display_factory_stop_monitor (GdmLocalDisplayFactory *factory) { + if (factory->uevent_handler_id) { + g_signal_handler_disconnect (factory->gudev_client, factory->uevent_handler_id); + factory->uevent_handler_id = 0; + } + g_clear_object (&factory->gudev_client); + if (factory->seat_new_id) { g_dbus_connection_signal_unsubscribe (factory->connection, factory->seat_new_id); factory->seat_new_id = 0; } if (factory->seat_removed_id) { g_dbus_connection_signal_unsubscribe (factory->connection, factory->seat_removed_id); factory->seat_removed_id = 0; } if (factory->seat_properties_changed_id) { g_dbus_connection_signal_unsubscribe (factory->connection, factory->seat_properties_changed_id); factory->seat_properties_changed_id = 0; } #if defined(ENABLE_USER_DISPLAY_SERVER) if (factory->active_vt_watch_id) { g_source_remove (factory->active_vt_watch_id); factory->active_vt_watch_id = 0; } if (factory->wait_to_finish_timeout_id != 0) { g_source_remove (factory->wait_to_finish_timeout_id); factory->wait_to_finish_timeout_id = 0; } #endif } static void on_display_added (GdmDisplayStore *display_store, const char *id, diff --git a/daemon/meson.build b/daemon/meson.build index 2e61b644..41f30abe 100644 --- a/daemon/meson.build +++ b/daemon/meson.build @@ -177,37 +177,41 @@ gdm_daemon_sources = files( 'gdm-session-record.c', 'gdm-session-worker-common.c', 'gdm-session-worker-job.c', 'gdm-session.c', 'main.c', ) gdm_daemon_gen_sources = [ display_dbus_gen, local_display_factory_dbus_gen, manager_dbus_gen, local_display_dbus_gen, session_dbus_gen, session_worker_dbus_gen, gdm_session_enums, ] if xdmcp_dep.found() gdm_daemon_deps += xdmcp_dep gdm_daemon_sources = [ gdm_daemon_sources, files( 'gdm-xdmcp-display-factory.c', 'gdm-xdmcp-display.c', 'gdm-xdmcp-chooser-display.c', ), ] endif +if gudev_dep.found() + gdm_daemon_deps += gudev_dep +endif + gdm_daemon = executable('gdm', [ gdm_daemon_sources, gdm_daemon_gen_sources ], dependencies: gdm_daemon_deps, include_directories: config_h_dir, install: true, install_dir: get_option('sbindir') ) diff --git a/meson.build b/meson.build index 02d609dc..05d8da41 100644 --- a/meson.build +++ b/meson.build @@ -11,60 +11,61 @@ i18n = import('i18n') # Compiler cc = meson.get_compiler('c') # Options gdm_prefix = get_option('prefix') gdmconfdir = (get_option('sysconfsubdir') == '')? gdm_prefix / get_option('sysconfdir') : gdm_prefix / get_option('sysconfdir') / get_option('sysconfsubdir') dmconfdir = (get_option('dmconfdir') != '')? get_option('dmconfdir') : gdm_prefix / get_option('sysconfdir') / 'dm' udev_dir = get_option('udev-dir') at_spi_registryd_dir = (get_option('at-spi-registryd-dir') != '')? get_option('at-spi-registryd-dir') : gdm_prefix / get_option('libexecdir') lang_config_file = (get_option('lang-file') != '')? get_option('lang-file') : gdm_prefix / get_option('sysconfdir') / 'locale.conf' pam_mod_dir = (get_option('pam-mod-dir') != '')? get_option('pam-mod-dir') : gdm_prefix / get_option('libdir') / 'security' dbus_sys_dir = (get_option('dbus-sys') != '')? get_option('dbus-sys') : get_option('sysconfdir') / 'dbus-1' / 'system.d' gdm_defaults_conf = (get_option('defaults-conf') != '')? get_option('defaults-conf') : gdm_prefix / get_option('datadir') / 'gdm' / 'defaults.conf' gdm_custom_conf = (get_option('custom-conf') != '')? get_option('custom-conf') : gdmconfdir / 'custom.conf' gnome_settings_daemon_dir = (get_option('gnome-settings-daemon-dir') != '')? get_option('gnome-settings-daemon-dir') : gdm_prefix / get_option('libexecdir') gdm_run_dir = (get_option('run-dir') != '')? get_option('run-dir') : gdm_prefix / get_option('localstatedir') / 'run' / 'gdm' gdm_runtime_conf = (get_option('runtime-conf') != '')? get_option('runtime-conf') : gdm_run_dir / 'custom.conf' gdm_pid_file = (get_option('pid-file') != '')? get_option('pid-file') : gdm_run_dir / 'gdm.pid' ran_once_marker_dir = (get_option('ran-once-marker-dir') != '')? get_option('ran-once-marker-dir') : gdm_run_dir working_dir = (get_option('working-dir') != '')? get_option('working-dir') : gdm_prefix / get_option('localstatedir') / 'lib' / 'gdm' gdm_xauth_dir = (get_option('xauth-dir') != '')? get_option('xauth-dir') : gdm_run_dir gdm_screenshot_dir = (get_option('screenshot-dir') != '')? get_option('screenshot-dir') : gdm_run_dir / 'greeter' # Common variables config_h_dir = include_directories('.') # Dependencies udev_dep = dependency('udev') +gudev_dep = dependency('gudev-1.0', version: '>= 232') glib_min_version = '2.56.0' glib_dep = dependency('glib-2.0', version: '>=' + glib_min_version) gobject_dep = dependency('gobject-2.0', version: '>=' + glib_min_version) gio_dep = dependency('gio-2.0', version: '>=' + glib_min_version) gio_unix_dep = dependency('gio-unix-2.0', version: '>=' + glib_min_version) gtk_dep = dependency('gtk+-3.0', version: '>= 2.91.1') libcanberra_gtk_dep = dependency('libcanberra-gtk3', version: '>= 0.4') accountsservice_dep = dependency('accountsservice', version: '>= 0.6.35') xcb_dep = dependency('xcb') keyutils_dep = dependency('libkeyutils', required: false) libselinux_dep = dependency('libselinux', required: get_option('selinux')) # udev if udev_dir == '' if udev_dep.found() udev_prefix = udev_dep.get_pkgconfig_variable('udevdir') else udev_prefix = gdm_prefix / 'lib' / 'udev' endif udev_dir = udev_prefix / 'rules.d' endif # X11 x_deps = declare_dependency( dependencies: [ dependency('x11'), dependency('xau'), ], @@ -217,60 +218,61 @@ conf.set('HAVE_UTMP_H', have_utmp_header) conf.set('HAVE_UTMPX_H', have_utmpx_header) conf.set('HAVE_POSIX_GETPWNAM_R', have_posix_getpwnam_r) conf.set('UTMP', utmp_struct) conf.set('HAVE_GETUTXENT', cc.has_function('getutxent')) conf.set('HAVE_UPDWTMP', cc.has_function('updwtmp')) conf.set('HAVE_UPDWTMPX', cc.has_function('updwtmpx')) conf.set('HAVE_LOGIN', cc.has_function('login', args: '-lutil')) conf.set('HAVE_LOGOUT', cc.has_function('logout', args: '-lutil')) conf.set('HAVE_LOGWTMP', cc.has_function('logwtmp', args: '-lutil')) conf.set('HAVE_PAM_SYSLOG', have_pam_syslog) conf.set('HAVE_KEYUTILS', keyutils_dep.found()) conf.set('SUPPORTS_PAM_EXTENSIONS', pam_extensions_supported) conf.set('HAVE_SELINUX', libselinux_dep.found()) conf.set('HAVE_XSERVER_WITH_LISTEN', xserver_has_listen) conf.set('ENABLE_USER_DISPLAY_SERVER', get_option('user-display-server')) conf.set('ENABLE_SYSTEMD_JOURNAL', get_option('systemd-journal')) conf.set('ENABLE_WAYLAND_SUPPORT', get_option('wayland-support')) conf.set('ENABLE_PROFILING', get_option('profiling')) conf.set('GDM_INITIAL_VT', get_option('initial-vt')) conf.set_quoted('GDM_DEFAULTS_CONF', gdm_defaults_conf) conf.set_quoted('GDM_CUSTOM_CONF', gdm_custom_conf) conf.set_quoted('GDM_RUNTIME_CONF', gdm_runtime_conf) conf.set_quoted('GDM_SESSION_DEFAULT_PATH', get_option('default-path')) conf.set_quoted('GDM_USERNAME', get_option('user')) conf.set_quoted('GDM_GROUPNAME', get_option('group')) conf.set('HAVE_LIBXDMCP', xdmcp_dep.found()) conf.set_quoted('SYSTEMD_X_SERVER', systemd_x_server) conf.set('WITH_PLYMOUTH', plymouth_dep.found()) conf.set_quoted('X_SERVER', x_bin) conf.set_quoted('X_PATH', x_path) +conf.set('HAVE_UDEV', gudev_dep.found()) conf.set('HAVE_UT_UT_HOST', utmp_has_host_field) conf.set('HAVE_UT_UT_PID', utmp_has_pid_field) conf.set('HAVE_UT_UT_ID', utmp_has_id_field) conf.set('HAVE_UT_UT_NAME', utmp_has_name_field) conf.set('HAVE_UT_UT_TYPE', utmp_has_type_field) conf.set('HAVE_UT_UT_EXIT_E_TERMINATION', utmp_has_exit_e_termination_field) conf.set('HAVE_UT_UT_USER', utmp_has_user_field) conf.set('HAVE_UT_UT_TIME', utmp_has_time_field) conf.set('HAVE_UT_UT_TV', utmp_has_tv_field) conf.set('HAVE_UT_UT_SYSLEN', utmp_has_syslen_field) conf.set('ENABLE_IPV6', get_option('ipv6')) configure_file(output: 'config.h', configuration: conf) # Subdirs subdir('data') subdir('common') if pam_extensions_supported subdir('pam-extensions') endif subdir('daemon') subdir('libgdm') subdir('utils') subdir('pam_gdm') subdir('po') if libcheck_dep.found() subdir('tests') endif if xdmcp_dep.found() subdir('chooser') endif -- 2.34.1