https://github.com/swaywm/sway/pull/7236
https://github.com/swaywm/sway/pull/7281
https://github.com/swaywm/sway/pull/7294
diff -uNr a/include/sway/server.h b/include/sway/server.h
--- a/include/sway/server.h
+++ b/include/sway/server.h
@@ -3,7 +3,6 @@
 #include <stdbool.h>
 #include <wayland-server-core.h>
 #include <wlr/backend.h>
-#include <wlr/backend/session.h>
 #include <wlr/render/allocator.h>
 #include <wlr/render/wlr_renderer.h>
 #include <wlr/types/wlr_compositor.h>
@@ -34,6 +33,7 @@
 	const char *socket;
 
 	struct wlr_backend *backend;
+	struct wlr_session *session;
 	// secondary headless backend used for creating virtual outputs on-the-fly
 	struct wlr_backend *headless_backend;
 	struct wlr_renderer *renderer;
diff -uNr a/meson.build b/meson.build
--- a/meson.build
+++ b/meson.build
@@ -43,6 +43,24 @@
 	required: false,
 	version: wlroots_version,
 )
+wlroots = dependency('wlroots', version: wlroots_version)
+wlroots_features = {
+	'xwayland': false,
+	'libinput_backend': false,
+	'gles2_renderer': false,
+	'session': false,
+}
+foreach name, _ : wlroots_features
+	var_name = 'have_' + name.underscorify()
+	have = wlroots.get_variable(pkgconfig: var_name, internal: var_name) == 'true'
+	wlroots_features += { name: have }
+endforeach
+
+if get_option('xwayland').enabled() and not wlroots_features['xwayland']
+	error('Cannot enable Xwayland in sway: wlroots has been built without Xwayland support')
+endif
+
+null_dep = dependency('', required: false)
 
 jsonc = dependency('json-c', version: '>=0.13')
 pcre2 = dependency('libpcre2-8')
@@ -50,20 +68,19 @@
 wayland_client = dependency('wayland-client')
 wayland_cursor = dependency('wayland-cursor')
 wayland_protos = dependency('wayland-protocols', version: '>=1.24')
-wlroots = dependency('wlroots', version: wlroots_version)
 xkbcommon = dependency('xkbcommon')
 cairo = dependency('cairo')
 pango = dependency('pango')
 pangocairo = dependency('pangocairo')
 gdk_pixbuf = dependency('gdk-pixbuf-2.0', required: get_option('gdk-pixbuf'))
 pixman = dependency('pixman-1')
-glesv2 = dependency('glesv2')
+glesv2 = wlroots_features['gles2_renderer'] ? dependency('glesv2') : null_dep
 libevdev = dependency('libevdev')
-libinput = dependency('libinput', version: '>=1.21.0')
+libinput = wlroots_features['libinput_backend'] ? dependency('libinput', version: '>=1.21.0') : null_dep
 xcb = dependency('xcb', required: get_option('xwayland'))
 drm_full = dependency('libdrm') # only needed for drm_fourcc.h
 drm = drm_full.partial_dependency(compile_args: true, includes: true)
-libudev = dependency('libudev')
+libudev = wlroots_features['libinput_backend'] ? dependency('libudev') : null_dep
 bash_comp = dependency('bash-completion', required: false)
 fish_comp = dependency('fish', required: false)
 math = cc.find_library('m')
@@ -71,18 +88,6 @@
 xcb_icccm = dependency('xcb-icccm', required: get_option('xwayland'))
 threads = dependency('threads') # for pthread_setschedparam
 
-wlroots_features = {
-	'xwayland': false,
-}
-foreach name, _ : wlroots_features
-	var_name = 'have_' + name.underscorify()
-	have = wlroots.get_variable(pkgconfig: var_name, internal: var_name) == 'true'
-	wlroots_features += { name: have }
-endforeach
-
-if get_option('xwayland').enabled() and not wlroots_features['xwayland']
-	error('Cannot enable Xwayland in sway: wlroots has been built without Xwayland support')
-endif
 have_xwayland = xcb.found() and xcb_icccm.found() and wlroots_features['xwayland']
 
 if get_option('sd-bus-provider') == 'auto'
diff -uNr a/sway/commands/input/events.c b/sway/commands/input/events.c
--- a/sway/commands/input/events.c
+++ b/sway/commands/input/events.c
@@ -1,14 +1,19 @@
 #include <limits.h>
 #include <string.h>
 #include <strings.h>
-#include <wlr/backend/libinput.h>
+#include <wlr/config.h>
 #include "sway/config.h"
 #include "sway/commands.h"
 #include "sway/input/input-manager.h"
 #include "log.h"
 
+#if WLR_HAS_LIBINPUT_BACKEND
+#include <wlr/backend/libinput.h>
+#endif
+
 static void toggle_supported_send_events_for_device(struct input_config *ic,
 		struct sway_input_device *input_device) {
+#if WLR_HAS_LIBINPUT_BACKEND
 	struct wlr_input_device *wlr_device = input_device->wlr_device;
 	if (!wlr_input_device_is_libinput(wlr_device)) {
 		return;
@@ -41,6 +46,7 @@
 	}
 
 	ic->send_events = mode;
+#endif
 }
 
 static int mode_for_name(const char *name) {
@@ -56,6 +62,7 @@
 
 static void toggle_select_send_events_for_device(struct input_config *ic,
 		struct sway_input_device *input_device, int argc, char **argv) {
+#if WLR_HAS_LIBINPUT_BACKEND
 	if (!wlr_input_device_is_libinput(input_device->wlr_device)) {
 		return;
 	}
@@ -72,6 +79,7 @@
 		}
 	}
 	ic->send_events = mode_for_name(argv[index % argc]);
+#endif
 }
 
 static void toggle_send_events(int argc, char **argv) {
diff -uNr a/sway/config/output.c b/sway/config/output.c
--- a/sway/config/output.c
+++ b/sway/config/output.c
@@ -6,10 +6,10 @@
 #include <sys/socket.h>
 #include <sys/wait.h>
 #include <unistd.h>
+#include <wlr/config.h>
 #include <wlr/types/wlr_cursor.h>
 #include <wlr/types/wlr_output_layout.h>
 #include <wlr/types/wlr_output.h>
-#include <wlr/backend/drm.h>
 #include "sway/config.h"
 #include "sway/input/cursor.h"
 #include "sway/output.h"
@@ -17,6 +17,10 @@
 #include "log.h"
 #include "util.h"
 
+#if WLR_HAS_DRM_BACKEND
+#include <wlr/backend/drm.h>
+#endif
+
 int output_name_cmp(const void *item, const void *data) {
 	const struct output_config *output = item;
 	const char *name = data;
@@ -286,6 +290,7 @@
 
 static void set_modeline(struct wlr_output *output,
 		struct wlr_output_state *pending, drmModeModeInfo *drm_mode) {
+#if WLR_HAS_DRM_BACKEND
 	if (!wlr_output_is_drm(output)) {
 		sway_log(SWAY_ERROR, "Modeline can only be set to DRM output");
 		return;
@@ -295,6 +300,9 @@
 	if (mode) {
 		wlr_output_state_set_mode(pending, mode);
 	}
+#else
+	sway_log(SWAY_ERROR, "Modeline can only be set to DRM output");
+#endif
 }
 
 /* Some manufacturers hardcode the aspect-ratio of the output in the physical
@@ -436,9 +444,11 @@
 	enum wl_output_transform tr = WL_OUTPUT_TRANSFORM_NORMAL;
 	if (oc && oc->transform >= 0) {
 		tr = oc->transform;
+#if WLR_HAS_DRM_BACKEND
 	} else if (wlr_output_is_drm(wlr_output)) {
 		tr = wlr_drm_connector_get_panel_orientation(wlr_output);
 		sway_log(SWAY_DEBUG, "Auto-detected output transform: %d", tr);
+#endif
 	}
 	if (wlr_output->transform != tr) {
 		sway_log(SWAY_DEBUG, "Set %s transform to %d", oc->name, tr);
diff -uNr a/sway/desktop/output.c b/sway/desktop/output.c
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -4,11 +4,10 @@
 #include <strings.h>
 #include <time.h>
 #include <wayland-server-core.h>
-#include <wlr/backend/drm.h>
+#include <wlr/config.h>
 #include <wlr/backend/headless.h>
 #include <wlr/render/wlr_renderer.h>
 #include <wlr/types/wlr_buffer.h>
-#include <wlr/types/wlr_drm_lease_v1.h>
 #include <wlr/types/wlr_matrix.h>
 #include <wlr/types/wlr_output_layout.h>
 #include <wlr/types/wlr_output.h>
@@ -31,6 +30,11 @@
 #include "sway/tree/view.h"
 #include "sway/tree/workspace.h"
 
+#if WLR_HAS_DRM_BACKEND
+#include <wlr/backend/drm.h>
+#include <wlr/types/wlr_drm_lease_v1.h>
+#endif
+
 struct sway_output *output_by_name_or_id(const char *name_or_id) {
 	for (int i = 0; i < root->outputs->length; ++i) {
 		struct sway_output *output = root->outputs->items[i];
@@ -915,10 +919,12 @@
 	if (wlr_output->non_desktop) {
 		sway_log(SWAY_DEBUG, "Not configuring non-desktop output");
 		struct sway_output_non_desktop *non_desktop = output_non_desktop_create(wlr_output);
+#if WLR_HAS_DRM_BACKEND
 		if (server->drm_lease_manager) {
 			wlr_drm_lease_v1_manager_offer_output(server->drm_lease_manager,
 					wlr_output);
 		}
+#endif
 		list_add(root->non_desktop_outputs, non_desktop);
 		return;
 	}
diff -uNr a/sway/desktop/render.c b/sway/desktop/render.c
--- a/sway/desktop/render.c
+++ b/sway/desktop/render.c
@@ -1,11 +1,10 @@
 #define _POSIX_C_SOURCE 200809L
 #include <assert.h>
-#include <GLES2/gl2.h>
 #include <stdlib.h>
 #include <strings.h>
 #include <time.h>
 #include <wayland-server-core.h>
-#include <wlr/render/gles2.h>
+#include <wlr/config.h>
 #include <wlr/render/wlr_renderer.h>
 #include <wlr/types/wlr_buffer.h>
 #include <wlr/types/wlr_damage_ring.h>
@@ -28,6 +27,10 @@
 #include "sway/tree/view.h"
 #include "sway/tree/workspace.h"
 
+#if WLR_HAS_GLES2_RENDERER
+#include <wlr/render/gles2.h>
+#endif
+
 struct render_data {
 	pixman_region32_t *damage;
 	float alpha;
@@ -74,6 +77,7 @@
 
 static void set_scale_filter(struct wlr_output *wlr_output,
 		struct wlr_texture *texture, enum scale_filter_mode scale_filter) {
+#if WLR_HAS_GLES2_RENDERER
 	if (!wlr_texture_is_gles2(texture)) {
 		return;
 	}
@@ -94,6 +98,7 @@
 	case SCALE_FILTER_SMART:
 		assert(false); // unreachable
 	}
+#endif
 }
 
 static void render_texture(struct wlr_output *wlr_output,
diff -uNr a/sway/input/input-manager.c b/sway/input/input-manager.c
--- a/sway/input/input-manager.c
+++ b/sway/input/input-manager.c
@@ -3,7 +3,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <math.h>
-#include <wlr/backend/libinput.h>
+#include <wlr/config.h>
 #include <wlr/types/wlr_cursor.h>
 #include <wlr/types/wlr_keyboard_group.h>
 #include <wlr/types/wlr_input_inhibitor.h>
@@ -22,6 +22,10 @@
 #include "list.h"
 #include "log.h"
 
+#if WLR_HAS_LIBINPUT_BACKEND
+#include <wlr/backend/libinput.h>
+#endif
+
 #define DEFAULT_SEAT "seat0"
 
 struct input_config *current_input_config = NULL;
@@ -90,6 +94,7 @@
 }
 
 static bool device_is_touchpad(struct sway_input_device *device) {
+#if WLR_HAS_LIBINPUT_BACKEND
 	if (device->wlr_device->type != WLR_INPUT_DEVICE_POINTER ||
 			!wlr_input_device_is_libinput(device->wlr_device)) {
 		return false;
@@ -99,6 +104,9 @@
 		wlr_libinput_get_device_handle(device->wlr_device);
 
 	return libinput_device_config_tap_get_finger_count(libinput_device) > 0;
+#else
+	return false;
+#endif
 }
 
 const char *input_device_get_type(struct sway_input_device *device) {
@@ -236,7 +244,11 @@
 
 	apply_input_type_config(input_device);
 
+#if WLR_HAS_LIBINPUT_BACKEND
 	bool config_changed = sway_input_configure_libinput_device(input_device);
+#else
+	bool config_changed = false;
+#endif
 
 	wl_signal_add(&device->events.destroy, &input_device->device_destroy);
 	input_device->device_destroy.notify = handle_device_destroy;
@@ -532,7 +544,11 @@
 
 static void input_manager_configure_input(
 		struct sway_input_device *input_device) {
+#if WLR_HAS_LIBINPUT_BACKEND
 	bool config_changed = sway_input_configure_libinput_device(input_device);
+#else
+	bool config_changed = false;
+#endif
 	struct sway_seat *seat = NULL;
 	wl_list_for_each(seat, &server.input->seats, link) {
 		seat_configure_device(seat, input_device);
@@ -567,7 +583,9 @@
 }
 
 void input_manager_reset_input(struct sway_input_device *input_device) {
+#if WLR_HAS_LIBINPUT_BACKEND
 	sway_input_reset_libinput_device(input_device);
+#endif
 	struct sway_seat *seat = NULL;
 	wl_list_for_each(seat, &server.input->seats, link) {
 		seat_reset_device(seat, input_device);
diff -uNr a/sway/input/keyboard.c b/sway/input/keyboard.c
--- a/sway/input/keyboard.c
+++ b/sway/input/keyboard.c
@@ -1,8 +1,8 @@
 #include <assert.h>
 #include <limits.h>
 #include <strings.h>
+#include <wlr/config.h>
 #include <wlr/backend/multi.h>
-#include <wlr/backend/session.h>
 #include <wlr/interfaces/wlr_keyboard.h>
 #include <wlr/types/wlr_idle.h>
 #include <wlr/types/wlr_keyboard.h>
@@ -16,6 +16,10 @@
 #include "sway/ipc-server.h"
 #include "log.h"
 
+#if WLR_HAS_SESSION
+#include <wlr/backend/session.h>
+#endif
+
 static struct modifier_key {
 	char *name;
 	uint32_t mod;
@@ -264,14 +268,12 @@
 		xkb_keysym_t keysym = pressed_keysyms[i];
 		if (keysym >= XKB_KEY_XF86Switch_VT_1 &&
 				keysym <= XKB_KEY_XF86Switch_VT_12) {
-			if (wlr_backend_is_multi(server.backend)) {
-				struct wlr_session *session =
-					wlr_backend_get_session(server.backend);
-				if (session) {
-					unsigned vt = keysym - XKB_KEY_XF86Switch_VT_1 + 1;
-					wlr_session_change_vt(session, vt);
-				}
+#if WLR_HAS_SESSION
+			if (server.session) {
+				unsigned vt = keysym - XKB_KEY_XF86Switch_VT_1 + 1;
+				wlr_session_change_vt(server.session, vt);
 			}
+#endif
 			return true;
 		}
 	}
diff -uNr a/sway/input/seat.c b/sway/input/seat.c
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -4,6 +4,7 @@
 #include <string.h>
 #include <strings.h>
 #include <time.h>
+#include <wlr/config.h>
 #include <wlr/types/wlr_cursor.h>
 #include <wlr/types/wlr_data_device.h>
 #include <wlr/types/wlr_idle.h>
@@ -747,6 +748,7 @@
 			mapped_to_output = NULL;
 			break;
 		}
+#if WLR_HAS_LIBINPUT_BACKEND
 		if (mapped_to_output == NULL && is_touch_or_tablet_tool(sway_device) &&
 				sway_libinput_device_is_builtin(sway_device->input_device)) {
 			mapped_to_output = get_builtin_output_name();
@@ -755,6 +757,10 @@
 					mapped_to_output, sway_device->input_device->identifier);
 			}
 		}
+#else
+		(void)is_touch_or_tablet_tool;
+		(void)get_builtin_output_name;
+#endif
 		if (mapped_to_output == NULL) {
 			return;
 		}
diff -uNr a/sway/input/tablet.c b/sway/input/tablet.c
--- a/sway/input/tablet.c
+++ b/sway/input/tablet.c
@@ -1,6 +1,6 @@
 #define _POSIX_C_SOURCE 200809L
 #include <stdlib.h>
-#include <wlr/backend/libinput.h>
+#include <wlr/config.h>
 #include <wlr/types/wlr_tablet_v2.h>
 #include <wlr/types/wlr_tablet_tool.h>
 #include <wlr/types/wlr_tablet_pad.h>
@@ -9,6 +9,10 @@
 #include "sway/input/seat.h"
 #include "sway/input/tablet.h"
 
+#if WLR_HAS_LIBINPUT_BACKEND
+#include <wlr/backend/libinput.h>
+#endif
+
 static void handle_pad_tablet_destroy(struct wl_listener *listener, void *data) {
 	struct sway_tablet_pad *pad =
 		wl_container_of(listener, pad, tablet_destroy);
@@ -63,6 +67,7 @@
 			wlr_tablet_create(server.tablet_v2, seat->wlr_seat, device);
 	}
 
+#if WLR_HAS_LIBINPUT_BACKEND
 	/* Search for a sibling tablet pad */
 	if (!wlr_input_device_is_libinput(device)) {
 		/* We can only do this on libinput devices */
@@ -87,6 +92,7 @@
 			break;
 		}
 	}
+#endif
 }
 
 void sway_tablet_destroy(struct sway_tablet *tablet) {
@@ -287,6 +293,7 @@
 	tablet_pad->ring.notify = handle_tablet_pad_ring;
 	wl_signal_add(&tablet_pad->wlr->events.ring, &tablet_pad->ring);
 
+#if WLR_HAS_LIBINPUT_BACKEND
 	/* Search for a sibling tablet */
 	if (!wlr_input_device_is_libinput(wlr_device)) {
 		/* We can only do this on libinput devices */
@@ -311,6 +318,7 @@
 			break;
 		}
 	}
+#endif
 }
 
 void sway_tablet_pad_destroy(struct sway_tablet_pad *tablet_pad) {
diff -uNr a/sway/ipc-json.c b/sway/ipc-json.c
--- a/sway/ipc-json.c
+++ b/sway/ipc-json.c
@@ -3,8 +3,8 @@
 #include <json.h>
 #include <libevdev/libevdev.h>
 #include <stdio.h>
-#include <wlr/backend/libinput.h>
 #include <wlr/types/wlr_output.h>
+#include <wlr/config.h>
 #include <xkbcommon/xkbcommon.h>
 #include "config.h"
 #include "log.h"
@@ -20,6 +20,10 @@
 #include "wlr-layer-shell-unstable-v1-protocol.h"
 #include "sway/desktop/idle_inhibit_v1.h"
 
+#if WLR_HAS_LIBINPUT_BACKEND
+#include <wlr/backend/libinput.h>
+#endif
+
 static const int i3_output_id = INT32_MAX;
 static const int i3_scratch_id = INT32_MAX - 1;
 
@@ -822,6 +822,7 @@
 	return object;
 }
 
+#if WLR_HAS_LIBINPUT_BACKEND
 static json_object *describe_libinput_device(struct libinput_device *device) {
 	json_object *object = json_object_new_object();
 
@@ -1027,6 +1028,7 @@
 
 	return object;
 }
+#endif
 
 json_object *ipc_json_describe_input(struct sway_input_device *device) {
 	if (!(sway_assert(device, "Device must not be null"))) {
@@ -1090,12 +1092,14 @@
 				json_object_new_double(scroll_factor));
 	}
 
+#if WLR_HAS_LIBINPUT_BACKEND
 	if (wlr_input_device_is_libinput(device->wlr_device)) {
 		struct libinput_device *libinput_dev;
 		libinput_dev = wlr_libinput_get_device_handle(device->wlr_device);
 		json_object_object_add(object, "libinput",
 				describe_libinput_device(libinput_dev));
 	}
+#endif
 
 	return object;
 }
diff -uNr a/sway/meson.build b/sway/meson.build
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -26,7 +26,6 @@
 	'input/input-manager.c',
 	'input/cursor.c',
 	'input/keyboard.c',
-	'input/libinput.c',
 	'input/seat.c',
 	'input/seatop_default.c',
 	'input/seatop_down.c',
@@ -227,12 +226,16 @@
 	wayland_server,
 	wlroots,
 	xkbcommon,
+	xcb,
 	xcb_icccm,
 ]
 
 if have_xwayland
 	sway_sources += 'desktop/xwayland.c'
-	sway_deps += xcb
+endif
+
+if wlroots_features['libinput_backend']
+	sway_sources += 'input/libinput.c'
 endif
 
 executable(
diff -uNr a/sway/server.c b/sway/server.c
--- a/sway/server.c
+++ b/sway/server.c
@@ -7,12 +7,10 @@
 #include <wlr/backend.h>
 #include <wlr/backend/headless.h>
 #include <wlr/backend/multi.h>
-#include <wlr/backend/session.h>
 #include <wlr/config.h>
 #include <wlr/render/wlr_renderer.h>
 #include <wlr/types/wlr_compositor.h>
 #include <wlr/types/wlr_data_control_v1.h>
-#include <wlr/types/wlr_drm_lease_v1.h>
 #include <wlr/types/wlr_drm.h>
 #include <wlr/types/wlr_export_dmabuf_v1.h>
 #include <wlr/types/wlr_gamma_control_v1.h>
@@ -49,6 +47,11 @@
 #include "sway/xwayland.h"
 #endif
 
+#if WLR_HAS_DRM_BACKEND
+#include <wlr/types/wlr_drm_lease_v1.h>
+#endif
+
+#if WLR_HAS_DRM_BACKEND
 static void handle_drm_lease_request(struct wl_listener *listener, void *data) {
 	/* We only offer non-desktop outputs, but in the future we might want to do
 	 * more logic here. */
@@ -60,6 +63,7 @@
 		wlr_drm_lease_request_v1_reject(req);
 	}
 }
+#endif
 
 #define SWAY_XDG_SHELL_VERSION	2
 
@@ -67,8 +71,8 @@
 	sway_log(SWAY_DEBUG, "Initializing Wayland server");
 	server->wl_display = wl_display_create();
 	server->wl_event_loop = wl_display_get_event_loop(server->wl_display);
-	server->backend = wlr_backend_autocreate(server->wl_display);
 
+	server->backend = wlr_backend_autocreate(server->wl_display, &server->session);
 	if (!server->backend) {
 		sway_log(SWAY_ERROR, "Unable to create backend");
 		return false;
@@ -186,6 +190,7 @@
 
 	sway_session_lock_init();
 
+#if WLR_HAS_DRM_BACKEND
 	server->drm_lease_manager=
 		wlr_drm_lease_v1_manager_create(server->wl_display, server->backend);
 	if (server->drm_lease_manager) {
@@ -196,6 +201,7 @@
 		sway_log(SWAY_DEBUG, "Failed to create wlr_drm_lease_device_v1");
 		sway_log(SWAY_INFO, "VR will not be available");
 	}
+#endif
 
 	wlr_export_dmabuf_manager_v1_create(server->wl_display);
 	wlr_screencopy_manager_v1_create(server->wl_display);
