diff --git a/CMakeLists.txt b/CMakeLists.txt index a633b94826072f9a0aa13f488abf9249486fe893..039b1865eb51062a158a0044b21fdb35da1d937a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,6 +74,8 @@ cmake_dependent_option(BUILD_WITH_DBUS "Enable dbus support (for BLE support)" O cmake_dependent_option(BUILD_COMPOSITOR_MAIN "Build main compositor host" ON "BUILD_WITH_WAYLAND OR BUILD_WITH_XCB" OFF) cmake_dependent_option(XRT_BUILD_IPC "Build OpenXR runtime target" ON "BUILD_COMPOSITOR_MAIN" OFF) cmake_dependent_option(XRT_HAVE_SYSTEMD "Enable systemd support (for socket activation of service)" ON "Systemd_FOUND AND XRT_BUILD_IPC" OFF) +cmake_dependent_option(XRT_INSTALL_SYSTEMD_UNIT_FILES "Install user unit files for systemd socket activation on installation" ON "XRT_HAVE_SYSTEMD" OFF) +cmake_dependent_option(XRT_INSTALL_ABSOLUTE_SYSTEMD_UNIT_FILES "Use an absolute path to monado-system in installed user unit files for systemd socket activation" ON "XRT_INSTALL_SYSTEMD_UNIT_FILES" OFF) cmake_dependent_option(BUILD_TARGET_OPENXR "Build OpenXR runtime target" ON "BUILD_COMPOSITOR_MAIN OR XRT_BUILD_IPC" OFF) # Most users won't touch these. diff --git a/doc/changes/big/mr.306.md b/doc/changes/big/mr.306.md new file mode 100644 index 0000000000000000000000000000000000000000..61d6272a2c52753a46ae3f5f39c6369f2bdfb791 --- /dev/null +++ b/doc/changes/big/mr.306.md @@ -0,0 +1 @@ +Support optional systemd socket-activation: if not disabled at configure time, `monado-service` can be launched by systemd as a service with an associated socket. If the service is launched this way, it will use the systemd-created domain socket instead of creating its own. (If launched manually, it will still create its own as normal.) This allows optional auto-launching of the service when running a client (OpenXR) application. Associated systemd unit files are also included. diff --git a/src/xrt/targets/service/CMakeLists.txt b/src/xrt/targets/service/CMakeLists.txt index f36d54820ef0df14a329c0dc5918fea0574690e0..37ee300a8f3c103046d637d6606d6259351bda0f 100644 --- a/src/xrt/targets/service/CMakeLists.txt +++ b/src/xrt/targets/service/CMakeLists.txt @@ -18,3 +18,63 @@ target_link_libraries(monado-service PRIVATE install(TARGETS monado-service RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) + +if(XRT_HAVE_SYSTEMD) + set(SERVICE_INPUT ${CMAKE_CURRENT_SOURCE_DIR}/monado.in.service) + set(SOCKET_INPUT ${CMAKE_CURRENT_SOURCE_DIR}/monado.in.socket) + ### + # Generate systemd unit files with absolute path to service intended for development without installing + set(UNIT_NAME monado-dev) + set(service_path $<TARGET_FILE:monado-service>) + set(conflicts monado) + set(exit_on_disconnect ON) + set(extra_desc "in build tree") + configure_file(${SOCKET_INPUT} ${CMAKE_CURRENT_BINARY_DIR}/${UNIT_NAME}.socket) + # Need this step because file(GENERATE) only evaluates generator expressions, and not what configure_file does. + configure_file(${SERVICE_INPUT} ${CMAKE_CURRENT_BINARY_DIR}/${UNIT_NAME}-intermediate.service) + file(GENERATE + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${UNIT_NAME}.service" + INPUT ${CMAKE_CURRENT_BINARY_DIR}/${UNIT_NAME}-intermediate.service) + + configure_file(${SOCKET_INPUT} ${CMAKE_CURRENT_BINARY_DIR}/${UNIT_NAME}.socket @ONLY) + + # Make a custom target to link those in. + add_custom_target(link-systemd-dev-units + COMMAND systemctl --user link ${CMAKE_CURRENT_BINARY_DIR}/${UNIT_NAME}.socket + COMMAND systemctl --user link ${CMAKE_CURRENT_BINARY_DIR}/${UNIT_NAME}.service + COMMAND systemctl --user daemon-reload + VERBATIM + COMMENT "Linking monado-dev.{socket,service} into your local systemd unit directory." + ) +endif() + +if(XRT_INSTALL_SYSTEMD_UNIT_FILES) + set(UNIT_NAME monado) + set(conflicts monado-dev) + set(exit_on_disconnect OFF) + + # Try to ask where to install it + pkg_get_variable(PC_SYSTEMD_USERUNITDIR systemd systemduserunitdir) + pkg_get_variable(PC_SYSTEMD_PREFIX systemd prefix) + if(NOT DEFINED XRT_SYSTEMD_UNIT_INSTALL_DIR) + # Fallback dest + set(XRT_SYSTEMD_UNIT_INSTALL_DIR lib/systemd/user) + if(PC_SYSTEMD_USERUNITDIR AND PC_SYSTEMD_PREFIX) + # Strip prefix + string(REGEX REPLACE "^${PC_SYSTEMD_PREFIX}/" "" XRT_SYSTEMD_UNIT_INSTALL_DIR "${PC_SYSTEMD_USERUNITDIR}") + endif() + set(XRT_SYSTEMD_UNIT_INSTALL_DIR "${XRT_SYSTEMD_UNIT_INSTALL_DIR}" CACHE STRING "The (absolute, or CMAKE_INSTALL_PREFIX-relative) path to install the systemd user unit files.") + mark_as_advanced(XRT_SYSTEMD_UNIT_INSTALL_DIR) + endif() + if(XRT_SYSTEMD_UNIT_INSTALL_DIR MATCHES "^/") + # Destination is absolute: prepend only destdir at install time + set(UNIT_DIR "\$ENV{DESTDIR}${XRT_SYSTEMD_UNIT_INSTALL_DIR}") + else() + # Destination is relative: prepend destdir and install prefix at install time + set(UNIT_DIR "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${XRT_SYSTEMD_UNIT_INSTALL_DIR}") + endif() + configure_file(configure_and_install_units.cmake ${CMAKE_CURRENT_BINARY_DIR}/configure_and_install_units.cmake @ONLY) + + # This script will configure the units and install them at install time. + install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/configure_and_install_units.cmake) +endif() diff --git a/src/xrt/targets/service/configure_and_install_units.cmake b/src/xrt/targets/service/configure_and_install_units.cmake new file mode 100644 index 0000000000000000000000000000000000000000..e58681e7d1e836c4ee3d4a351efcd51869acdeed --- /dev/null +++ b/src/xrt/targets/service/configure_and_install_units.cmake @@ -0,0 +1,26 @@ +# Copyright 2020, Collabora, Ltd. +# SPDX-License-Identifier: BSL-1.0 + +set(XRT_INSTALL_ABSOLUTE_SYSTEMD_UNIT_FILES @XRT_INSTALL_ABSOLUTE_SYSTEMD_UNIT_FILES@) + +# Set up variables to use when configuring files +set(conflicts @conflicts@) +set(exit_on_disconnect @exit_on_disconnect@) +set(service_path "monado-service") +if(XRT_INSTALL_ABSOLUTE_SYSTEMD_UNIT_FILES) + set(service_path + "${CMAKE_INSTALL_PREFIX}/@CMAKE_INSTALL_BINDIR@/${service_path}") +endif() + +# Create unit files +configure_file(@SOCKET_INPUT@ "@CMAKE_CURRENT_BINARY_DIR@/@UNIT_NAME@.socket") +configure_file(@SERVICE_INPUT@ "@CMAKE_CURRENT_BINARY_DIR@/@UNIT_NAME@.service") + +# Install them +file( + INSTALL + DESTINATION "@UNIT_DIR@" + TYPE FILE + FILES + "@CMAKE_CURRENT_BINARY_DIR@/@UNIT_NAME@.socket" + "@CMAKE_CURRENT_BINARY_DIR@/@UNIT_NAME@.service") diff --git a/src/xrt/targets/service/monado.in.service b/src/xrt/targets/service/monado.in.service new file mode 100644 index 0000000000000000000000000000000000000000..b32a79bf69743ba112f74c3d1de185aede8279d3 --- /dev/null +++ b/src/xrt/targets/service/monado.in.service @@ -0,0 +1,15 @@ +[Unit] +Description=Monado XR runtime service module @extra_desc@ +Requires=%N.socket +ConditionUser=!root +Conflicts=@conflicts@.service + +[Service] +ExecStart=@service_path@ +Environment="XRT_COMPOSITOR_PRINT_DEBUG=on" "XRT_PRINT_OPTIONS=on" "IPC_EXIT_ON_DISCONNECT=@exit_on_disconnect@" +# MemoryDenyWriteExecute=yes +# NoNewPrivileges=yes +Restart=no + +[Install] +Also=%N.socket diff --git a/src/xrt/targets/service/monado.in.socket b/src/xrt/targets/service/monado.in.socket new file mode 100644 index 0000000000000000000000000000000000000000..7192215cc71f9bc36e52732aa02975803751c6e9 --- /dev/null +++ b/src/xrt/targets/service/monado.in.socket @@ -0,0 +1,10 @@ +[Unit] +Description=Monado XR service module connection socket @extra_desc@ +ConditionUser=!root +Conflicts=@conflicts@.socket + +[Socket] +ListenStream=/tmp/monado_comp_ipc + +[Install] +WantedBy=sockets.target