Skip to content

Commit

Permalink
build(macos)!: add homebrew formula and drop dmg (#2222)
Browse files Browse the repository at this point in the history
  • Loading branch information
ReenigneArcher authored Mar 9, 2024
1 parent ce3b625 commit 33e99e1
Show file tree
Hide file tree
Showing 9 changed files with 162 additions and 114 deletions.
155 changes: 57 additions & 98 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -505,137 +505,96 @@ 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:
include:
# 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: |
# install dependencies using homebrew
brew install cmake
- name: Configure formula
run: |
if [[ ${{ matrix.arch }} == "arm64" ]]; then
brew_prefix="/opt/homebrew"
# variables for formula
branch=${GITHUB_HEAD_REF}
# 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
brew_prefix="/usr/local"
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}"
# install dependencies using homebrew
brew install cmake curl miniupnpc node openssl opus pkg-config
# 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
run: |
export BOOST_ROOT=${HOME}/boost-${BOOST_VERSION}
# 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}
# 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/[email protected]
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]
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
8 changes: 8 additions & 0 deletions cmake/prep/options.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions cmake/prep/special_package_configuration.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
13 changes: 12 additions & 1 deletion cmake/targets/common.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,19 @@ endif()

target_compile_options(sunshine PRIVATE $<$<COMPILE_LANGUAGE:CXX>:${SUNSHINE_COMPILE_OPTIONS}>;$<$<COMPILE_LANGUAGE:CUDA>:${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
13 changes: 5 additions & 8 deletions docs/source/about/setup.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://docs.brew.sh/Installation>`__
#. Update the Homebrew sources and install Sunshine.

#. Download the ``sunshine-<macos_version>-<cpu_architecture>.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

Expand Down
62 changes: 62 additions & 0 deletions packaging/macos/sunshine.rb
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions src_assets/macos/misc/uninstall_pkg.sh
Original file line number Diff line number Diff line change
@@ -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
Expand Down
17 changes: 11 additions & 6 deletions vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
Expand Down

0 comments on commit 33e99e1

Please sign in to comment.