mirror of
https://github.com/LizardByte/Sunshine.git
synced 2026-08-07 10:20:46 +00:00
feat(macos): build a signed .app bundle in a .dmg (#4759)
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
---
|
||||
name: CI-macOS
|
||||
permissions: {}
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
publish_release:
|
||||
required: true
|
||||
type: string
|
||||
release_commit:
|
||||
required: true
|
||||
type: string
|
||||
release_version:
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
# email address
|
||||
APPLE_ID:
|
||||
required: false
|
||||
# 10-character Team ID
|
||||
APPLE_TEAM_ID:
|
||||
required: false
|
||||
# app-specific password in APPLE_ID's account that must be named "notarytool"
|
||||
# https://support.apple.com/en-us/102654
|
||||
APPLE_NOTARYTOOL_PASSWORD:
|
||||
required: false
|
||||
# Developer ID Application: Full Name (TEAMIDHERE)
|
||||
APPLE_CODESIGN_IDENTITY:
|
||||
required: false
|
||||
# pkcs12 export from Xcode in base64
|
||||
APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_BASE64:
|
||||
required: false
|
||||
# pkcs12 password added by Xcode export
|
||||
APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_P12_PASSWORD:
|
||||
required: false
|
||||
|
||||
env:
|
||||
BRANCH: ${{ github.head_ref || github.ref_name }}
|
||||
BUILD_VERSION: ${{ inputs.release_version }}
|
||||
COMMIT: ${{ inputs.release_commit }}
|
||||
|
||||
jobs:
|
||||
build_dmg:
|
||||
name: ${{ matrix.name }}
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: "macos-14"
|
||||
name: "macOS-arm64"
|
||||
- os: "macos-15-intel"
|
||||
name: "macOS-x86_64"
|
||||
steps:
|
||||
- name: Install Apple certificate
|
||||
uses: apple-actions/import-codesign-certs@b610f78488812c1e56b20e6df63ec42d833f2d14 # v6.0.0
|
||||
if: inputs.publish_release == 'true'
|
||||
with:
|
||||
p12-file-base64: ${{ secrets.APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_BASE64 }}
|
||||
p12-password: ${{ secrets.APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_P12_PASSWORD }}
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 5
|
||||
run: |
|
||||
brew install --force \
|
||||
cmake \
|
||||
doxygen \
|
||||
graphviz \
|
||||
node \
|
||||
pkgconf \
|
||||
icu4c@78 \
|
||||
miniupnpc \
|
||||
openssl@3 \
|
||||
opus
|
||||
|
||||
- name: Configure
|
||||
env:
|
||||
APPLE_CODESIGN_IDENTITY: ${{ secrets.APPLE_CODESIGN_IDENTITY }}
|
||||
run: |
|
||||
mkdir -p build
|
||||
cmake \
|
||||
-B build \
|
||||
-S . \
|
||||
-DBUILD_WERROR=ON \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DOPENSSL_ROOT_DIR="$(brew --prefix openssl@3 2>/dev/null)" \
|
||||
-DOpus_ROOT_DIR="$(brew --prefix opus 2>/dev/null)" \
|
||||
-DSUNSHINE_PUBLISHER_NAME="${GITHUB_REPOSITORY_OWNER}" \
|
||||
-DSUNSHINE_PUBLISHER_WEBSITE="https://app.lizardbyte.dev" \
|
||||
-DSUNSHINE_PUBLISHER_ISSUE_URL="https://app.lizardbyte.dev/support" \
|
||||
-DAPPLE_CODESIGN_IDENTITY="${APPLE_CODESIGN_IDENTITY}"
|
||||
|
||||
- name: Build
|
||||
run: cmake --build build -j "$(sysctl -n hw.ncpu)"
|
||||
|
||||
- name: Package DMG
|
||||
env:
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
APPLE_NOTARYTOOL_PASSWORD: ${{ secrets.APPLE_NOTARYTOOL_PASSWORD }}
|
||||
APPLE_CODESIGN_IDENTITY: ${{ secrets.APPLE_CODESIGN_IDENTITY }}
|
||||
SHOULD_SIGN: ${{ inputs.publish_release }}
|
||||
run: |
|
||||
# build DMG and sign everything (see cmake/packaging/macos.cmake)
|
||||
# cpack can rarely fail with "hdiutil: create failed - Resource busy"
|
||||
# so let's allow 1 retry
|
||||
if ! cpack -G DragNDrop --config build/CPackConfig.cmake; then
|
||||
echo "cpack failed, retrying once with verbose..."
|
||||
if ! cpack -G DragNDrop --config build/CPackConfig.cmake --verbose; then
|
||||
echo "cpack failed again. Aborting."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Notarize
|
||||
if [[ "${SHOULD_SIGN}" == "true" && -n "${APPLE_NOTARYTOOL_PASSWORD}" ]]; then
|
||||
# Notarizing allows the signed .app to run on any Mac with no prompts.
|
||||
# If you don't notarize, users must jump through the "Open Anyway" hoop as well as run
|
||||
# `xattr -cr /Applications/Sunshine.app` to remove quarantine.
|
||||
if [[ -n "${APPLE_NOTARYTOOL_PASSWORD}" ]]; then
|
||||
xcrun notarytool submit build/cpack_artifacts/Sunshine.dmg \
|
||||
--apple-id "${APPLE_ID}" \
|
||||
--team-id "${APPLE_TEAM_ID}" \
|
||||
--password "${APPLE_NOTARYTOOL_PASSWORD}" \
|
||||
--wait
|
||||
xcrun stapler staple -v build/cpack_artifacts/Sunshine.dmg
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir -p artifacts
|
||||
mv build/cpack_artifacts/Sunshine.dmg \
|
||||
artifacts/Sunshine-${{ matrix.name }}.dmg
|
||||
|
||||
- name: Test
|
||||
id: test
|
||||
working-directory: build/tests
|
||||
run: ./test_sunshine --gtest_color=yes --gtest_output=xml:test_results.xml
|
||||
|
||||
- name: Generate gcov report
|
||||
id: test_report
|
||||
# any except canceled or skipped
|
||||
if: >-
|
||||
always() &&
|
||||
(steps.test.outcome == 'success' || steps.test.outcome == 'failure')
|
||||
working-directory: build
|
||||
run: |
|
||||
python -m pip install "../scripts[test]"
|
||||
python -m gcovr . -r ../src \
|
||||
--exclude-noncode-lines \
|
||||
--exclude-throw-branches \
|
||||
--exclude-unreachable-branches \
|
||||
--xml-pretty \
|
||||
-j "$(sysctl -n hw.ncpu)" \
|
||||
-o coverage.xml
|
||||
|
||||
- name: Upload coverage artifact
|
||||
if: >-
|
||||
always() &&
|
||||
(steps.test_report.outcome == 'success')
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||
with:
|
||||
name: coverage-${{ matrix.name }}
|
||||
path: |
|
||||
build/coverage.xml
|
||||
build/tests/test_results.xml
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||
with:
|
||||
name: build-${{ matrix.name }}
|
||||
path: artifacts/
|
||||
if-no-files-found: error
|
||||
@@ -89,6 +89,26 @@ jobs:
|
||||
GH_TOKEN: ${{ secrets.GH_BOT_TOKEN }}
|
||||
GIT_EMAIL: ${{ secrets.GH_BOT_EMAIL }}
|
||||
|
||||
build-macos:
|
||||
name: macOS
|
||||
needs: release-setup
|
||||
permissions:
|
||||
contents: read
|
||||
uses: ./.github/workflows/ci-macos.yml
|
||||
with:
|
||||
publish_release: ${{ needs.release-setup.outputs.publish_release }}
|
||||
release_commit: ${{ needs.release-setup.outputs.release_commit }}
|
||||
release_version: ${{ needs.release-setup.outputs.release_version }}
|
||||
secrets:
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
APPLE_NOTARYTOOL_PASSWORD: ${{ secrets.APPLE_NOTARYTOOL_PASSWORD }}
|
||||
APPLE_CODESIGN_IDENTITY: ${{ secrets.APPLE_CODESIGN_IDENTITY }}
|
||||
APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_BASE64: >-
|
||||
${{ secrets.APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_BASE64 }}
|
||||
APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_P12_PASSWORD: >-
|
||||
${{ secrets.APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_P12_PASSWORD }}
|
||||
|
||||
build-linux:
|
||||
name: Linux
|
||||
needs: release-setup
|
||||
@@ -161,6 +181,7 @@ jobs:
|
||||
- build-linux
|
||||
- build-archlinux
|
||||
- build-linux-flatpak
|
||||
- build-macos
|
||||
- build-homebrew
|
||||
- build-windows
|
||||
permissions:
|
||||
@@ -182,6 +203,12 @@ jobs:
|
||||
- name: Archlinux
|
||||
coverage: true
|
||||
pr: true
|
||||
- name: macOS-arm64
|
||||
coverage: true
|
||||
pr: true
|
||||
- name: macOS-x86_64
|
||||
coverage: true
|
||||
pr: true
|
||||
- name: Homebrew-macos-14
|
||||
coverage: false
|
||||
pr: true
|
||||
|
||||
@@ -142,6 +142,8 @@ include_directories(
|
||||
"${CMAKE_SOURCE_DIR}/third-party/moonlight-common-c/enet/include"
|
||||
"${CMAKE_SOURCE_DIR}/third-party/nanors"
|
||||
"${CMAKE_SOURCE_DIR}/third-party/nanors/deps/obl"
|
||||
${OPENSSL_INCLUDE_DIR}
|
||||
${Opus_INCLUDE_DIR}
|
||||
${FFMPEG_INCLUDE_DIRS}
|
||||
${Boost_INCLUDE_DIRS} # has to be the last, or we get runtime error on macOS ffmpeg encoder
|
||||
)
|
||||
@@ -152,7 +154,7 @@ list(APPEND SUNSHINE_EXTERNAL_LIBRARIES
|
||||
enet
|
||||
libdisplaydevice::display_device
|
||||
nlohmann_json::nlohmann_json
|
||||
opus
|
||||
${Opus_LIBRARY}
|
||||
${FFMPEG_LIBRARIES}
|
||||
${Boost_LIBRARIES}
|
||||
${OPENSSL_LIBRARIES}
|
||||
|
||||
@@ -2,6 +2,14 @@
|
||||
|
||||
add_compile_definitions(SUNSHINE_PLATFORM="macos")
|
||||
|
||||
if (SUNSHINE_BUILD_HOMEBREW)
|
||||
set(SUNSHINE_ASSETS_DIR "${CMAKE_INSTALL_PREFIX}/${SUNSHINE_ASSETS_DIR}")
|
||||
else()
|
||||
# Bundle layout for macOS app builds
|
||||
set(SUNSHINE_ASSETS_DIR "${CMAKE_PROJECT_NAME}.app/Contents/Resources/assets")
|
||||
set(SUNSHINE_ASSETS_DIR_DEF "../Resources/assets")
|
||||
endif()
|
||||
|
||||
set(MACOS_LINK_DIRECTORIES
|
||||
/opt/homebrew/lib
|
||||
/opt/local/lib
|
||||
@@ -26,7 +34,9 @@ list(APPEND SUNSHINE_EXTERNAL_LIBRARIES
|
||||
${FOUNDATION_LIBRARY}
|
||||
${VIDEO_TOOLBOX_LIBRARY})
|
||||
|
||||
set(APPLE_PLIST_FILE "${SUNSHINE_SOURCE_ASSETS_DIR}/macos/assets/Info.plist")
|
||||
set(APPLE_PLIST_TEMPLATE "${SUNSHINE_SOURCE_ASSETS_DIR}/macos/build/Info.plist.in")
|
||||
set(APPLE_PLIST_FILE "${CMAKE_BINARY_DIR}/Info.plist")
|
||||
configure_file("${APPLE_PLIST_TEMPLATE}" "${APPLE_PLIST_FILE}" @ONLY)
|
||||
|
||||
set(PLATFORM_TARGET_FILES
|
||||
"${CMAKE_SOURCE_DIR}/src/platform/macos/av_audio.h"
|
||||
|
||||
@@ -5,6 +5,6 @@ list(APPEND SUNSHINE_EXTERNAL_LIBRARIES
|
||||
${CURL_LIBRARIES})
|
||||
|
||||
# add install prefix to assets path if not already there
|
||||
if(NOT SUNSHINE_ASSETS_DIR MATCHES "^${CMAKE_INSTALL_PREFIX}")
|
||||
if(NOT APPLE AND NOT SUNSHINE_ASSETS_DIR MATCHES "^${CMAKE_INSTALL_PREFIX}")
|
||||
set(SUNSHINE_ASSETS_DIR "${CMAKE_INSTALL_PREFIX}/${SUNSHINE_ASSETS_DIR}")
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
# Copyright 2019-2022, Collabora, Ltd.
|
||||
#
|
||||
# SPDX-License-Identifier: BSL-1.0
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# Original Author:
|
||||
# 2019-2022 Rylie Pavlik <rylie.pavlik@collabora.com> <rylie@ryliepavlik.com>
|
||||
|
||||
#[[.rst:
|
||||
FindOpus
|
||||
---------------
|
||||
|
||||
Find the opus codec library.
|
||||
|
||||
Targets
|
||||
^^^^^^^
|
||||
|
||||
If successful, the following imported target is created
|
||||
|
||||
* ``Opus::opus``
|
||||
|
||||
Cache variables
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
The following cache variable may also be set to assist/control the operation of this module:
|
||||
|
||||
``Opus_ROOT_DIR``
|
||||
The root to search for opus.
|
||||
|
||||
#]]
|
||||
|
||||
set(Opus_ROOT_DIR # cmake-lint: disable=C0103
|
||||
"${Opus_ROOT_DIR}"
|
||||
CACHE PATH "Root to search for opus")
|
||||
|
||||
# Todo: handle in-tree/fetch-content builds?
|
||||
|
||||
if(NOT OPUS_FOUND)
|
||||
# Look for a CMake config file
|
||||
find_package(Opus QUIET NO_MODULE)
|
||||
endif()
|
||||
|
||||
if(TARGET opus)
|
||||
# for fetch content/in tree
|
||||
set(Opus_LIBRARY opus) # cmake-lint: disable=C0103
|
||||
endif()
|
||||
|
||||
if(NOT ANDROID)
|
||||
find_package(PkgConfig QUIET)
|
||||
if(PKG_CONFIG_FOUND)
|
||||
set(_old_prefix_path "${CMAKE_PREFIX_PATH}")
|
||||
# So pkg-config uses Opus_ROOT_DIR too.
|
||||
if(Opus_ROOT_DIR)
|
||||
list(APPEND CMAKE_PREFIX_PATH ${Opus_ROOT_DIR})
|
||||
endif()
|
||||
pkg_check_modules(PC_opus QUIET opus)
|
||||
# Restore
|
||||
set(CMAKE_PREFIX_PATH "${_old_prefix_path}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_path(
|
||||
Opus_INCLUDE_DIR
|
||||
NAMES opus/opus.h
|
||||
PATHS ${Opus_ROOT_DIR}
|
||||
HINTS ${PC_opus_INCLUDE_DIRS} ${OPUS_INCLUDE_DIR} ${OPUS_INCLUDE_DIRS}
|
||||
PATH_SUFFIXES include)
|
||||
find_library(
|
||||
Opus_LIBRARY
|
||||
NAMES opus
|
||||
PATHS ${Opus_ROOT_DIR}
|
||||
HINTS ${PC_opus_LIBRARY_DIRS}
|
||||
PATH_SUFFIXES lib)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Opus REQUIRED_VARS Opus_LIBRARY
|
||||
Opus_INCLUDE_DIR)
|
||||
if(Opus_FOUND)
|
||||
if(NOT TARGET Opus::opus)
|
||||
if(TARGET ${Opus_LIBRARY})
|
||||
# we want an alias
|
||||
add_library(Opus::opus ALIAS ${Opus_LIBRARY})
|
||||
else()
|
||||
# we want an imported target
|
||||
add_library(Opus::opus UNKNOWN IMPORTED)
|
||||
|
||||
set_target_properties(
|
||||
Opus::opus
|
||||
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${Opus_INCLUDE_DIR}"
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
|
||||
IMPORTED_LOCATION ${Opus_LIBRARY})
|
||||
endif()
|
||||
endif()
|
||||
mark_as_advanced(Opus_INCLUDE_DIR Opus_LIBRARY)
|
||||
endif()
|
||||
mark_as_advanced(Opus_ROOT_DIR)
|
||||
|
||||
include(FeatureSummary)
|
||||
set_package_properties(
|
||||
Opus PROPERTIES
|
||||
URL "https://opus-codec.org/"
|
||||
DESCRIPTION
|
||||
"The reference library implementation for the audio codec of the same name."
|
||||
)
|
||||
@@ -1,6 +1,10 @@
|
||||
# load common dependencies
|
||||
# this file will also load platform specific dependencies
|
||||
|
||||
# Resolve OpenSSL before subprojects run their own find_package(OpenSSL) calls.
|
||||
# This ensures a user-provided OPENSSL_ROOT_DIR is honored consistently.
|
||||
find_package(OpenSSL REQUIRED)
|
||||
|
||||
# boost, this should be before Simple-Web-Server as it also depends on boost
|
||||
include(dependencies/Boost_Sunshine)
|
||||
|
||||
@@ -17,7 +21,6 @@ add_subdirectory("${CMAKE_SOURCE_DIR}/third-party/libdisplaydevice")
|
||||
|
||||
# common dependencies
|
||||
include("${CMAKE_MODULE_PATH}/dependencies/nlohmann_json.cmake")
|
||||
find_package(OpenSSL REQUIRED)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
find_package(Threads REQUIRED)
|
||||
pkg_check_modules(CURL REQUIRED libcurl)
|
||||
@@ -29,6 +32,9 @@ include_directories(SYSTEM ${MINIUPNP_INCLUDE_DIRS})
|
||||
# ffmpeg pre-compiled binaries
|
||||
include("${CMAKE_MODULE_PATH}/dependencies/ffmpeg.cmake")
|
||||
|
||||
# Opus
|
||||
include("${CMAKE_MODULE_PATH}/dependencies/FindOpus.cmake")
|
||||
|
||||
# platform specific dependencies
|
||||
if(WIN32)
|
||||
include("${CMAKE_MODULE_PATH}/dependencies/windows.cmake")
|
||||
|
||||
+105
-19
@@ -1,25 +1,111 @@
|
||||
# macos specific packaging
|
||||
|
||||
# todo - bundle doesn't produce a valid .app use cpack -G DragNDrop
|
||||
set(CPACK_BUNDLE_NAME "${CMAKE_PROJECT_NAME}")
|
||||
set(CPACK_BUNDLE_PLIST "${APPLE_PLIST_FILE}")
|
||||
set(CPACK_BUNDLE_ICON "${PROJECT_SOURCE_DIR}/sunshine.icns")
|
||||
# set(CPACK_BUNDLE_STARTUP_COMMAND "${INSTALL_RUNTIME_DIR}/sunshine")
|
||||
if (SUNSHINE_BUILD_HOMEBREW)
|
||||
install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/macos/assets/"
|
||||
DESTINATION "${SUNSHINE_ASSETS_DIR}")
|
||||
|
||||
if(SUNSHINE_PACKAGE_MACOS) # todo
|
||||
set(MAC_PREFIX "${CMAKE_PROJECT_NAME}.app/Contents")
|
||||
set(INSTALL_RUNTIME_DIR "${MAC_PREFIX}/MacOS")
|
||||
# copy assets to build directory, for running without install
|
||||
file(COPY "${SUNSHINE_SOURCE_ASSETS_DIR}/macos/assets/"
|
||||
DESTINATION "${CMAKE_BINARY_DIR}/assets")
|
||||
else()
|
||||
# .app build
|
||||
set(APPLE_CODESIGN_IDENTITY "" CACHE STRING "Codesign identity, e.g. 'Developer ID Application: Name (TEAMID)'")
|
||||
|
||||
# Build an .app
|
||||
set(CMAKE_MACOSX_BUNDLE YES)
|
||||
|
||||
set(MAC_BUNDLE_NAME "${CMAKE_PROJECT_NAME}.app")
|
||||
set(MAC_BUNDLE_CONTENTS "${MAC_BUNDLE_NAME}/Contents")
|
||||
set(MAC_BUNDLE_RESOURCES "${MAC_BUNDLE_CONTENTS}/Resources")
|
||||
|
||||
install(TARGETS sunshine
|
||||
BUNDLE DESTINATION . COMPONENT Runtime
|
||||
RUNTIME DESTINATION ${INSTALL_RUNTIME_DIR} COMPONENT Runtime)
|
||||
else()
|
||||
install(FILES "${SUNSHINE_SOURCE_ASSETS_DIR}/macos/misc/uninstall_pkg.sh"
|
||||
DESTINATION "${SUNSHINE_ASSETS_DIR}")
|
||||
endif()
|
||||
BUNDLE DESTINATION .
|
||||
COMPONENT Runtime)
|
||||
|
||||
install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/macos/assets/"
|
||||
DESTINATION "${SUNSHINE_ASSETS_DIR}")
|
||||
# copy assets to build directory, for running without install
|
||||
file(COPY "${SUNSHINE_SOURCE_ASSETS_DIR}/macos/assets/"
|
||||
DESTINATION "${CMAKE_BINARY_DIR}/assets")
|
||||
install(FILES "${APPLE_PLIST_FILE}"
|
||||
DESTINATION "${MAC_BUNDLE_CONTENTS}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
install(FILES "${PROJECT_SOURCE_DIR}/src_assets/macos/build/sunshine.icns"
|
||||
DESTINATION "${MAC_BUNDLE_RESOURCES}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
# macOS-specific assets (apps.json, etc.)
|
||||
install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/macos/assets/"
|
||||
DESTINATION "${MAC_BUNDLE_RESOURCES}/assets"
|
||||
COMPONENT Runtime
|
||||
PATTERN ".DS_Store" EXCLUDE
|
||||
PATTERN "._*" EXCLUDE)
|
||||
|
||||
# Pull in non-system dylibs for a self-contained .app
|
||||
install(CODE "
|
||||
set(_app \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_PROJECT_NAME}.app\")
|
||||
|
||||
message(STATUS \"Running fixup_bundle for: \${_app}\")
|
||||
include(BundleUtilities)
|
||||
set(BU_CHMOD_BUNDLE_ITEMS TRUE)
|
||||
fixup_bundle(\"\${_app}\" \"\" \"\")
|
||||
|
||||
# Remove Finder/resource-fork metadata that breaks codesign.
|
||||
execute_process(COMMAND /usr/bin/xattr -rc \"\${_app}\")
|
||||
|
||||
message(STATUS \"removing any existing signatures\")
|
||||
execute_process(COMMAND /usr/bin/codesign
|
||||
--remove-signature --force --deep
|
||||
\"\${_app}\"
|
||||
RESULT_VARIABLE rc
|
||||
)
|
||||
if(NOT rc EQUAL 0)
|
||||
message(FATAL_ERROR \"codesign failed to remove existing signatures\")
|
||||
endif()
|
||||
|
||||
# SHOULD_SIGN is set only when publish_release is true or when manually building
|
||||
if(\$ENV{SHOULD_SIGN} STREQUAL \"true\")
|
||||
# Sign anything inside Contents/Frameworks
|
||||
set(_fw_dir \"\${_app}/Contents/Frameworks\")
|
||||
if(EXISTS \"\${_fw_dir}\")
|
||||
file(GLOB_RECURSE _sign_items
|
||||
\"\${_fw_dir}/*.framework\"
|
||||
\"\${_fw_dir}/*.dylib\"
|
||||
)
|
||||
|
||||
foreach(item IN LISTS _sign_items)
|
||||
execute_process(COMMAND /usr/bin/codesign --verbose=2
|
||||
--sign \"${APPLE_CODESIGN_IDENTITY}\" \"\${item}\"
|
||||
--force --timestamp --options=runtime
|
||||
RESULT_VARIABLE rc2
|
||||
)
|
||||
if(NOT rc2 EQUAL 0)
|
||||
message(FATAL_ERROR \"codesign failed while signing library: \${item}\")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# Sign the app last
|
||||
execute_process(COMMAND /usr/bin/codesign --verbose=2
|
||||
--sign \"${APPLE_CODESIGN_IDENTITY}\" \"\${_app}\"
|
||||
--force --timestamp --options=runtime
|
||||
RESULT_VARIABLE rc3
|
||||
)
|
||||
if(NOT rc3 EQUAL 0)
|
||||
message(FATAL_ERROR \"codesign failed while signing .app\")
|
||||
endif()
|
||||
|
||||
# Verify
|
||||
execute_process(COMMAND /usr/bin/codesign --verify --deep --strict --verbose=2 \"\${_app}\"
|
||||
RESULT_VARIABLE rc4
|
||||
)
|
||||
if(NOT rc4 EQUAL 0)
|
||||
message(FATAL_ERROR \"codesign --verify failed\")
|
||||
endif()
|
||||
endif()
|
||||
" COMPONENT Runtime)
|
||||
|
||||
# DragNDrop
|
||||
set(CPACK_BUNDLE_NAME "${CMAKE_PROJECT_NAME}")
|
||||
set(CPACK_BUNDLE_PLIST "${APPLE_PLIST_FILE}")
|
||||
set(CPACK_BUNDLE_ICON "${PROJECT_SOURCE_DIR}/src_assets/macos/build/sunshine.icns")
|
||||
set(CPACK_PACKAGING_INSTALL_PREFIX "/")
|
||||
set(CPACK_DMG_BACKGROUND_IMAGE "${PROJECT_SOURCE_DIR}/src_assets/macos/build/sunshine-background-72dpi.jpg")
|
||||
set(CPACK_DMG_DS_STORE_SETUP_SCRIPT "${PROJECT_SOURCE_DIR}/src_assets/macos/build/dmg-finder-layout.applescript")
|
||||
endif()
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# unix specific packaging
|
||||
# put anything here that applies to both linux and macos
|
||||
|
||||
# return here if building a macos package
|
||||
if(SUNSHINE_PACKAGE_MACOS)
|
||||
# return here if building a macos .app
|
||||
if(APPLE AND NOT SUNSHINE_BUILD_HOMEBREW)
|
||||
return()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
if (WIN32)
|
||||
elseif (APPLE)
|
||||
if (NOT SUNSHINE_BUILD_HOMEBREW)
|
||||
set(CMAKE_BUILD_WITH_INSTALL_RPATH ON)
|
||||
set(CMAKE_INSTALL_RPATH "")
|
||||
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
|
||||
endif()
|
||||
elseif (UNIX)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
|
||||
@@ -41,8 +41,6 @@ endif()
|
||||
if(APPLE)
|
||||
option(SUNSHINE_CONFIGURE_PORTFILE
|
||||
"Configure macOS Portfile. Recommended to use with SUNSHINE_CONFIGURE_ONLY" OFF)
|
||||
option(SUNSHINE_PACKAGE_MACOS
|
||||
"Should only be used when creating a macOS package/dmg." OFF)
|
||||
elseif(UNIX) # Linux
|
||||
option(SUNSHINE_BUILD_APPIMAGE
|
||||
"Enable an AppImage build." OFF)
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
# common target definitions
|
||||
# this file will also load platform specific macros
|
||||
|
||||
add_executable(sunshine ${SUNSHINE_TARGET_FILES})
|
||||
if(APPLE AND NOT SUNSHINE_BUILD_HOMEBREW)
|
||||
add_executable(sunshine MACOSX_BUNDLE ${SUNSHINE_TARGET_FILES})
|
||||
else()
|
||||
add_executable(sunshine ${SUNSHINE_TARGET_FILES})
|
||||
endif()
|
||||
foreach(dep ${SUNSHINE_TARGET_DEPENDENCIES})
|
||||
add_dependencies(sunshine ${dep}) # compile these before sunshine
|
||||
endforeach()
|
||||
@@ -27,9 +31,15 @@ endif()
|
||||
|
||||
target_link_libraries(sunshine ${SUNSHINE_EXTERNAL_LIBRARIES} ${EXTRA_LIBS})
|
||||
target_compile_definitions(sunshine PUBLIC ${SUNSHINE_DEFINITIONS})
|
||||
set_target_properties(sunshine PROPERTIES CXX_STANDARD 23
|
||||
if(APPLE AND NOT SUNSHINE_BUILD_HOMEBREW)
|
||||
# codesign on Mac won't sign an .app that uses a symlink
|
||||
set_target_properties(sunshine PROPERTIES CXX_STANDARD 23)
|
||||
else()
|
||||
# symlink sunshine -> sunshine-PROJECT_VERSION
|
||||
set_target_properties(sunshine PROPERTIES CXX_STANDARD 23
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR})
|
||||
endif()
|
||||
|
||||
# CLion complains about unknown flags after running cmake, and cannot add symbols to the index for cuda files
|
||||
if(CUDA_INHERIT_COMPILE_OPTIONS)
|
||||
|
||||
@@ -1,4 +1,26 @@
|
||||
# macos specific target definitions
|
||||
target_link_options(sunshine PRIVATE LINKER:-sectcreate,__TEXT,__info_plist,${APPLE_PLIST_FILE})
|
||||
|
||||
if (SUNSHINE_BUILD_HOMEBREW)
|
||||
target_link_options(sunshine PRIVATE LINKER:-sectcreate,__TEXT,__info_plist,${APPLE_PLIST_FILE})
|
||||
else()
|
||||
# .app build
|
||||
set_target_properties(sunshine PROPERTIES
|
||||
OUTPUT_NAME "${CMAKE_PROJECT_NAME}"
|
||||
MACOSX_BUNDLE_BUNDLE_NAME "${CMAKE_PROJECT_NAME}"
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER "${PROJECT_FQDN}"
|
||||
MACOSX_BUNDLE_INFO_PLIST "${APPLE_PLIST_FILE}"
|
||||
MACOSX_BUNDLE_ICON_FILE "sunshine.icns"
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}"
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_VERSION}")
|
||||
|
||||
# Populate bundle resources in the build tree for local runs.
|
||||
set(_bundle_resources_dir "$<TARGET_FILE_DIR:sunshine>/../Resources")
|
||||
add_custom_command(TARGET sunshine POST_BUILD
|
||||
COMMENT "Copying bundle resources to build tree"
|
||||
COMMAND "${CMAKE_COMMAND}" -E make_directory "${_bundle_resources_dir}"
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_BINARY_DIR}/assets" "${_bundle_resources_dir}/assets"
|
||||
VERBATIM)
|
||||
endif()
|
||||
|
||||
# Tell linker to dynamically load these symbols at runtime, in case they're unavailable:
|
||||
target_link_options(sunshine PRIVATE -Wl,-U,_CGPreflightScreenCaptureAccess -Wl,-U,_CGRequestScreenCaptureAccess)
|
||||
|
||||
+68
-27
@@ -1,4 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
# Note: This script is not used by CI, and is only for manually building/signing the .app.
|
||||
# Changes made to this script should also be made in ci-macos.yml.
|
||||
set -euo pipefail
|
||||
|
||||
# Default value for arguments
|
||||
@@ -7,16 +9,18 @@ publisher_name="LizardByte"
|
||||
publisher_website="https://app.lizardbyte.dev"
|
||||
publisher_issue_url="https://app.lizardbyte.dev/support"
|
||||
step="all"
|
||||
build_docs="ON"
|
||||
build_docs="OFF"
|
||||
build_tests="ON"
|
||||
build_type="Release"
|
||||
build_system="Unix Makefiles"
|
||||
sign_app="true"
|
||||
|
||||
# environment variables
|
||||
BUILD_VER=""
|
||||
# BUILD_VERSION should be empty or cmake will assume a CI build
|
||||
BUILD_VERSION=""
|
||||
BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||||
COMMIT=$(git rev-parse --short HEAD)
|
||||
|
||||
export BUILD_VER
|
||||
export BUILD_VERSION
|
||||
export BRANCH
|
||||
export COMMIT
|
||||
|
||||
@@ -38,9 +42,14 @@ function _usage() {
|
||||
local exit_code=$1
|
||||
|
||||
cat <<EOF
|
||||
This script installs the dependencies and builds the project.
|
||||
The script is intended to be run on an Apple Silicon Mac,
|
||||
but may work on Intel as well.
|
||||
This script builds a macOS .app bundle packaged inside a .dmg.
|
||||
|
||||
If the environment variable APPLE_CODESIGN_IDENTITY is set, the app will be signed.
|
||||
This must be a "Developer ID" identity.
|
||||
|
||||
For others to be able to open the .dmg, it must be notarized. Create a keychain profile named
|
||||
"notarytool-password" based on the instructions at
|
||||
https://developer.apple.com/documentation/security/customizing-the-notarization-workflow?language=objc
|
||||
|
||||
Usage:
|
||||
$0 [options]
|
||||
@@ -52,14 +61,17 @@ Options:
|
||||
--publisher-website The URL of the publisher's website.
|
||||
--publisher-issue-url The URL of the publisher's support site or issue tracker.
|
||||
If you provide a modified version of Sunshine, we kindly request that you use your own url.
|
||||
--step Which step(s) to run: deps, cmake, build, or all (default: all)
|
||||
--step=STEP Which step(s) to run: deps, cmake, build, dmg, or all (default: all)
|
||||
--debug Build in debug mode.
|
||||
--skip-docs Don't build docs.
|
||||
--build-docs Build docs.
|
||||
--skip-tests Don't build the test suite.
|
||||
--skip-codesign Don't sign/notarize the bundle.
|
||||
|
||||
Steps:
|
||||
deps Install dependencies only
|
||||
cmake Run cmake configure only
|
||||
build Build the project only
|
||||
dmg Create a DMG package
|
||||
all Run all steps (default)
|
||||
EOF
|
||||
|
||||
@@ -79,19 +91,25 @@ function run_step_cmake() {
|
||||
# prepare CMAKE args
|
||||
cmake_args=(
|
||||
"-B=build"
|
||||
"-G=${build_system}"
|
||||
"-S=."
|
||||
"-DCMAKE_BUILD_TYPE=${build_type}"
|
||||
"-DBUILD_WERROR=ON"
|
||||
"-DHOMEBREW_ALLOW_FETCHCONTENT=ON"
|
||||
"-DOPENSSL_ROOT_DIR=$(brew --prefix openssl@3 2>/dev/null)"
|
||||
"-DSUNSHINE_ASSETS_DIR=sunshine/assets"
|
||||
"-DSUNSHINE_BUILD_HOMEBREW=ON"
|
||||
"-DSUNSHINE_ENABLE_TRAY=ON"
|
||||
"-DBUILD_DOCS=${build_docs}"
|
||||
"-DBOOST_USE_STATIC=OFF"
|
||||
"-DBUILD_TESTS=${build_tests}"
|
||||
"-DBUILD_WERROR=ON"
|
||||
"-DCMAKE_BUILD_TYPE=${build_type}"
|
||||
"-DOPENSSL_ROOT_DIR=$(brew --prefix openssl@3 2>/dev/null)"
|
||||
"-DOpus_ROOT_DIR=$(brew --prefix opus 2>/dev/null)"
|
||||
"-DSUNSHINE_ENABLE_TRAY=ON"
|
||||
)
|
||||
|
||||
if [[ -n "${sign_app}" ]]; then
|
||||
if [[ -n "${APPLE_CODESIGN_IDENTITY:-}" ]]; then
|
||||
cmake_args+=("-DAPPLE_CODESIGN_IDENTITY='${APPLE_CODESIGN_IDENTITY}'")
|
||||
else
|
||||
echo "Please set the APPLE_CODESIGN_IDENTITY environment variable or use --skip-codesign"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Publisher metadata
|
||||
if [[ -n "$publisher_name" ]]; then
|
||||
cmake_args+=("-DSUNSHINE_PUBLISHER_NAME='${publisher_name}'")
|
||||
@@ -113,12 +131,26 @@ function run_step_cmake() {
|
||||
|
||||
function run_step_build() {
|
||||
echo "Running step: Build"
|
||||
make -C "${build_dir}" -j "${num_processors}"
|
||||
cmake --build "${build_dir}" -j "${num_processors}"
|
||||
return 0
|
||||
}
|
||||
|
||||
echo "*** To complete installation, run:"
|
||||
echo
|
||||
echo " sudo make -C \"${build_dir}\" install"
|
||||
echo " /usr/local/bin/sunshine"
|
||||
function run_step_dmg() {
|
||||
echo "Running step: Creating DMG package"
|
||||
|
||||
# This variable is needed by cmake/packaging/macos.cmake
|
||||
SHOULD_SIGN=false
|
||||
if [[ -n "${sign_app}" ]]; then
|
||||
SHOULD_SIGN=true
|
||||
fi
|
||||
export SHOULD_SIGN
|
||||
|
||||
cpack -G DragNDrop --config "${build_dir}/CPackConfig.cmake" --verbose
|
||||
|
||||
if [[ -n "${sign_app}" ]]; then
|
||||
xcrun notarytool submit "${build_dir}/cpack_artifacts/Sunshine.dmg" --keychain-profile "notarytool-password" --wait
|
||||
xcrun stapler staple -v "${build_dir}/cpack_artifacts/Sunshine.dmg"
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -133,14 +165,17 @@ function run_install() {
|
||||
build)
|
||||
run_step_build
|
||||
;;
|
||||
dmg)
|
||||
run_step_dmg
|
||||
;;
|
||||
all)
|
||||
run_step_deps
|
||||
run_step_cmake
|
||||
run_step_build
|
||||
run_step_dmg
|
||||
;;
|
||||
*)
|
||||
echo "Invalid step: $step"
|
||||
echo "Valid steps are: deps, cmake, build, all"
|
||||
echo "Valid steps are: deps, cmake, build, dmg, all"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -172,8 +207,14 @@ while getopts ":h-:" opt; do
|
||||
debug)
|
||||
build_type="Debug"
|
||||
;;
|
||||
skip-docs)
|
||||
build_docs="OFF"
|
||||
build-docs)
|
||||
build_docs="ON"
|
||||
;;
|
||||
skip-tests)
|
||||
build_tests="OFF"
|
||||
;;
|
||||
skip-codesign)
|
||||
sign_app=""
|
||||
;;
|
||||
*)
|
||||
echo "Invalid option: --${OPTARG}" 1>&2
|
||||
|
||||
@@ -5,9 +5,14 @@
|
||||
// standard includes
|
||||
#include <codecvt>
|
||||
#include <csignal>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <mach-o/dyld.h>
|
||||
#endif
|
||||
|
||||
// local includes
|
||||
#include "confighttp.h"
|
||||
#include "display_device.h"
|
||||
@@ -116,6 +121,25 @@ void mainThreadLoop(const std::shared_ptr<safe::event_t<bool>> &shutdown_event)
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
#ifdef __APPLE__
|
||||
// Bundle assets are referenced relative to the executable
|
||||
// (e.g. ../Resources/assets), so anchor cwd to Contents/MacOS.
|
||||
{
|
||||
char executable[2048];
|
||||
uint32_t size = sizeof(executable);
|
||||
if (_NSGetExecutablePath(executable, &size) == 0) {
|
||||
std::error_code ec;
|
||||
auto exec_dir = std::filesystem::weakly_canonical(std::filesystem::path {executable}, ec).parent_path();
|
||||
if (!ec) {
|
||||
std::filesystem::current_path(exec_dir, ec);
|
||||
}
|
||||
if (ec) {
|
||||
std::cerr << "Failed to set working directory to executable path: " << ec.message() << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
lifetime::argv = argv;
|
||||
|
||||
task_pool_util::TaskPool::task_id_t force_shutdown = nullptr;
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>dev.lizardbyte.sunshine</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Sunshine</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>This app requires access to your microphone to stream audio.</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>@PROJECT_FQDN@</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>@CMAKE_PROJECT_NAME@</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>@CMAKE_PROJECT_NAME@</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>@CMAKE_PROJECT_NAME@</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>@PROJECT_VERSION@</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>@PROJECT_VERSION@</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>sunshine.icns</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.utilities</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>@CMAKE_PROJECT_NAME@ requires access to your microphone to stream audio.</string>
|
||||
<key>NSBonjourServices</key>
|
||||
<array>
|
||||
<string>_nvstream._tcp</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
# Based on https://gitlab.kitware.com/cmake/cmake/-/blob/master/Packaging/CMakeDMGSetup.scpt
|
||||
on run argv
|
||||
set image_name to item 1 of argv
|
||||
|
||||
tell application "Finder"
|
||||
tell disk image_name
|
||||
|
||||
-- wait for the image to finish mounting
|
||||
set open_attempts to 0
|
||||
repeat while open_attempts < 4
|
||||
try
|
||||
open
|
||||
delay 1
|
||||
set open_attempts to 5
|
||||
close
|
||||
on error errStr number errorNumber
|
||||
set open_attempts to open_attempts + 1
|
||||
delay 10
|
||||
end try
|
||||
end repeat
|
||||
delay 5
|
||||
|
||||
-- open the image the first time and save a DS_Store with just
|
||||
-- background and icon setup
|
||||
open
|
||||
set current view of container window to icon view
|
||||
set theViewOptions to the icon view options of container window
|
||||
set background picture of theViewOptions to file ".background:background.jpg"
|
||||
set arrangement of theViewOptions to not arranged
|
||||
set icon size of theViewOptions to 128
|
||||
set text size of theViewOptions to 16
|
||||
close
|
||||
|
||||
-- next setup the position of the app and Applications symlink
|
||||
-- plus hide all the window decoration
|
||||
open
|
||||
update without registering applications
|
||||
tell container window
|
||||
set sidebar width to 0
|
||||
set statusbar visible to false
|
||||
set toolbar visible to false
|
||||
set the bounds to { 400, 100, 900, 465 }
|
||||
set position of item "Sunshine.app" to { 133, 200 }
|
||||
set position of item "Applications" to { 378, 200 }
|
||||
end tell
|
||||
update without registering applications
|
||||
close
|
||||
|
||||
end tell
|
||||
delay 1
|
||||
end tell
|
||||
end run
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 122 KiB |
Binary file not shown.
@@ -1,41 +0,0 @@
|
||||
#!/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
|
||||
|
||||
echo "Removing files now..."
|
||||
FILES=$(pkgutil --files $package_name --only-files)
|
||||
|
||||
for file in ${FILES}; do
|
||||
file="/$file"
|
||||
echo "removing: $file"
|
||||
rm -f "$file"
|
||||
done
|
||||
|
||||
echo "Removing directories now..."
|
||||
DIRECTORIES=$(pkgutil --files org.macports.Sunshine --only-dirs)
|
||||
|
||||
for dir in ${DIRECTORIES}; do
|
||||
dir="/$dir"
|
||||
echo "Checking if empty directory: $dir"
|
||||
|
||||
# check if directory is empty... could just use ${DIRECTORIES} here if pkgutils added the `/` prefix
|
||||
empty_dir=$(find "$dir" -depth 0 -type d -empty)
|
||||
|
||||
# remove the directory if it is empty
|
||||
if [[ $empty_dir != "" ]]; then # prevent the loop from running and failing if no directories found
|
||||
# shellcheck disable=SC2066 # don't split words as we already know this will be a single directory
|
||||
for i in "${empty_dir}"; do
|
||||
echo "Removing empty directory: ${i}"
|
||||
rmdir "${i}"
|
||||
done
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Forgetting Sunshine..."
|
||||
pkgutil --forget $package_name
|
||||
|
||||
echo "Sunshine has been uninstalled..."
|
||||
Binary file not shown.
Reference in New Issue
Block a user