diff --git a/README.md b/README.md index b31608322..96f2894d8 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,10 @@ Sunshine is a Gamestream host for Moonlight ## Linux +If you do not wish to clutter your PC with development files, yet you want the very latest version... +You can use these [build scripts](scripts/README.md) +They make use of docker to handle building Sunshine automatically + ### Requirements: Ubuntu 20.04: @@ -41,6 +45,7 @@ sudo apt install libwayland-dev #### Cuda + NvFBC This requires proprietary software +On Ubuntu 20.04, the cuda compiler will fail since it's version is too old, it's recommended you compile the sources with the [build scripts](scripts/README.md) ``` sudo apt install nvidia-cuda-dev nvidia-cuda-toolkit ``` diff --git a/appveyor.yml b/appveyor.yml index 782b58c23..7994c1abf 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,40 +1,36 @@ -image: - - Ubuntu2004 - - Visual Studio 2019 +services: + - docker environment: matrix: - - BUILD_TYPE: Debug - - BUILD_TYPE: Release + - APPVEYOR_BUILD_WORKER_IMAGE: Ubuntu2004 + DOCKERFILE: Dockerfile-2004 + - APPVEYOR_BUILD_WORKER_IMAGE: Ubuntu2004 + DOCKERFILE: Dockerfile-2104 + - APPVEYOR_BUILD_WORKER_IMAGE: Ubuntu2004 + DOCKERFILE: Dockerfile-debian + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + BUILD_TYPE: Release install: - - sh: sudo apt update --ignore-missing - - sh: sudo apt install -y build-essential fakeroot gcc-10 g++-10 cmake libssl-dev libavdevice-dev libboost-thread-dev libboost-filesystem-dev libboost-log-dev libpulse-dev libopus-dev libxtst-dev libx11-dev libxrandr-dev libxfixes-dev libevdev-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev libdrm-dev libcap-dev software-properties-common wget curl - - sh: sudo apt list --installed - - sh: sudo wget https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/cuda_11.4.2_470.57.02_linux.run -O cuda_11.4.2_470.57.02_linux.run - - sh: sudo sh cuda_11.4.2_470.57.02_linux.run --silent --toolkit --no-opengl-libs --no-man-page --no-drm - - sh: export PATH=/usr/local/cuda-11.4/bin${PATH:+:${PATH}} - - sh: export LD_LIBRARY_PATH=/usr/local/cuda-11.4/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}} - # - sh: export APPVEYOR_SSH_BLOCK=true - # - sh: curl -sflL 'https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-ssh.sh' | bash -e - - cmd: C:\msys64\usr\bin\bash -lc "pacman --needed --noconfirm -S mingw-w64-x86_64-openssl mingw-w64-x86_64-cmake mingw-w64-x86_64-toolchain mingw-w64-x86_64-opus mingw-w64-x86_64-x265 mingw-w64-x86_64-boost git yasm nasm diffutils make" before_build: - - git submodule update --init --recursive - - mkdir build - - cd build + - cmd: git submodule update --init --recursive + - cmd: mkdir build + - cmd: cd build + - sh: cd scripts + - sh: ./build-container.sh -f $DOCKERFILE build_script: - cmd: set OLDPATH=%PATH% - cmd: set PATH=C:\msys64\mingw64\bin - - sh: cmake -DCMAKE_C_COMPILER=gcc-10 -DCMAKE_CXX_COMPILER=g++-10 -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSUNSHINE_EXECUTABLE_PATH=sunshine -DSUNSHINE_ASSETS_DIR=/etc/sunshine .. - cmd: cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSUNSHINE_ASSETS_DIR=assets -G "MinGW Makefiles" .. - - sh: make -j$(nproc) - cmd: mingw32-make -j2 - cmd: set PATH=%OLDPATH% + - sh: ./build-sunshine.sh -pu after_build: - - sh: ./gen-deb - cmd: Del ..\assets\apps_linux.json - cmd: 7z a Sunshine-Windows.zip ..\assets - cmd: 7z a Sunshine-Windows.zip sunshine.exe @@ -44,5 +40,5 @@ after_build: - cmd: 7z a Sunshine-Windows.zip ..\tools\install-service.bat - cmd: 7z a Sunshine-Windows.zip ..\tools\uninstall-service.bat - cmd: appveyor PushArtifact Sunshine-Windows.zip - - sh: appveyor PushArtifact package-deb/sunshine.deb - - sh: appveyor PushArtifact sunshine.service + - sh: appveyor PushArtifact sunshine-build/sunshine.deb + diff --git a/scripts/Dockerfile-2004 b/scripts/Dockerfile-2004 new file mode 100644 index 000000000..fe4dc326f --- /dev/null +++ b/scripts/Dockerfile-2004 @@ -0,0 +1,18 @@ +FROM ubuntu:20.04 AS sunshine-2004 + +ARG DEBIAN_FRONTEND=noninteractive +ARG TZ="Europe/London" + +RUN apt-get update -y && \ + apt-get install -y \ + git wget gcc-10 g++-10 build-essential cmake libssl-dev libavdevice-dev libboost-thread-dev libboost-filesystem-dev libboost-log-dev libpulse-dev libopus-dev libxtst-dev libx11-dev libxrandr-dev libxfixes-dev libevdev-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev libdrm-dev libcap-dev libwayland-dev + +RUN cp /usr/bin/gcc-10 /usr/bin/gcc && cp /usr/bin/g++-10 /usr/bin/gcc-10 + +RUN wget https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/cuda_11.4.2_470.57.02_linux.run --progress=bar:force:noscroll -q --show-progress -O /root/cuda.run && chmod a+x /root/cuda.run +RUN /root/cuda.run --silent --toolkit --toolkitpath=/usr --no-opengl-libs --no-man-page --no-drm && rm /root/cuda.run + +COPY build-private.sh /root/build.sh + + +ENTRYPOINT ["/root/build.sh"] diff --git a/scripts/Dockerfile-2104 b/scripts/Dockerfile-2104 new file mode 100644 index 000000000..b8174a36c --- /dev/null +++ b/scripts/Dockerfile-2104 @@ -0,0 +1,13 @@ +FROM ubuntu:21.04 AS sunshine-2104 + +ARG DEBIAN_FRONTEND=noninteractive +ARG TZ="Europe/London" + +RUN apt-get update -y && \ + apt-get install -y \ + git build-essential cmake libssl-dev libavdevice-dev libboost-thread-dev libboost-filesystem-dev libboost-log-dev libpulse-dev libopus-dev libxtst-dev libx11-dev libxrandr-dev libxfixes-dev libevdev-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev libdrm-dev libcap-dev libwayland-dev nvidia-cuda-dev nvidia-cuda-toolkit + +COPY build-private.sh /root/build.sh + + +ENTRYPOINT ["/root/build.sh"] diff --git a/scripts/Dockerfile-debian b/scripts/Dockerfile-debian new file mode 100644 index 000000000..253a4d45c --- /dev/null +++ b/scripts/Dockerfile-debian @@ -0,0 +1,14 @@ +FROM debian:bullseye AS sunshine-debian + +ARG DEBIAN_FRONTEND=noninteractive +ARG TZ="Europe/London" + +RUN echo deb http://deb.debian.org/debian/ bullseye main contrib non-free | tee /etc/apt/sources.list.d/non-free.list +RUN apt-get update -y && \ + apt-get install -y \ + git build-essential cmake libssl-dev libavdevice-dev libboost-thread-dev libboost-filesystem-dev libboost-log-dev libpulse-dev libopus-dev libxtst-dev libx11-dev libxrandr-dev libxfixes-dev libevdev-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev libdrm-dev libcap-dev libwayland-dev nvidia-cuda-dev nvidia-cuda-toolkit + +COPY build-private.sh /root/build.sh + + +ENTRYPOINT ["/root/build.sh"] diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 000000000..5c2068d47 --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,53 @@ +# Introduction +Sunshine is a Gamestream host for Moonlight + +[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/cgrtw2g3fq9b0b70/branch/master?svg=true)](https://ci.appveyor.com/project/loki-47-6F-64/sunshine/branch/master) +[![Downloads](https://img.shields.io/github/downloads/Loki-47-6F-64/sunshine/total)](https://github.com/Loki-47-6F-64/sunshine/releases) + +You may wish to simply build sunshine from source, without bloating your OS with development files. +These scripts will create a docker images that have the necessary packages. As a result, removing the development files after you're done is a single command away. +These scripts use docker under the hood, as such, they can only be used to compile the Linux version + + +#### Requirements + +``` +sudo apt install docker +``` + +#### instructions + +You'll require one of the following Dockerfiles: +* Dockerfile-2004 --> Ubuntu 20.04 +* Dockerfile-2104 --> Ubuntu 21.04 +* Dockerfile-debian --> Debian Bullseye + +Depending on your system, the build-* scripts may need root privilleges + +First, the docker container needs to be created: +``` +cd scripts +./build-container.sh -f Dockerfile- +``` + +Then, the sources will be compiled and the debian package generated: +``` +./build-sunshine -p -s .. +``` +You can run `build-sunshine -p -s ..` again as long as the docker container exists. + +``` +git pull +./build-sunshine -p -s .. +``` + +Optionally, the docker container can be removed after you're finished: +``` +./build-container.sh -c delete +``` + +Finally install the resulting package: +``` +sudo apt install -f sunshine-build/sunshine.deb +``` + diff --git a/scripts/build-container.sh b/scripts/build-container.sh new file mode 100755 index 000000000..e332c7bb0 --- /dev/null +++ b/scripts/build-container.sh @@ -0,0 +1,174 @@ +#/bin/bash -e + +function usage { + echo "Usage: $0 [OPTIONS]" + echo " -c: command --> default [build]" + echo " | delete --> Delete the container, Dockerfile isn't mandatory" + echo " | build --> Build the container, Dockerfile is mandatory" + echo " | compile --> Builds the container, then compiles it. Dockerfile is mandatory" + echo "" + echo " -n: name: Docker container name --> default [sunshine]" + echo " --> all: Build/Compile/Delete all available docker containers" + echo " -f: Dockerfile: The name of the docker file" +} + +# Attempt to turn relative paths into absolute paths +function absolute_path() { + RELATIVE_PATH=$1 + if which realpath >/dev/null 2>/dev/null + then + RELATIVE_PATH=$(realpath $RELATIVE_PATH) + else + echo "Warning: realpath is not installed on your system, ensure [$1] is absolute" + fi + + RETURN=$RELATIVE_PATH +} + +CONTAINER_NAME=sunshine +COMMAND=BUILD + +function build_container() { + CONTAINER_NAME=$1 + DOCKER_FILE=$2 + + if [ ! -f "$DOCKER_FILE" ] + then + echo "Error: $DOCKER_FILE doesn't exist" + exit 7 + fi + + echo "docker build . -t $CONTAINER_NAME -f $DOCKER_FILE" + docker build . -t "$CONTAINER_NAME" -f "$DOCKER_FILE" +} + +function delete() { + CONTAINER_NAME_UPPER=$(echo "$CONTAINER_NAME" | tr '[:lower:]' '[:upper:]') + if [ "$CONTAINER_NAME_UPPER" == "ALL" ] + then + shopt -s nullglob + for file in $(find . -maxdepth 1 -iname "Dockerfile-*" -type f) + do + CURRENT_CONTAINER="sunshine-$(echo $file | cut -c 14-)" + + if docker inspect "$CURRENT_CONTAINER" > /dev/null 2> /dev/null + then + echo "docker rmi $CURRENT_CONTAINER" + docker rmi "$CURRENT_CONTAINER" + fi + done + shopt -u nullglob #revert nullglob back to it's normal default state + else + if docker inspect "$CONTAINER_NAME" > /dev/null 2> /dev/null + then + echo "docker rmi $CONTAINER_NAME" + docker rmi $CONTAINER_NAME + fi + fi +} + +function build() { + CONTAINER_NAME_UPPER=$(echo "$CONTAINER_NAME" | tr '[:lower:]' '[:upper:]') + if [ "$CONTAINER_NAME_UPPER" == "ALL" ] + then + shopt -s nullglob + for file in $(find . -maxdepth 1 -iname "Dockerfile-*" -type f) + do + CURRENT_CONTAINER="sunshine-$(echo $file | cut -c 14-)" + build_container "$CURRENT_CONTAINER" "$file" + done + shopt -u nullglob #revert nullglob back to it's normal default state + else + if [[ -z "$DOCKER_FILE" ]] + then + echo "Error: if container name isn't equal to 'all', you need to specify the Dockerfile" + exit 6 + fi + + build_container "$CONTAINER_NAME" "$DOCKER_FILE" + fi +} + +function abort() { + echo "$1" + exit 10 +} + +function compile() { + CONTAINER_NAME_UPPER=$(echo "$CONTAINER_NAME" | tr '[:lower:]' '[:upper:]') + if [ "$CONTAINER_NAME_UPPER" == "ALL" ] + then + shopt -s nullglob + + # If any docker container doesn't exist, we cannot compile all of them + for file in $(find . -maxdepth 1 -iname "Dockerfile-*" -type f) + do + CURRENT_CONTAINER="sunshine-$(echo $file | cut -c 14-)" + + # If container doesn't exist --> abort. + docker inspect "$CURRENT_CONTAINER" > /dev/null 2> /dev/null || abort "Error: container image [$CURRENT_CONTAINER] doesn't exist" + done + + for file in $(find . -maxdepth 1 -iname "Dockerfile-*" -type f) + do + CURRENT_CONTAINER="sunshine-$(echo $file | cut -c 14-)" + + echo "$PWD/build-sunshine.sh -p -n $CURRENT_CONTAINER" + "$PWD/build-sunshine.sh" -p -n "$CURRENT_CONTAINER" + done + shopt -u nullglob #revert nullglob back to it's normal default state + else + # If container exists + if docker inspect "$CURRENT_CONTAINER" > /dev/null 2> /dev/null + then + echo "$PWD/build-sunshine.sh -p -n $CONTAINER_NAME" + "$PWD/build-sunshine.sh" -p -n "$CONTAINER_NAME" + else + echo "Error: container image [$CONTAINER_NAME] doesn't exist" + exit 9 + fi + fi +} + +while getopts ":c:hn:f:" arg; do + case ${arg} in + c) + COMMAND=$(echo $OPTARG | tr '[:lower:]' '[:upper:]') + ;; + n) + echo "Container name: $OPTARG" + CONTAINER_NAME="$OPTARG" + ;; + f) + echo "Using Dockerfile [$OPTARG]" + DOCKER_FILE="$OPTARG" + ;; + h) + usage + exit 0 + ;; + esac +done + +echo "$0 set to $(echo $COMMAND | tr '[:upper:]' '[:lower:]')" + +if [[ "$COMMAND" == "BUILD" ]] +then + echo "Start building..." + delete + build + echo "Done." +elif [[ "$COMMAND" == "COMPILE" ]] +then + echo "Start compiling..." + compile + echo "Done." +elif [[ "$COMMAND" == "DELETE" ]] +then + echo "Start deleting..." + delete + echo "Done." +else + echo "Unknown command [$(echo $COMMAND | tr '[:upper:]' '[:lower:]')]" + exit 4 +fi diff --git a/scripts/build-private.sh b/scripts/build-private.sh new file mode 100755 index 000000000..1526a754b --- /dev/null +++ b/scripts/build-private.sh @@ -0,0 +1,34 @@ +#!/bin/bash -e + +CMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" +SUNSHINE_EXECUTABLE_PATH="${SUNSHINE_EXECUTABLE_PATH:-/usr/bin/sunshine}" +SUNSHINE_ASSETS_DIR="${SUNSHINE_ASSETS_DIR:-/etc/sunshine}" + + +SUNSHINE_ROOT="${SUNSHINE_ROOT:-/root/sunshine}" +SUNSHINE_TAG="${SUNSHINE_TAG:-master}" +SUNSHINE_GIT_URL="${SUNSHINE_GIT_URL:-https://github.com/loki-47-6F-64/sunshine.git}" + + +SUNSHINE_ENABLE_WAYLAND=${SUNSHINE_ENABLE_WAYLAND:-ON} +SUNSHINE_ENABLE_X11=${SUNSHINE_ENABLE_X11:-ON} +SUNSHINE_ENABLE_DRM=${SUNSHINE_ENABLE_DRM:-ON} +SUNSHINE_ENABLE_CUDA=${SUNSHINE_ENABLE_CUDA:-ON} + +# For debugging, it would be usefull to have the sources on the host. +if [[ ! -d "$SUNSHINE_ROOT" ]] +then + git clone --depth 1 --branch "$SUNSHINE_TAG" "$SUNSHINE_GIT_URL" --recurse-submodules "$SUNSHINE_ROOT" +fi + +if [[ ! -d /root/sunshine-build ]] +then + mkdir -p /root/sunshine-build +fi +cd /root/sunshine-build + +cmake "-DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE" "-DSUNSHINE_EXECUTABLE_PATH=$SUNSHINE_EXECUTABLE_PATH" "-DSUNSHINE_ASSETS_DIR=$SUNSHINE_ASSETS_DIR" "-DSUNSHINE_ENABLE_WAYLAND=$SUNSHINE_ENABLE_WAYLAND" "-DSUNSHINE_ENABLE_X11=$SUNSHINE_ENABLE_X11" "-DSUNSHINE_ENABLE_DRM=$SUNSHINE_ENABLE_DRM" "-DSUNSHINE_ENABLE_CUDA=$SUNSHINE_ENABLE_CUDA" "$SUNSHINE_ROOT" + +make -j ${nproc} + +./gen-deb diff --git a/scripts/build-sunshine.sh b/scripts/build-sunshine.sh new file mode 100755 index 000000000..d6d6359e3 --- /dev/null +++ b/scripts/build-sunshine.sh @@ -0,0 +1,113 @@ +#/bin/bash -e + +function usage { + echo "Usage: $0" + echo " -d: Generate a debug build" + echo " -p: Generate a debian package" + echo " -u: The input device is not a TTY" + echo " -n name: Docker container name --> default [sunshine]" + echo " -s path/to/sources/sunshine: Use local sources instead of a git repository" + echo " -c path/to/cmake/binary/dir: Store cmake output on host OS" +} + +# Attempt to turn relative paths into absolute paths +function absolute_path() { + RELATIVE_PATH=$1 + if which realpath >/dev/null 2>/dev/null + then + RELATIVE_PATH=$(realpath $RELATIVE_PATH) + else + echo "Warning: realpath is not installed on your system, ensure [$1] is absolute" + fi + + RETURN=$RELATIVE_PATH +} + +CMAKE_BUILD_TYPE="-e CMAKE_BUILD_TYPE=Release" +SUNSHINE_PACKAGE_BUILD=OFF +SUNSHINE_GIT_URL=https://github.com/loki-47-6F-64/sunshine.git +CONTAINER_NAME=sunshine + +# Docker will fail if ctrl+c is passed through and the input is not a tty +DOCKER_INTERACTIVE=-ti + +while getopts ":dpuhc:s:n:" arg; do + case ${arg} in + u) + echo "Input device is not a TTY" + USERNAME="$USER" + unset DOCKER_INTERACTIVE + ;; + d) + echo "Creating debug build" + CMAKE_BUILD_TYPE="-e CMAKE_BUILD_TYPE=Debug" + ;; + p) + echo "Creating package build" + SUNSHINE_PACKAGE_BUILD=ON + SUNSHINE_ASSETS_DIR="-e SUNSHINE_ASSETS_DIR=/etc/sunshine" + SUNSHINE_EXECUTABLE_PATH="-e SUNSHINE_EXECUTABLE_PATH=/usr/bin/sunshine" + ;; + s) + absolute_path "$OPTARG" + OPTARG="$RETURN" + echo "Using sources from $OPTARG" + SUNSHINE_ROOT="-v $OPTARG:/root/sunshine" + ;; + c) + [ "$USERNAME" == "" ] && USERNAME=$(logname) + + absolute_path "$OPTARG" + OPTARG="$RETURN" + + echo "Using $OPTARG as cmake binary dir" + if [[ ! -d $OPTARG ]] + then + echo "cmake binary dir doesn't exist, a new one will be created." + mkdir -p "$OPTARG" + [ "$USERNAME" == "$USER"] || chown $USERNAME:$USERNAME "$OPTARG" + fi + + CMAKE_ROOT="-v $OPTARG:/root/sunshine-build" + ;; + n) + echo "Container name: $OPTARG" + CONTAINER_NAME=$OPTARG + ;; + h) + usage + exit 0 + ;; + esac +done + +[ "$USERNAME" == "" ] && USERNAME=$(logname) + +BUILD_DIR="$PWD/$CONTAINER_NAME-build" +SUNSHINE_ASSETS_DIR="-e SUNSHINE_ASSETS_DIR=$BUILD_DIR/assets" +SUNSHINE_EXECUTABLE_PATH="-e SUNSHINE_EXECUTABLE_PATH=$BUILD_DIR/sunshine" + +docker run $DOCKER_INTERACTIVE --privileged $SUNSHINE_ROOT $CMAKE_ROOT $SUNSHINE_ASSETS_DIR $SUNSHINE_EXECUTABLE_PATH $CMAKE_BUILD_TYPE --name $CONTAINER_NAME $CONTAINER_NAME + +exit_code=$? + +if [ $exit_code -eq 0 ] +then + mkdir -p $BUILD_DIR + case $SUNSHINE_PACKAGE_BUILD in + ON) + echo "Downloading package to: $BUILD_DIR/$CONTAINER_NAME.deb" + docker cp $CONTAINER_NAME:/root/sunshine-build/package-deb/sunshine.deb "$BUILD_DIR/$CONTAINER_NAME.deb" + ;; + *) + echo "Downloading binary and assets to: $BUILD_DIR" + docker cp $CONTAINER_NAME:/root/sunshine/assets "$BUILD_DIR" + docker cp $CONTAINER_NAME:/root/sunshine-build/sunshine "$BUILD_DIR" + ;; + esac + echo "chown --recursive $USERNAME:$USERNAME $BUILD_DIR" + chown --recursive $USERNAME:$USERNAME "$BUILD_DIR" +fi + +echo "Removing docker container $CONTAINER_NAME" +docker rm $CONTAINER_NAME