From 33e99e1feb02299ac907c12fedf9d8d36cae775c Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Sat, 9 Mar 2024 10:47:55 -0500 Subject: [PATCH] build(macos)!: add homebrew formula and drop dmg (#2222) --- .github/workflows/CI.yml | 151 +++++++----------- CMakeLists.txt | 2 +- cmake/prep/options.cmake | 8 + .../prep/special_package_configuration.cmake | 3 + cmake/targets/common.cmake | 13 +- docs/source/about/setup.rst | 13 +- packaging/macos/sunshine.rb | 62 +++++++ src_assets/macos/misc/uninstall_pkg.sh | 3 + vite.config.js | 17 +- 9 files changed, 160 insertions(+), 112 deletions(-) create mode 100644 packaging/macos/sunshine.rb diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 6b1eb296..f2529e73 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -505,10 +505,8 @@ jobs: discussionCategory: announcements prerelease: ${{ needs.setup_release.outputs.pre_release }} - build_mac: + build_mac_brew: needs: [check_changelog, setup_release] - env: - BOOST_VERSION: 1.83.0 strategy: fail-fast: false # false to test all, true to fail entire job if any fail matrix: @@ -516,126 +514,87 @@ jobs: # https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories # while GitHub has larger macOS runners, they are not available for our repos :( - os_version: "12" - arch: "x86_64" + release: true - os_version: "13" - arch: "x86_64" - os_version: "14" - arch: "arm64" - name: macOS-${{ matrix.os_version }} ${{ matrix.arch }} + name: Homebrew (macOS-${{ matrix.os_version }}) runs-on: macos-${{ matrix.os_version }} steps: - name: Checkout uses: actions/checkout@v4 - with: - submodules: recursive - - name: Setup Dependencies MacOS + - name: Setup Dependencies Homebrew run: | - if [[ ${{ matrix.arch }} == "arm64" ]]; then - brew_prefix="/opt/homebrew" - else - brew_prefix="/usr/local" - fi - # install dependencies using homebrew - brew install cmake curl miniupnpc node openssl opus pkg-config + brew install cmake - # fix openssl header not found - openssl_path=$(find ${brew_prefix}/Cellar -type d -name "openssl" -path "*/openssl@3/*/include" | head -n 1) - echo "OpenSSL path: $openssl_path" - ln -sf $openssl_path ${brew_prefix}/include/openssl - ls -l ${brew_prefix}/include/openssl - - # fix opus header not found - opus_path=$(find ${brew_prefix}/Cellar -type d -name "opus" -path "*/opus/*/include" | head -n 1) - echo "Opus path: $opus_path" - ln -sf $opus_path ${brew_prefix}/include/opus - ls -l ${brew_prefix}/include/opus - - # fix miniupnpc header not found - upnp_path=$(find ${brew_prefix}/Cellar -type d -name "miniupnpc" -path "*/miniupnpc/*/include" | head -n 1) - echo "Miniupnpc path: $upnp_path" - ln -sf $upnp_path ${brew_prefix}/include/miniupnpc - ls -l ${brew_prefix}/include/miniupnpc - - - name: Install Boost - # installing boost from homebrew takes 30 minutes in a GitHub runner + - name: Configure formula run: | - export BOOST_ROOT=${HOME}/boost-${BOOST_VERSION} + # variables for formula + branch=${GITHUB_HEAD_REF} - # install boost - wget \ - https://github.com/boostorg/boost/releases/download/boost-${BOOST_VERSION}/boost-${BOOST_VERSION}.tar.gz \ - --progress=bar:force:noscroll -q --show-progress - tar xf boost-${BOOST_VERSION}.tar.gz - cd boost-${BOOST_VERSION} + # check the branch variable + if [ -z "$branch" ] + then + echo "This is a PUSH event" + clone_url=${{ github.event.repository.clone_url }} + branch="${{ github.ref_name }}" + else + echo "This is a PR event" + clone_url=${{ github.event.pull_request.head.repo.clone_url }} + branch="${{ github.event.pull_request.head.ref }}" + fi + echo "Branch: ${branch}" + echo "Clone URL: ${clone_url}" - # libdir should be set by --prefix but isn't - ./bootstrap.sh \ - --prefix=${BOOST_ROOT} \ - --libdir=${BOOST_ROOT}/lib \ - --with-libraries=locale,log,program_options,system,thread - ./b2 headers - ./b2 install \ - --prefix=${BOOST_ROOT} \ - --libdir=${BOOST_ROOT}/lib \ - -j$(sysctl -n hw.ncpu) \ - link=shared,static \ - variant=release \ - cxxflags=-std=c++14 \ - cxxflags=-stdlib=libc++ \ - linkflags=-stdlib=libc++ - - # put boost in cmake prefix path - echo "BOOST_ROOT=${BOOST_ROOT}" >> ${GITHUB_ENV} - - - name: Build MacOS - env: - BRANCH: ${{ github.head_ref || github.ref_name }} - BUILD_VERSION: ${{ needs.check_changelog.outputs.next_version_bare }} - COMMIT: ${{ github.event.pull_request.head.sha || github.sha }} - run: | mkdir build cd build cmake \ - -DBUILD_WERROR=ON \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX=/usr \ - -DSUNSHINE_ASSETS_DIR=local/sunshine/assets \ - -DSUNSHINE_EXECUTABLE_PATH=/usr/bin/sunshine \ + -DGITHUB_BRANCH="${branch}" \ + -DGITHUB_CLONE_URL="${clone_url}" \ + -DSUNSHINE_CONFIGURE_HOMEBREW=ON \ + -DSUNSHINE_CONFIGURE_ONLY=ON \ .. - make -j $(sysctl -n hw.ncpu) + cd .. - - name: Package MacOS - run: | - mkdir -p artifacts - cd build + # copy formula to artifacts + mkdir -p homebrew + cp -f ./build/sunshine.rb ./homebrew/sunshine.rb - # package - cpack -G DragNDrop - mv ./cpack_artifacts/Sunshine.dmg \ - ../artifacts/sunshine-macos-${{ matrix.os_version }}-${{ matrix.arch }}.dmg + # testing + cat ./homebrew/sunshine.rb - name: Upload Artifacts + if: ${{ matrix.release }} uses: actions/upload-artifact@v4 with: - name: sunshine-macos-${{ matrix.os_version }}-${{ matrix.arch }} - path: artifacts/ + name: sunshine-homebrew + path: homebrew/ - - name: Create/Update GitHub Release - if: ${{ needs.setup_release.outputs.create_release == 'true' }} - uses: ncipollo/release-action@v1 + - name: Should Publish Homebrew Formula + id: homebrew_publish + run: | + PUBLISH=false + if [[ \ + "${{ matrix.release }}" == "true" && \ + "${{ github.repository_owner }}" == "LizardByte" && \ + "${{ needs.setup_release.outputs.create_release }}" == "true" && \ + "${{ github.ref }}" == "refs/heads/master" \ + ]]; then + PUBLISH=true + fi + + echo "publish=${PUBLISH}" >> $GITHUB_OUTPUT + + - name: Validate and Publish Homebrew Formula + uses: LizardByte/homebrew-release-action@v2024.309.150158 with: - name: ${{ needs.setup_release.outputs.release_name }} - tag: ${{ needs.setup_release.outputs.release_tag }} - commit: ${{ needs.setup_release.outputs.release_commit }} - artifacts: "*artifacts/*" + formula_file: ${{ github.workspace }}/homebrew/sunshine.rb + git_email: ${{ secrets.GH_BOT_EMAIL }} + git_username: ${{ secrets.GH_BOT_NAME }} + publish: ${{ steps.homebrew_publish.outputs.publish }} token: ${{ secrets.GH_BOT_TOKEN }} - allowUpdates: true - body: ${{ needs.setup_release.outputs.release_body }} - discussionCategory: announcements - prerelease: ${{ needs.setup_release.outputs.pre_release }} build_mac_port: needs: [check_changelog, setup_release] diff --git a/CMakeLists.txt b/CMakeLists.txt index d672c9b8..593d86b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.18) # todo - set version to 0.0.0 once confident in automated versioning project(Sunshine VERSION 0.22.0 - DESCRIPTION "Sunshine is a self-hosted game stream host for Moonlight." + DESCRIPTION "Self-hosted game stream host for Moonlight" HOMEPAGE_URL "https://app.lizardbyte.dev/Sunshine") set(PROJECT_LICENSE "GPL-3.0") diff --git a/cmake/prep/options.cmake b/cmake/prep/options.cmake index 9104320d..9a7fca8e 100644 --- a/cmake/prep/options.cmake +++ b/cmake/prep/options.cmake @@ -12,7 +12,15 @@ option(CUDA_INHERIT_COMPILE_OPTIONS "When building CUDA code, inherit compile options from the the main project. You may want to disable this if your IDE throws errors about unknown flags after running cmake." ON) +if(UNIX) + # technically, the homebrew build could be on linux as well... no idea if it would actually work + option(SUNSHINE_BUILD_HOMEBREW + "Enable a Homebrew build." OFF) +endif () + if(APPLE) + option(SUNSHINE_CONFIGURE_HOMEBREW + "Configure macOS Homebrew formula. Recommended to use with SUNSHINE_CONFIGURE_ONLY" OFF) option(SUNSHINE_CONFIGURE_PORTFILE "Configure macOS Portfile. Recommended to use with SUNSHINE_CONFIGURE_ONLY" OFF) option(SUNSHINE_PACKAGE_MACOS diff --git a/cmake/prep/special_package_configuration.cmake b/cmake/prep/special_package_configuration.cmake index a5a780f5..695b6e44 100644 --- a/cmake/prep/special_package_configuration.cmake +++ b/cmake/prep/special_package_configuration.cmake @@ -2,6 +2,9 @@ if (APPLE) if(${SUNSHINE_CONFIGURE_PORTFILE}) configure_file(packaging/macos/Portfile Portfile @ONLY) endif() + if(${SUNSHINE_CONFIGURE_HOMEBREW}) + configure_file(packaging/macos/sunshine.rb sunshine.rb @ONLY) + endif() elseif (UNIX) include(GNUInstallDirs) # this needs to be included prior to configuring the desktop files diff --git a/cmake/targets/common.cmake b/cmake/targets/common.cmake index 3dd629e0..9f2ce082 100644 --- a/cmake/targets/common.cmake +++ b/cmake/targets/common.cmake @@ -37,8 +37,19 @@ endif() target_compile_options(sunshine PRIVATE $<$:${SUNSHINE_COMPILE_OPTIONS}>;$<$:${SUNSHINE_COMPILE_OPTIONS_CUDA};-std=c++17>) # cmake-lint: disable=C0301 +# Homebrew build fails the vite build if we set these environment variables +if(${SUNSHINE_BUILD_HOMEBREW}) + set(NPM_SOURCE_ASSETS_DIR "") + set(NPM_ASSETS_DIR "") + set(NPM_BUILD_HOMEBREW "true") +else() + set(NPM_SOURCE_ASSETS_DIR ${SUNSHINE_SOURCE_ASSETS_DIR}) + set(NPM_ASSETS_DIR ${CMAKE_BINARY_DIR}) + set(NPM_BUILD_HOMEBREW "") +endif() + #WebUI build add_custom_target(web-ui ALL WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" COMMENT "Installing NPM Dependencies and Building the Web UI" - COMMAND bash -c \"npm install && SUNSHINE_SOURCE_ASSETS_DIR=${SUNSHINE_SOURCE_ASSETS_DIR} SUNSHINE_ASSETS_DIR=${CMAKE_BINARY_DIR} npm run build\") # cmake-lint: disable=C0301 + COMMAND bash -c \"npm install && SUNSHINE_BUILD_HOMEBREW=${NPM_BUILD_HOMEBREW} SUNSHINE_SOURCE_ASSETS_DIR=${NPM_SOURCE_ASSETS_DIR} SUNSHINE_ASSETS_DIR=${NPM_ASSETS_DIR} npm run build\") # cmake-lint: disable=C0301 diff --git a/docs/source/about/setup.rst b/docs/source/about/setup.rst index 2457ccc5..53da1398 100644 --- a/docs/source/about/setup.rst +++ b/docs/source/about/setup.rst @@ -283,18 +283,15 @@ Install .. important:: Sunshine on macOS is experimental. Gamepads do not work. - .. tab:: dmg + .. tab:: Homebrew - .. warning:: The `dmg` does not include runtime dependencies. This package is not recommended for most users. - No support will be provided! + #. Install `Homebrew `__ + #. Update the Homebrew sources and install Sunshine. - #. Download the ``sunshine--.dmg`` file and install it. - - Uninstall: .. code-block:: bash - cd /etc/sunshine/assets - uninstall_pkg.sh + brew tap LizardByte/homebrew + brew install sunshine .. tab:: Portfile diff --git a/packaging/macos/sunshine.rb b/packaging/macos/sunshine.rb new file mode 100644 index 00000000..e312c99d --- /dev/null +++ b/packaging/macos/sunshine.rb @@ -0,0 +1,62 @@ +require "language/node" + +class @PROJECT_NAME@ < Formula + desc "@PROJECT_DESCRIPTION@" + homepage "@PROJECT_HOMEPAGE_URL@" + url "@GITHUB_CLONE_URL@", + tag: "@GITHUB_BRANCH@" + version "@PROJECT_VERSION@" + license all_of: ["GPL-3.0-only"] + head "@GITHUB_CLONE_URL@", branch: "nightly" + + depends_on "boost" => :build + depends_on "cmake" => :build + depends_on "pkg-config" => :build + depends_on "curl" + depends_on "miniupnpc" + depends_on "node" + depends_on "openssl" + depends_on "opus" + + def install + args = %W[ + -DBUIld_WERROR=ON + -DCMAKE_INSTALL_PREFIX=#{prefix} + -DOPENSSL_ROOT_DIR=#{Formula["openssl"].opt_prefix} + -DSUNSHINE_ASSETS_DIR=sunshine/assets + -DSUNSHINE_BUILD_HOMEBREW=ON + ] + system "cmake", "-S", ".", "-B", "build", *std_cmake_args, *args + + cd "build" do + system "make", "-j" + system "make", "install" + end + end + + service do + run [opt_bin/"sunshine", "~/.config/sunshine/sunshine.conf"] + end + + def caveats + <<~EOS + Thanks for installing @PROJECT_NAME@! + + To get started, review the documentation at: + https://docs.lizardbyte.dev/projects/sunshine/en/latest/ + + Sunshine can only access microphones on macOS due to system limitations. + To stream system audio use "Soundflower" or "BlackHole". + + Gamepads are not currently supported on macOS. + EOS + end + + test do + # test that the binary runs at all + output = shell_output("#{bin}/sunshine --version").strip + puts output + + # TODO: add unit tests + end +end diff --git a/src_assets/macos/misc/uninstall_pkg.sh b/src_assets/macos/misc/uninstall_pkg.sh index 869f33d2..89e7bbfb 100644 --- a/src_assets/macos/misc/uninstall_pkg.sh +++ b/src_assets/macos/misc/uninstall_pkg.sh @@ -1,4 +1,7 @@ #!/bin/bash -e + +# note: this file was used to remove files when using the pkg/dmg, it is no longer used, but left for reference + set -e package_name=org.macports.Sunshine diff --git a/vite.config.js b/vite.config.js index a41470e4..8732f1a0 100644 --- a/vite.config.js +++ b/vite.config.js @@ -16,13 +16,18 @@ import process from 'process' let assetsSrcPath = 'src_assets/common/assets/web'; let assetsDstPath = 'build/assets/web'; -if (process.env.SUNSHINE_SOURCE_ASSETS_DIR) { - console.log("Using srcdir from Cmake: " + resolve(process.env.SUNSHINE_SOURCE_ASSETS_DIR,"common/assets/web")); - assetsSrcPath = resolve(process.env.SUNSHINE_SOURCE_ASSETS_DIR,"common/assets/web") +if (process.env.SUNSHINE_BUILD_HOMEBREW) { + console.log("Building for homebrew, using default paths") } -if (process.env.SUNSHINE_ASSETS_DIR) { - console.log("Using destdir from Cmake: " + resolve(process.env.SUNSHINE_ASSETS_DIR,"assets/web")); - assetsDstPath = resolve(process.env.SUNSHINE_ASSETS_DIR,"assets/web") +else { + if (process.env.SUNSHINE_SOURCE_ASSETS_DIR) { + console.log("Using srcdir from Cmake: " + resolve(process.env.SUNSHINE_SOURCE_ASSETS_DIR,"common/assets/web")); + assetsSrcPath = resolve(process.env.SUNSHINE_SOURCE_ASSETS_DIR,"common/assets/web") + } + if (process.env.SUNSHINE_ASSETS_DIR) { + console.log("Using destdir from Cmake: " + resolve(process.env.SUNSHINE_ASSETS_DIR,"assets/web")); + assetsDstPath = resolve(process.env.SUNSHINE_ASSETS_DIR,"assets/web") + } } let header = fs.readFileSync(resolve(assetsSrcPath, "template_header.html"))