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:
@@ -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
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR})
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user