# linux specific compile definitions if(FREEBSD) add_compile_definitions(SUNSHINE_PLATFORM="freebsd") else() add_compile_definitions(SUNSHINE_PLATFORM="linux") endif() # AppImage if(${SUNSHINE_BUILD_APPIMAGE}) # use relative assets path for AppImage string(REPLACE "${CMAKE_INSTALL_PREFIX}" ".${CMAKE_INSTALL_PREFIX}" SUNSHINE_ASSETS_DIR_DEF ${SUNSHINE_ASSETS_DIR}) endif() # cuda set(CUDA_FOUND OFF) if(${SUNSHINE_ENABLE_CUDA}) include(CheckLanguage) check_language(CUDA) if(CMAKE_CUDA_COMPILER) set(CUDA_FOUND ON) enable_language(CUDA) message(STATUS "CUDA Compiler Version: ${CMAKE_CUDA_COMPILER_VERSION}") set(CMAKE_CUDA_ARCHITECTURES "") # https://docs.nvidia.com/cuda/archive/12.0.0/cuda-compiler-driver-nvcc/index.html if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0) list(APPEND CMAKE_CUDA_ARCHITECTURES 75 80 86 87 89 90) else() message(FATAL_ERROR "Sunshine requires a minimum CUDA Compiler version of 12.0. Found version: ${CMAKE_CUDA_COMPILER_VERSION}" ) endif() # https://docs.nvidia.com/cuda/archive/12.8.0/cuda-compiler-driver-nvcc/index.html if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 12.8) list(APPEND CMAKE_CUDA_ARCHITECTURES 100 101 120) endif() # https://docs.nvidia.com/cuda/archive/12.9.0/cuda-compiler-driver-nvcc/index.html if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 12.9) list(APPEND CMAKE_CUDA_ARCHITECTURES 103 121) endif() # https://docs.nvidia.com/cuda/archive/13.0.0/cuda-compiler-driver-nvcc/index.html if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0) list(REMOVE_ITEM CMAKE_CUDA_ARCHITECTURES 101) list(APPEND CMAKE_CUDA_ARCHITECTURES 110) else() list(APPEND CMAKE_CUDA_ARCHITECTURES 50 52 53 60 61 62 70 72) endif() # sort the architectures list(SORT CMAKE_CUDA_ARCHITECTURES COMPARE NATURAL) # message(STATUS "CUDA NVCC Flags: ${CUDA_NVCC_FLAGS}") message(STATUS "CUDA Architectures: ${CMAKE_CUDA_ARCHITECTURES}") elseif(${CUDA_FAIL_ON_MISSING}) message(FATAL_ERROR "CUDA not found. If this is intentional, set '-DSUNSHINE_ENABLE_CUDA=OFF' or '-DCUDA_FAIL_ON_MISSING=OFF'" ) endif() endif() if(CUDA_FOUND) include_directories(SYSTEM "${CMAKE_SOURCE_DIR}/third-party/nvfbc") list(APPEND PLATFORM_TARGET_FILES "${CMAKE_SOURCE_DIR}/src/platform/linux/cuda.h" "${CMAKE_SOURCE_DIR}/src/platform/linux/cuda.cu" "${CMAKE_SOURCE_DIR}/src/platform/linux/cuda.cpp" "${CMAKE_SOURCE_DIR}/third-party/nvfbc/NvFBC.h") add_compile_definitions(SUNSHINE_BUILD_CUDA) endif() # libdrm is required for DRM (KMS), KWin ScreenCast and Wayland if(${SUNSHINE_ENABLE_DRM} OR ${SUNSHINE_ENABLE_KWIN} OR ${SUNSHINE_ENABLE_WAYLAND}) find_package(LIBDRM REQUIRED) else() set(LIBDRM_FOUND OFF) endif() if(LIBDRM_FOUND) include_directories(SYSTEM ${LIBDRM_INCLUDE_DIRS}) list(APPEND PLATFORM_LIBRARIES ${LIBDRM_LIBRARIES}) endif() # drm if(${SUNSHINE_ENABLE_DRM}) find_package(LIBCAP REQUIRED) else() set(LIBCAP_FOUND OFF) endif() if(LIBDRM_FOUND AND LIBCAP_FOUND) add_compile_definitions(SUNSHINE_BUILD_DRM) include_directories(SYSTEM ${LIBCAP_INCLUDE_DIRS}) list(APPEND PLATFORM_LIBRARIES ${LIBCAP_LIBRARIES}) list(APPEND PLATFORM_TARGET_FILES "${CMAKE_SOURCE_DIR}/src/platform/linux/kmsgrab.cpp") list(APPEND SUNSHINE_DEFINITIONS EGL_NO_X11=1) endif() # evdev include(dependencies/libevdev_Sunshine) # vaapi if(${SUNSHINE_ENABLE_VAAPI}) find_package(Libva REQUIRED) else() set(LIBVA_FOUND OFF) endif() if(LIBVA_FOUND) add_compile_definitions(SUNSHINE_BUILD_VAAPI) include_directories(SYSTEM ${LIBVA_INCLUDE_DIR}) list(APPEND PLATFORM_LIBRARIES ${LIBVA_LIBRARIES} ${LIBVA_DRM_LIBRARIES}) list(APPEND PLATFORM_TARGET_FILES "${CMAKE_SOURCE_DIR}/src/platform/linux/vaapi.h" "${CMAKE_SOURCE_DIR}/src/platform/linux/vaapi.cpp") endif() # vulkan video encoding (via FFmpeg) if(${SUNSHINE_ENABLE_VULKAN}) if(NOT SUNSHINE_SYSTEM_VULKAN_HEADERS) # use Vulkan headers from build-deps submodule (system headers may be too old, e.g. Ubuntu 22.04) set(VULKAN_HEADERS_DIR "${CMAKE_SOURCE_DIR}/third-party/build-deps/third-party/FFmpeg/Vulkan-Headers/include") else() find_package(VulkanHeaders REQUIRED) get_target_property(VULKAN_HEADERS_DIR Vulkan::Headers INTERFACE_INCLUDE_DIRECTORIES) endif() if(NOT EXISTS "${VULKAN_HEADERS_DIR}/vulkan/vulkan.h") message(FATAL_ERROR "Vulkan headers not found in build-deps submodule") endif() find_library(VULKAN_LIBRARY NAMES vulkan vulkan-1) if(NOT VULKAN_LIBRARY) message(FATAL_ERROR "libvulkan not found") endif() # prefer glslc, fall back to glslangValidator find_program(GLSLC_EXECUTABLE glslc) if(NOT GLSLC_EXECUTABLE) find_program(GLSLANG_EXECUTABLE glslangValidator) endif() if(NOT GLSLC_EXECUTABLE AND NOT GLSLANG_EXECUTABLE) message(FATAL_ERROR "Vulkan shader compiler not found (need glslc or glslangValidator)") endif() list(APPEND SUNSHINE_DEFINITIONS SUNSHINE_BUILD_VULKAN=1) include_directories(SYSTEM ${VULKAN_HEADERS_DIR}) list(APPEND PLATFORM_LIBRARIES ${VULKAN_LIBRARY}) list(APPEND PLATFORM_TARGET_FILES "${CMAKE_SOURCE_DIR}/src/platform/linux/vulkan_encode.h" "${CMAKE_SOURCE_DIR}/src/platform/linux/vulkan_encode.cpp") # compile GLSL -> SPIR-V -> C include at build time set(VULKAN_SHADER_DIR "${CMAKE_BINARY_DIR}/generated-src/shaders") set(VULKAN_SHADER_SOURCE "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/assets/shaders/vulkan/rgb2yuv.comp") set(VULKAN_SHADER_SPV "${VULKAN_SHADER_DIR}/rgb2yuv.spv") set(VULKAN_SHADER_DATA "${VULKAN_SHADER_DIR}/rgb2yuv.spv.inc") file(MAKE_DIRECTORY "${VULKAN_SHADER_DIR}") if(GLSLC_EXECUTABLE) add_custom_command( OUTPUT "${VULKAN_SHADER_SPV}" COMMAND ${GLSLC_EXECUTABLE} -O "${VULKAN_SHADER_SOURCE}" -o "${VULKAN_SHADER_SPV}" DEPENDS "${VULKAN_SHADER_SOURCE}" COMMENT "Compiling Vulkan shader rgb2yuv.comp (glslc)" VERBATIM) else() add_custom_command( OUTPUT "${VULKAN_SHADER_SPV}" COMMAND ${GLSLANG_EXECUTABLE} -V -o "${VULKAN_SHADER_SPV}" "${VULKAN_SHADER_SOURCE}" DEPENDS "${VULKAN_SHADER_SOURCE}" COMMENT "Compiling Vulkan shader rgb2yuv.comp (glslangValidator)" VERBATIM) endif() add_custom_command( OUTPUT "${VULKAN_SHADER_DATA}" COMMAND ${CMAKE_COMMAND} -DSPV_FILE=${VULKAN_SHADER_SPV} -DOUT_FILE=${VULKAN_SHADER_DATA} -P "${CMAKE_SOURCE_DIR}/cmake/scripts/binary_to_c.cmake" DEPENDS "${VULKAN_SHADER_SPV}" COMMENT "Generating C include from rgb2yuv.spv" VERBATIM) add_custom_target(vulkan_shaders DEPENDS "${VULKAN_SHADER_DATA}" COMMENT "Vulkan shader compilation") set(SUNSHINE_TARGET_DEPENDENCIES ${SUNSHINE_TARGET_DEPENDENCIES} vulkan_shaders) endif() # wayland if(${SUNSHINE_ENABLE_WAYLAND}) find_package(Wayland REQUIRED) else() set(WAYLAND_FOUND OFF) endif() if(WAYLAND_FOUND) add_compile_definitions(SUNSHINE_BUILD_WAYLAND) if(NOT SUNSHINE_SYSTEM_WAYLAND_PROTOCOLS) set(WAYLAND_PROTOCOLS_DIR "${CMAKE_SOURCE_DIR}/third-party/wayland-protocols") else() pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir) pkg_check_modules(WAYLAND_PROTOCOLS wayland-protocols REQUIRED) endif() GEN_WAYLAND("${WAYLAND_PROTOCOLS_DIR}" "unstable/xdg-output" xdg-output-unstable-v1) GEN_WAYLAND("${WAYLAND_PROTOCOLS_DIR}" "unstable/linux-dmabuf" linux-dmabuf-unstable-v1) GEN_WAYLAND("${CMAKE_SOURCE_DIR}/third-party/wlr-protocols" "unstable" wlr-screencopy-unstable-v1) include_directories( SYSTEM ${WAYLAND_INCLUDE_DIRS} ${CMAKE_BINARY_DIR}/generated-src ) list(APPEND PLATFORM_LIBRARIES ${WAYLAND_LIBRARIES} gbm) list(APPEND PLATFORM_TARGET_FILES "${CMAKE_SOURCE_DIR}/src/platform/linux/wlgrab.cpp" "${CMAKE_SOURCE_DIR}/src/platform/linux/wayland.h" "${CMAKE_SOURCE_DIR}/src/platform/linux/wayland.cpp") endif() # x11 if(${SUNSHINE_ENABLE_X11}) find_package(X11 REQUIRED) else() set(X11_FOUND OFF) endif() if(X11_FOUND) add_compile_definitions(SUNSHINE_BUILD_X11) include_directories(SYSTEM ${X11_INCLUDE_DIR}) list(APPEND PLATFORM_LIBRARIES ${X11_LIBRARIES}) list(APPEND PLATFORM_TARGET_FILES "${CMAKE_SOURCE_DIR}/src/platform/linux/x11grab.h" "${CMAKE_SOURCE_DIR}/src/platform/linux/x11grab.cpp") endif() # GIO pkg_check_modules(GIO gio-2.0 gio-unix-2.0 REQUIRED) if(GIO_FOUND) include_directories(SYSTEM ${GIO_INCLUDE_DIRS}) list(APPEND PLATFORM_LIBRARIES ${GIO_LIBRARIES}) endif() # Pipewire if(${SUNSHINE_ENABLE_KWIN} OR ${SUNSHINE_ENABLE_PORTAL}) pkg_check_modules(PIPEWIRE libpipewire-0.3 REQUIRED) else() set(PIPEWIRE_FOUND OFF) endif() if(PIPEWIRE_FOUND) include_directories(SYSTEM ${PIPEWIRE_INCLUDE_DIRS}) list(APPEND PLATFORM_LIBRARIES ${PIPEWIRE_LIBRARIES}) list(APPEND PLATFORM_TARGET_FILES "${CMAKE_SOURCE_DIR}/src/platform/linux/pipewire.cpp") endif() # XDG portal set(PORTAL_FOUND OFF) if(PIPEWIRE_FOUND AND GIO_FOUND AND ${SUNSHINE_ENABLE_PORTAL}) set(PORTAL_FOUND ON) add_compile_definitions(SUNSHINE_BUILD_PORTAL) list(APPEND PLATFORM_TARGET_FILES "${CMAKE_SOURCE_DIR}/src/platform/linux/portalgrab.cpp") endif() # KWin ScreenCast (direct Wayland protocol, bypasses portal) set(KWIN_FOUND OFF) if(PIPEWIRE_FOUND AND WAYLAND_FOUND AND ${SUNSHINE_ENABLE_KWIN}) set(KWIN_FOUND ON) add_compile_definitions(SUNSHINE_BUILD_KWIN) GEN_WAYLAND("${CMAKE_SOURCE_DIR}/third-party/plasma-wayland-protocols/src/protocols" "" kde-output-order-v1) GEN_WAYLAND("${CMAKE_SOURCE_DIR}/third-party/plasma-wayland-protocols/src/protocols" "" zkde-screencast-unstable-v1) list(APPEND PLATFORM_TARGET_FILES "${CMAKE_SOURCE_DIR}/src/platform/linux/kwingrab.cpp") elseif(${SUNSHINE_ENABLE_KWIN} AND NOT WAYLAND_FOUND) message(FATAL_ERROR "SUNSHINE_ENABLE_KWIN requires SUNSHINE_ENABLE_WAYLAND — KWin capture disabled") endif() if(NOT ${CUDA_FOUND} AND NOT (${LIBDRM_FOUND} AND ${LIBCAP_FOUND}) AND NOT ${LIBVA_FOUND} AND NOT ${KWIN_FOUND} AND NOT ${PORTAL_FOUND} AND NOT ${WAYLAND_FOUND} AND NOT ${X11_FOUND}) message(FATAL_ERROR "Couldn't find either cuda, (libdrm and libcap), libva, kwin, pipewire, portal, wayland or x11") endif() # tray icon if(${SUNSHINE_ENABLE_TRAY}) pkg_check_modules(APPINDICATOR ayatana-appindicator3-0.1) if(APPINDICATOR_FOUND) list(APPEND SUNSHINE_DEFINITIONS TRAY_AYATANA_APPINDICATOR=1) else() pkg_check_modules(APPINDICATOR appindicator3-0.1) if(APPINDICATOR_FOUND) list(APPEND SUNSHINE_DEFINITIONS TRAY_LEGACY_APPINDICATOR=1) endif () endif() pkg_check_modules(LIBNOTIFY libnotify) if(NOT APPINDICATOR_FOUND OR NOT LIBNOTIFY_FOUND) message(STATUS "APPINDICATOR_FOUND: ${APPINDICATOR_FOUND}") message(STATUS "LIBNOTIFY_FOUND: ${LIBNOTIFY_FOUND}") message(FATAL_ERROR "Couldn't find either appindicator or libnotify") else() include_directories(SYSTEM ${APPINDICATOR_INCLUDE_DIRS} ${LIBNOTIFY_INCLUDE_DIRS}) link_directories(${APPINDICATOR_LIBRARY_DIRS} ${LIBNOTIFY_LIBRARY_DIRS}) list(APPEND PLATFORM_TARGET_FILES "${CMAKE_SOURCE_DIR}/third-party/tray/src/tray_linux.c") list(APPEND SUNSHINE_EXTERNAL_LIBRARIES ${APPINDICATOR_LIBRARIES} ${LIBNOTIFY_LIBRARIES}) endif() set(SUNSHINE_TRAY_PREFIX "${PROJECT_FQDN}") list(APPEND SUNSHINE_DEFINITIONS SUNSHINE_TRAY_PREFIX="${SUNSHINE_TRAY_PREFIX}") else() set(SUNSHINE_TRAY 0) message(STATUS "Tray icon disabled") endif() # These need to be set before adding the inputtino subdirectory in order for them to be picked up set(LIBEVDEV_CUSTOM_INCLUDE_DIR "${EVDEV_INCLUDE_DIR}") set(LIBEVDEV_CUSTOM_LIBRARY "${EVDEV_LIBRARY}") if(FREEBSD) set(USE_UHID OFF) endif() add_subdirectory("${CMAKE_SOURCE_DIR}/third-party/inputtino") list(APPEND SUNSHINE_EXTERNAL_LIBRARIES inputtino::libinputtino) file(GLOB_RECURSE INPUTTINO_SOURCES ${CMAKE_SOURCE_DIR}/src/platform/linux/input/inputtino*.h ${CMAKE_SOURCE_DIR}/src/platform/linux/input/inputtino*.cpp) list(APPEND PLATFORM_TARGET_FILES ${INPUTTINO_SOURCES}) # build libevdev before the libinputtino target if(EXTERNAL_PROJECT_LIBEVDEV_USED) add_dependencies(libinputtino libevdev) endif() # AppImage and Flatpak if (${SUNSHINE_BUILD_APPIMAGE}) list(APPEND SUNSHINE_DEFINITIONS SUNSHINE_BUILD_APPIMAGE=1) endif () if (${SUNSHINE_BUILD_FLATPAK}) list(APPEND SUNSHINE_DEFINITIONS SUNSHINE_BUILD_FLATPAK=1) endif () list(APPEND PLATFORM_TARGET_FILES "${CMAKE_SOURCE_DIR}/src/platform/linux/publish.cpp" "${CMAKE_SOURCE_DIR}/src/platform/linux/graphics.h" "${CMAKE_SOURCE_DIR}/src/platform/linux/graphics.cpp" "${CMAKE_SOURCE_DIR}/src/platform/linux/misc.h" "${CMAKE_SOURCE_DIR}/src/platform/linux/misc.cpp" "${CMAKE_SOURCE_DIR}/src/platform/linux/audio.cpp") list(APPEND PLATFORM_LIBRARIES dl pulse pulse-simple) list(APPEND SUNSHINE_EXTERNAL_LIBRARIES glad)