diff --git a/docker/ubuntu-26.04.dockerfile b/docker/ubuntu-26.04.dockerfile new file mode 100644 index 000000000..33ff5a25e --- /dev/null +++ b/docker/ubuntu-26.04.dockerfile @@ -0,0 +1,133 @@ +# syntax=docker/dockerfile:1 +# artifacts: true +# platforms: linux/amd64,linux/arm64/v8 +# platforms_pr: linux/amd64 +# no-cache-filters: sunshine-base,artifacts,sunshine +ARG BASE=ubuntu +ARG TAG=26.04 +FROM ${BASE}:${TAG} AS sunshine-base + +ENV DEBIAN_FRONTEND=noninteractive + +FROM sunshine-base AS sunshine-deps + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +# Copy only the build script first for better layer caching +WORKDIR /build/sunshine/ +COPY --link scripts/linux_build.sh ./scripts/linux_build.sh + +# Install dependencies first - this layer will be cached +RUN <<_DEPS +#!/bin/bash +set -e +chmod +x ./scripts/linux_build.sh +./scripts/linux_build.sh \ + --step=deps \ + --sudo-off +apt-get clean +rm -rf /var/lib/apt/lists/* +_DEPS + +FROM sunshine-deps AS sunshine-build + +ARG BRANCH +ARG BUILD_VERSION +ARG COMMIT +# note: BUILD_VERSION may be blank + +ENV BRANCH=${BRANCH} +ENV BUILD_VERSION=${BUILD_VERSION} +ENV COMMIT=${COMMIT} + +# Now copy the full repository +COPY --link .. . + +# Configure, validate, build and package +RUN <<_BUILD +#!/bin/bash +set -e +./scripts/linux_build.sh \ + --step=cmake \ + --publisher-name='LizardByte' \ + --publisher-website='https://app.lizardbyte.dev' \ + --publisher-issue-url='https://app.lizardbyte.dev/support' \ + --sudo-off + +./scripts/linux_build.sh \ + --step=validation \ + --sudo-off + +./scripts/linux_build.sh \ + --step=build \ + --sudo-off + +./scripts/linux_build.sh \ + --step=package \ + --sudo-off +_BUILD + +# run tests +WORKDIR /build/sunshine/build/tests +RUN <<_TEST +#!/bin/bash +set -e +export DISPLAY=:1 +Xvfb ${DISPLAY} -screen 0 1024x768x24 & +./test_sunshine --gtest_color=yes +_TEST + +FROM sunshine-base AS sunshine + +ARG BASE +ARG TAG +ARG TARGETARCH + +# artifacts to be extracted in CI +COPY --link --from=sunshine-build /build/sunshine/build/cpack_artifacts/Sunshine.deb /artifacts/sunshine-${BASE}-${TAG}-${TARGETARCH}.deb + +# copy deb from builder +COPY --link --from=sunshine-build /build/sunshine/build/cpack_artifacts/Sunshine.deb /sunshine.deb + +# install sunshine +RUN <<_INSTALL_SUNSHINE +#!/bin/bash +set -e +apt-get update -y +apt-get install -y --no-install-recommends /sunshine.deb +apt-get clean +rm -rf /var/lib/apt/lists/* +_INSTALL_SUNSHINE + +# network setup +EXPOSE 47984-47990/tcp +EXPOSE 48010 +EXPOSE 47998-48000/udp + +# setup user +ARG PGID=1001 +ENV PGID=${PGID} +ARG PUID=1001 +ENV PUID=${PUID} +ENV TZ="UTC" +ARG UNAME=lizard +ENV UNAME=${UNAME} + +ENV HOME=/home/$UNAME + +# setup user +RUN <<_SETUP_USER +#!/bin/bash +set -e +groupadd -f -g "${PGID}" "${UNAME}" +useradd -lm -d ${HOME} -s /bin/bash -g "${PGID}" -u "${PUID}" "${UNAME}" +mkdir -p ${HOME}/.config/sunshine +ln -s ${HOME}/.config/sunshine /config +chown -R ${UNAME} ${HOME} +_SETUP_USER + +USER ${UNAME} +WORKDIR ${HOME} + +# entrypoint +ENTRYPOINT ["/usr/bin/sunshine"] diff --git a/docs/building.md b/docs/building.md index 91c0dd3d5..54d195b7f 100644 --- a/docs/building.md +++ b/docs/building.md @@ -69,7 +69,7 @@ Sunshine requires CUDA Toolkit for NVFBC capture. There are two caveats to CUDA: 1. The version installed depends on the version of GCC. 2. The version of CUDA you use will determine compatibility with various GPU generations. - At the time of writing, the recommended version to use is CUDA ~12.9. + At the time of writing, the recommended version to use is CUDA ~13.1. See [CUDA compatibility](https://docs.nvidia.com/deploy/cuda-compatibility/index.html) for more info. > [!NOTE] diff --git a/docs/getting_started.md b/docs/getting_started.md index dc7b8e4a4..c82117480 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -68,8 +68,8 @@ CUDA is used for NVFBC capture. Package - 12.9.1 - 575.57.08 + 13.1.1 + 590.48.01 50;52;60;61;62;70;72;75;80;86;87;89;90;100;101;103;120;121 sunshine.AppImage diff --git a/scripts/linux_build.sh b/scripts/linux_build.sh index f4a6d2bfe..00fc97dee 100755 --- a/scripts/linux_build.sh +++ b/scripts/linux_build.sh @@ -7,10 +7,17 @@ target_cmake_version="3.30.1" doxygen_min="1.10.0" _doxygen_min="${doxygen_min//\./_}" # Convert dots to underscores for URL doxygen_max="1.12.0" +default_cuda_version="13.1.1" +default_cuda_build="590.48.01" # Default value for arguments appimage_build=0 +cuda_version="$default_cuda_version" +cuda_build="$default_cuda_build" cuda_patches=0 +cuda_system_package=0 +cuda_system_package_name="" +force_cuda_runfile=0 num_processors=$(nproc) publisher_name="Third Party Publisher" publisher_website="" @@ -27,6 +34,97 @@ step="all" AARCH64="aarch64" DOXYGEN="doxygen" +function setup_cuda_system_package_environment() { + if [[ "$cuda_system_package" == 1 ]]; then + # Ubuntu CUDA 13 packages install nvcc here but do not add it to PATH. + local cuda_bin_path + cuda_bin_path="$(cuda_system_toolkit_path)/bin" + if [[ ":${PATH}:" != *":${cuda_bin_path}:"* ]]; then + export PATH="${cuda_bin_path}:${PATH}" + fi + fi + return 0 +} + +function cuda_system_toolkit_path() { + local cuda_minor_version="${cuda_version%.*}" + echo "/usr/local/cuda-${cuda_minor_version}" +} + +function cuda_target_dir() { + if [[ "$architecture" == "${AARCH64}" ]]; then + echo "sbsa-linux" + else + echo "x86_64-linux" + fi +} + +function cuda_math_functions_patch_applied() { + local cuda_toolkit_path=$1 + local math_functions_file + math_functions_file="${cuda_toolkit_path}/targets/$(cuda_target_dir)/include/crt/math_functions.h" + + if [[ ! -f "$math_functions_file" ]]; then + return 1 + fi + + grep -Fq "rsqrt(double x) noexcept (true)" "$math_functions_file" && \ + grep -Fq "rsqrtf(float x) noexcept (true)" "$math_functions_file" && \ + grep -Fq "__func__(double rsqrt(double a) noexcept (true));" "$math_functions_file" && \ + grep -Fq "__func__(float rsqrtf(float a) noexcept (true));" "$math_functions_file" +} + +function apply_cuda_patches() { + local cuda_toolkit_path=$1 + + if [[ "$cuda_patches" != 1 ]]; then + return 0 + fi + + if [[ ! -d "$cuda_toolkit_path" ]]; then + echo "CUDA toolkit path not found: $cuda_toolkit_path" + return 1 + fi + + if cuda_math_functions_patch_applied "$cuda_toolkit_path"; then + echo "CUDA math_functions.h patch already applied" + return 0 + fi + + echo "Applying CUDA patches" + local patch_dir="${script_dir}/../packaging/linux/patches/${architecture}" + local patch_file="" + + # Select the patch based on the CUDA major version, not the distro version. + # see https://forums.developer.nvidia.com/t/error-exception-specification-is-incompatible-for-cospi-sinpi-cospif-sinpif-with-glibc-2-41/323591/3 + local cuda_major="${cuda_version%%.*}" + if [[ "${cuda_major}" -eq 12 ]]; then + # CUDA 12.x: the extern declarations lack noexcept(true); add it to match glibc 2.41. + patch_file="${patch_dir}/cuda-12-math_functions.patch" + elif [[ "${cuda_major}" -eq 13 ]]; then + # CUDA 13.x: the extern declarations already have noexcept(true), but the __func__() + # macro invocations at the bottom still lack it, causing a redeclaration conflict. + patch_file="${patch_dir}/cuda-13-math_functions.patch" + else + echo "Warning: no math_functions.h patch available for CUDA ${cuda_major}.x, skipping." + fi + + if [[ -n "$patch_file" ]]; then + if [[ -f "$patch_file" ]]; then + echo "Applying patch: $patch_file" + ${sudo_cmd} patch -p2 \ + --backup \ + --directory="$cuda_toolkit_path" \ + --verbose \ + < "$patch_file" + else + echo "Patch file not found: $patch_file" + fi + else + echo "No CUDA patch required for ${distro} ${version}" + fi +} + # Reusable function to detect nvcc path function detect_nvcc_path() { local nvcc_path="" @@ -81,7 +179,10 @@ Options: -h, --help Display this help message. -s, --sudo-off Disable sudo command. --appimage-build Compile for AppImage, this will not create the AppImage, just the executable. - --cuda-patches Apply cuda patches. + --cuda-patches Apply cuda patches. Enabled automatically on Ubuntu 26.04. + --cuda-runfile Force CUDA installation from the NVIDIA runfile. + --cuda-system-package=* The CUDA package to install when system CUDA is enabled. + Default for Ubuntu 26.04 is cuda-toolkit-13-1. --num-processors The number of processors to use for compilation. Default is the value of 'nproc'. --publisher-name The name of the publisher (not developer) of the application. --publisher-website The URL of the publisher's website. @@ -122,6 +223,12 @@ while getopts ":hs-:" opt; do cuda-patches) cuda_patches=1 ;; + cuda-runfile) + force_cuda_runfile=1 + ;; + cuda-system-package=*) + cuda_system_package_name="${OPTARG#*=}" + ;; num-processors=*) num_processors="${OPTARG#*=}" ;; @@ -229,6 +336,7 @@ function add_debian_based_deps() { "g++-${gcc_version}" "git" "graphviz" + "libayatana-appindicator3-dev" "libcap-dev" # KMS "libcurl4-openssl-dev" "libdrm-dev" # KMS @@ -283,7 +391,6 @@ function add_debian_deps() { add_test_ppa add_debian_based_deps dependencies+=( - "libayatana-appindicator3-dev" "systemd-dev" ) return 0 @@ -292,9 +399,24 @@ function add_debian_deps() { function add_ubuntu_deps() { add_test_ppa add_debian_based_deps - dependencies+=( - "libappindicator3-dev" - ) + + if [[ "$skip_cuda" == 0 ]] && [[ "$cuda_system_package" == 1 ]]; then + if [[ -z "$cuda_system_package_name" ]]; then + echo "CUDA system package was requested, but no package name was configured." + return 1 + fi + + echo "Using CUDA system package: $cuda_system_package_name" + dependencies+=( + "$cuda_system_package_name" + ) + fi + + if [[ "$(printf '%s\n' "$version" "24.04" | sort -V | head -n1)" == "24.04" ]]; then + dependencies+=( + "systemd-dev" + ) + fi return 0 } @@ -352,9 +474,22 @@ function add_fedora_deps() { } function install_cuda() { + setup_cuda_system_package_environment + # Check if CUDA is already available - if detect_nvcc_path > /dev/null 2>&1; then + if [[ "$force_cuda_runfile" == 1 ]] && [[ -f "${build_dir}/cuda/bin/nvcc" ]]; then + apply_cuda_patches "${build_dir}/cuda" return + elif [[ "$force_cuda_runfile" == 0 ]] && detect_nvcc_path > /dev/null 2>&1; then + if [[ "$cuda_system_package" == 1 ]]; then + apply_cuda_patches "$(cuda_system_toolkit_path)" + fi + return + fi + + if [[ "$cuda_system_package" == 1 ]]; then + echo "CUDA system package '$cuda_system_package_name' was requested, but nvcc was not found after dependency installation." + return 1 fi local cuda_override_arg="" @@ -396,41 +531,7 @@ function install_cuda() { "${build_dir}/cuda.run" --silent --toolkit --toolkitpath="${build_dir}/cuda" --no-opengl-libs --no-man-page --no-drm "$cuda_override_arg" rm "${build_dir}/cuda.run" - # run cuda patches - if [[ "$cuda_patches" == 1 ]]; then - echo "Applying CUDA patches" - local patch_dir="${script_dir}/../packaging/linux/patches/${architecture}" - local patch_file="" - - # Select the patch based on the CUDA major version, not the distro version. - # see https://forums.developer.nvidia.com/t/error-exception-specification-is-incompatible-for-cospi-sinpi-cospif-sinpif-with-glibc-2-41/323591/3 - local cuda_major="${cuda_version%%.*}" - if [[ "${cuda_major}" -eq 12 ]]; then - # CUDA 12.x: the extern declarations lack noexcept(true); add it to match glibc 2.41. - patch_file="${patch_dir}/cuda-12-math_functions.patch" - elif [[ "${cuda_major}" -eq 13 ]]; then - # CUDA 13.x: the extern declarations already have noexcept(true), but the __func__() - # macro invocations at the bottom still lack it, causing a redeclaration conflict. - patch_file="${patch_dir}/cuda-13-math_functions.patch" - else - echo "Warning: no math_functions.h patch available for CUDA ${cuda_major}.x, skipping." - fi - - if [[ -n "$patch_file" ]]; then - if [[ -f "$patch_file" ]]; then - echo "Applying patch: $patch_file" - patch -p2 \ - --backup \ - --directory="${build_dir}/cuda" \ - --verbose \ - < "$patch_file" - else - echo "Patch file not found: $patch_file" - fi - else - echo "No CUDA patch required for ${distro} ${version}" - fi - fi + apply_cuda_patches "${build_dir}/cuda" return 0 } @@ -556,11 +657,19 @@ function run_step_cmake() { # Setup NVM environment if needed (for web UI builds) setup_nvm_environment + setup_cuda_system_package_environment + if [[ "$skip_cuda" == 0 ]] && [[ "$cuda_system_package" == 1 ]]; then + apply_cuda_patches "$(cuda_system_toolkit_path)" + fi # Detect CUDA path using the reusable function nvcc_path="" if [[ "$skip_cuda" == 0 ]]; then - nvcc_path=$(detect_nvcc_path) + if [[ "$force_cuda_runfile" == 1 ]] && [[ -f "${build_dir}/cuda/bin/nvcc" ]]; then + nvcc_path="${build_dir}/cuda/bin/nvcc" + else + nvcc_path=$(detect_nvcc_path) + fi fi #set gcc version based on distros @@ -723,8 +832,6 @@ elif grep -q "Debian GNU/Linux 12 (bookworm)" /etc/os-release; then version="12" package_update_command="${sudo_cmd} apt-get update" package_install_command="${sudo_cmd} apt-get install -y" - cuda_version="12.9.1" - cuda_build="575.57.08" gcc_version="13" nvm_node=0 elif grep -q "Debian GNU/Linux 13 (trixie)" /etc/os-release; then @@ -732,8 +839,6 @@ elif grep -q "Debian GNU/Linux 13 (trixie)" /etc/os-release; then version="13" package_update_command="${sudo_cmd} apt-get update" package_install_command="${sudo_cmd} apt-get install -y" - cuda_version="12.9.1" - cuda_build="575.57.08" gcc_version="14" nvm_node=0 elif grep -q "PLATFORM_ID=\"platform:f42\"" /etc/os-release; then @@ -741,8 +846,6 @@ elif grep -q "PLATFORM_ID=\"platform:f42\"" /etc/os-release; then version="42" package_update_command="${sudo_cmd} dnf update -y" package_install_command="${sudo_cmd} dnf install -y" - cuda_version="12.9.1" - cuda_build="575.57.08" gcc_version="14" nvm_node=0 elif grep -q '^ID=fedora$' /etc/os-release && grep -q '^VERSION_ID=43$' /etc/os-release; then @@ -750,8 +853,6 @@ elif grep -q '^ID=fedora$' /etc/os-release && grep -q '^VERSION_ID=43$' /etc/os- version="43" package_update_command="${sudo_cmd} dnf update -y" package_install_command="${sudo_cmd} dnf install -y" - cuda_version="12.9.1" - cuda_build="575.57.08" gcc_version="14" nvm_node=0 elif grep -q '^ID=fedora$' /etc/os-release && grep -q '^VERSION_ID=44$' /etc/os-release; then @@ -759,8 +860,6 @@ elif grep -q '^ID=fedora$' /etc/os-release && grep -q '^VERSION_ID=44$' /etc/os- version="44" package_update_command="${sudo_cmd} dnf update -y" package_install_command="${sudo_cmd} dnf install -y" - cuda_version="12.9.1" - cuda_build="575.57.08" gcc_version="14" nvm_node=0 elif grep -q '^ID=fedora$' /etc/os-release && grep -q '^VERSION_ID=45$' /etc/os-release; then @@ -777,8 +876,6 @@ elif grep -q "Ubuntu 22.04" /etc/os-release; then version="22.04" package_update_command="${sudo_cmd} apt-get update" package_install_command="${sudo_cmd} apt-get install -y" - cuda_version="12.9.1" - cuda_build="575.57.08" gcc_version="14" nvm_node=1 elif grep -q "Ubuntu 24.04" /etc/os-release; then @@ -786,8 +883,6 @@ elif grep -q "Ubuntu 24.04" /etc/os-release; then version="24.04" package_update_command="${sudo_cmd} apt-get update" package_install_command="${sudo_cmd} apt-get install -y" - cuda_version="12.9.1" - cuda_build="575.57.08" gcc_version="14" nvm_node=1 elif grep -q "Ubuntu 25.04" /etc/os-release; then @@ -795,8 +890,6 @@ elif grep -q "Ubuntu 25.04" /etc/os-release; then version="25.04" package_update_command="${sudo_cmd} apt-get update" package_install_command="${sudo_cmd} apt-get install -y" - cuda_version="12.9.1" - cuda_build="575.57.08" gcc_version="14" nvm_node=0 elif grep -q "Ubuntu 25.10" /etc/os-release; then @@ -804,8 +897,20 @@ elif grep -q "Ubuntu 25.10" /etc/os-release; then version="25.10" package_update_command="${sudo_cmd} apt-get update" package_install_command="${sudo_cmd} apt-get install -y" - cuda_version="12.9.1" - cuda_build="575.57.08" + gcc_version="14" + nvm_node=0 +elif grep -q 'VERSION_ID="26.04"' /etc/os-release; then + distro="ubuntu" + version="26.04" + package_update_command="${sudo_cmd} apt-get update" + package_install_command="${sudo_cmd} apt-get install -y" + cuda_patches=1 + if [[ "$force_cuda_runfile" == 0 ]]; then + cuda_system_package=1 + if [[ -z "$cuda_system_package_name" ]]; then + cuda_system_package_name="cuda-toolkit-13-1" + fi + fi gcc_version="14" nvm_node=0 else