Merge pull request #12968 from OatmealDome/mac-updater-embed-3

Embed the Updater into DolphinQt's app bundle on macOS
This commit is contained in:
OatmealDome 2024-08-08 02:07:58 -04:00 committed by GitHub
commit 644508cfd7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 178 additions and 46 deletions

View File

@ -59,8 +59,6 @@ DEFAULT_CONFIG = {
# running corrupted binaries and allows for access to the extended # running corrupted binaries and allows for access to the extended
# permisions needed for ARM builds # permisions needed for ARM builds
"codesign_identity": "-", "codesign_identity": "-",
# Entitlements file to use for code signing
"entitlements": "../Source/Core/DolphinQt/DolphinEmu.entitlements",
# Minimum macOS version for each architecture slice # Minimum macOS version for each architecture slice
"arm64_mac_os_deployment_target": "11.0.0", "arm64_mac_os_deployment_target": "11.0.0",
@ -119,11 +117,6 @@ def parse_args(conf=DEFAULT_CONFIG):
help="Directory where universal binary will be stored", help="Directory where universal binary will be stored",
default=conf["dst_app"]) default=conf["dst_app"])
parser.add_argument(
"--entitlements",
help="Path to .entitlements file for code signing",
default=conf["entitlements"])
parser.add_argument("--run_unit_tests", action="store_true", parser.add_argument("--run_unit_tests", action="store_true",
default=conf["run_unit_tests"]) default=conf["run_unit_tests"])
@ -317,8 +310,6 @@ def build(config):
+ config[arch+"_mac_os_deployment_target"], + config[arch+"_mac_os_deployment_target"],
"-DMACOS_CODE_SIGNING_IDENTITY=" "-DMACOS_CODE_SIGNING_IDENTITY="
+ config["codesign_identity"], + config["codesign_identity"],
"-DMACOS_CODE_SIGNING_IDENTITY_UPDATER="
+ config["codesign_identity"],
'-DMACOS_CODE_SIGNING="ON"', '-DMACOS_CODE_SIGNING="ON"',
"-DSTEAM=" "-DSTEAM="
+ python_to_cmake_bool(config["steam"]), + python_to_cmake_bool(config["steam"]),
@ -354,21 +345,21 @@ def build(config):
src_app1 = ARCHITECTURES[1]+"/Binaries/" src_app1 = ARCHITECTURES[1]+"/Binaries/"
recursive_merge_binaries(src_app0, src_app1, dst_app) recursive_merge_binaries(src_app0, src_app1, dst_app)
for path in glob.glob(dst_app+"/*"):
if os.path.isdir(path) and os.path.splitext(path)[1] != ".app": if config["autoupdate"]:
continue
subprocess.check_call([ subprocess.check_call([
"codesign", "../Tools/mac-codesign.sh",
"-d", "-t",
"--force", "-e", "preserve",
"-s",
config["codesign_identity"], config["codesign_identity"],
"--options=runtime", dst_app+"/Dolphin.app/Contents/Helpers/Dolphin Updater.app"])
"--entitlements", config["entitlements"],
"--deep", subprocess.check_call([
"--verbose=2", "../Tools/mac-codesign.sh",
path]) "-t",
"-e", "preserve",
config["codesign_identity"],
dst_app+"/Dolphin.app"])
print("Built Universal Binary successfully!") print("Built Universal Binary successfully!")

View File

@ -14,14 +14,13 @@ if(CMAKE_GENERATOR)
set(_DOLPHIN_POSTPROCESS_BUNDLE_MODULE_LOCATION "${CMAKE_CURRENT_LIST_FILE}") set(_DOLPHIN_POSTPROCESS_BUNDLE_MODULE_LOCATION "${CMAKE_CURRENT_LIST_FILE}")
function(dolphin_postprocess_bundle target) function(dolphin_postprocess_bundle target)
add_custom_command(TARGET ${target} POST_BUILD add_custom_command(TARGET ${target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -DDOLPHIN_BUNDLE_PATH="$<TARGET_FILE_DIR:${target}>/../.." COMMAND ${CMAKE_COMMAND} "-D" "DOLPHIN_BUNDLE_PATH=$<TARGET_BUNDLE_DIR:${target}>"
-P "${_DOLPHIN_POSTPROCESS_BUNDLE_MODULE_LOCATION}" -P "${_DOLPHIN_POSTPROCESS_BUNDLE_MODULE_LOCATION}"
) )
endfunction() endfunction()
return() return()
endif() endif()
get_filename_component(DOLPHIN_BUNDLE_PATH "${DOLPHIN_BUNDLE_PATH}" ABSOLUTE)
message(STATUS "Fixing up application bundle: ${DOLPHIN_BUNDLE_PATH}") message(STATUS "Fixing up application bundle: ${DOLPHIN_BUNDLE_PATH}")
# Make sure to fix up any additional shared libraries (like plugins) that are # Make sure to fix up any additional shared libraries (like plugins) that are

View File

@ -138,7 +138,6 @@ if(APPLE)
option(MACOS_CODE_SIGNING "Enable codesigning" ON) option(MACOS_CODE_SIGNING "Enable codesigning" ON)
option(USE_BUNDLED_MOLTENVK "Build MoltenVK from Externals with Dolphin-specific patches" ON) option(USE_BUNDLED_MOLTENVK "Build MoltenVK from Externals with Dolphin-specific patches" ON)
set(MACOS_CODE_SIGNING_IDENTITY "-" CACHE STRING "The identity used for codesigning.") set(MACOS_CODE_SIGNING_IDENTITY "-" CACHE STRING "The identity used for codesigning.")
set(MACOS_CODE_SIGNING_IDENTITY_UPDATER "-" CACHE STRING "The identity used for codesigning, for the updater.")
endif() endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Linux") if(CMAKE_SYSTEM_NAME STREQUAL "Linux")

View File

@ -30,3 +30,59 @@ endif()
if (WIN32 AND ENABLE_AUTOUPDATE) if (WIN32 AND ENABLE_AUTOUPDATE)
add_subdirectory(WinUpdater) add_subdirectory(WinUpdater)
endif() endif()
if (APPLE AND ENABLE_QT)
set(DOLPHIN_MAC_BUNDLE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Dolphin.app")
add_custom_target(build_final_bundle ALL
COMMAND ${CMAKE_COMMAND} -E remove_directory
${DOLPHIN_MAC_BUNDLE}
COMMAND cp -R
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/DolphinQt.app
${DOLPHIN_MAC_BUNDLE}
# HACK: The Updater does not support setting the executable bit on new files,
# so don't use the new executable name, and instead continue to use "Dolphin".
COMMAND ${CMAKE_COMMAND} -E rename
${DOLPHIN_MAC_BUNDLE}/Contents/MacOS/DolphinQt
${DOLPHIN_MAC_BUNDLE}/Contents/MacOS/Dolphin
COMMAND plutil
-replace CFBundleExecutable -string Dolphin
${DOLPHIN_MAC_BUNDLE}/Contents/Info.plist
DEPENDS dolphin-emu)
if (ENABLE_AUTOUPDATE)
add_dependencies(build_final_bundle MacUpdater)
add_custom_command(TARGET build_final_bundle
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory
"${DOLPHIN_MAC_BUNDLE}/Contents/Helpers"
COMMAND cp -R
"$<TARGET_BUNDLE_DIR:MacUpdater>"
"${DOLPHIN_MAC_BUNDLE}/Contents/Helpers/Dolphin Updater.app")
if (MACOS_CODE_SIGNING)
add_custom_command(TARGET build_final_bundle
POST_BUILD
COMMAND "${CMAKE_SOURCE_DIR}/Tools/mac-codesign.sh"
"-t"
"${MACOS_CODE_SIGNING_IDENTITY}"
"${DOLPHIN_MAC_BUNDLE}/Contents/Helpers/Dolphin Updater.app")
endif()
endif()
if (MACOS_CODE_SIGNING)
add_custom_command(TARGET build_final_bundle
POST_BUILD
COMMAND "${CMAKE_SOURCE_DIR}/Tools/mac-codesign.sh"
"-t"
"-e" "${CMAKE_SOURCE_DIR}/Source/Core/DolphinQt/DolphinEmu$<$<CONFIG:Debug>:Debug>.entitlements"
"${MACOS_CODE_SIGNING_IDENTITY}"
"${DOLPHIN_MAC_BUNDLE}")
endif()
endif()

View File

@ -566,15 +566,14 @@ endif()
if(APPLE) if(APPLE)
include(BundleUtilities) include(BundleUtilities)
set(BUNDLE_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Dolphin.app) set(BUNDLE_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/DolphinQt.app)
# Ask for an application bundle. # Ask for an application bundle.
set_target_properties(dolphin-emu PROPERTIES set_target_properties(dolphin-emu PROPERTIES
MACOSX_BUNDLE true MACOSX_BUNDLE true
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_BINARY_DIR}/Info.plist" MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_BINARY_DIR}/Info.plist"
XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_CURRENT_SOURCE_DIR}/DolphinEmu.entitlements" XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ""
XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS "--deep --options=runtime" OUTPUT_NAME DolphinQt
OUTPUT_NAME Dolphin
) )
# Copy qt.conf into the bundle # Copy qt.conf into the bundle
@ -638,9 +637,13 @@ if(APPLE)
endif() endif()
if(MACOS_CODE_SIGNING) if(MACOS_CODE_SIGNING)
# Code sign make file builds add_custom_command(TARGET dolphin-emu
add_custom_command(TARGET dolphin-emu POST_BUILD POST_BUILD
COMMAND /usr/bin/codesign -f -s "${MACOS_CODE_SIGNING_IDENTITY}" --deep --options=runtime --entitlements "${CMAKE_SOURCE_DIR}/Source/Core/DolphinQt/DolphinEmu$<$<CONFIG:Debug>:Debug>.entitlements" "$<TARGET_BUNDLE_DIR:dolphin-emu>") COMMAND "${CMAKE_SOURCE_DIR}/Tools/mac-codesign.sh"
"-e" "${CMAKE_CURRENT_SOURCE_DIR}/DolphinEmu$<$<CONFIG:Debug>:Debug>.entitlements"
"${MACOS_CODE_SIGNING_IDENTITY}"
"${BUNDLE_PATH}"
)
endif() endif()
else() else()
install(TARGETS dolphin-emu RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) install(TARGETS dolphin-emu RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

View File

@ -30,7 +30,7 @@
</dict> </dict>
</array> </array>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>Dolphin</string> <string>DolphinQt</string>
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
<string>Dolphin.icns</string> <string>Dolphin.icns</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>

View File

@ -53,11 +53,23 @@ foreach(sb ${STORYBOARDS})
COMMENT "Compiling Storyboard ${sb}...") COMMENT "Compiling Storyboard ${sb}...")
endforeach() endforeach()
if(MACOS_CODE_SIGNING) if(NOT SKIP_POSTPROCESS_BUNDLE)
if (MACOS_CODE_SIGNING_IDENTITY_UPDATER STREQUAL "") # Update library references to make the bundle portable
set(MACOS_CODE_SIGNING_IDENTITY_UPDATER "${MACOS_CODE_SIGNING_IDENTITY}") include(DolphinPostprocessBundle)
endif() dolphin_postprocess_bundle(MacUpdater)
add_custom_command(TARGET MacUpdater POST_BUILD # Fix rpath
COMMAND /usr/bin/codesign -f -s "${MACOS_CODE_SIGNING_IDENTITY_UPDATER}" --deep --options runtime $<TARGET_BUNDLE_DIR:MacUpdater>) add_custom_command(TARGET MacUpdater
POST_BUILD COMMAND
${CMAKE_INSTALL_NAME_TOOL} -add_rpath "@executable_path/../Frameworks/"
$<TARGET_FILE:MacUpdater>)
endif()
if(MACOS_CODE_SIGNING)
add_custom_command(TARGET MacUpdater
POST_BUILD
COMMAND "${CMAKE_SOURCE_DIR}/Tools/mac-codesign.sh"
"${MACOS_CODE_SIGNING_IDENTITY}"
"$<TARGET_BUNDLE_DIR:MacUpdater>"
)
endif() endif()

View File

@ -9,11 +9,11 @@
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
<string>Dolphin.icns</string> <string>Dolphin.icns</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>com.dolphinteam.dolphin-updater</string> <string>org.dolphin-emu.updater</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>Updater</string> <string>Dolphin Updater</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>

View File

@ -49,15 +49,13 @@ const char UPDATER_LOG_FILE[] = "Updater.log";
std::string UpdaterPath(bool relocated = false) std::string UpdaterPath(bool relocated = false)
{ {
std::string path(File::GetExeDirectory() + DIR_SEP);
#ifdef __APPLE__ #ifdef __APPLE__
if (relocated) if (relocated)
path += ".Dolphin Updater.2.app"; return File::GetExeDirectory() + DIR_SEP + ".Dolphin Updater.2.app";
else else
path += "Dolphin Updater.app"; return File::GetBundleDirectory() + DIR_SEP + "Contents/Helpers/Dolphin Updater.app";
return path;
#else #else
return path + "Updater.exe"; return File::GetExeDirectory() + DIR_SEP + "Updater.exe";
#endif #endif
} }

74
Tools/mac-codesign.sh Executable file
View File

@ -0,0 +1,74 @@
#!/bin/bash
# This script signs a specific object with the specified identity, entitlements,
# and optional flags. If the target is a bundle, it will also sign all frameworks
# and dylibs within the bundle.
set -eu
function usage() {
echo "Usage: $0 [-t] [-e <entitlements file or "preserve">] <identity> <target to codesign>"
exit 1
}
USE_SECURE_TIMESTAMP=0
ENTITLEMENTS_FILE=""
while getopts ":te:" opt; do
case $opt in
t)
USE_SECURE_TIMESTAMP=1
;;
e)
ENTITLEMENTS_FILE=$OPTARG
;;
\?)
usage
;;
esac
done
if [ $USE_SECURE_TIMESTAMP -eq 1 ]; then
TIMESTAMP_FLAG="--timestamp"
else
TIMESTAMP_FLAG="--timestamp=none"
fi
shift $((OPTIND - 1))
if [ $# -ne 2 ]; then
usage
fi
IDENTITY=$1
TARGET_PATH=$2
# Signs the given target with the specified identity and optional flags.
function sign() {
/usr/bin/codesign -f -s "$IDENTITY" $TIMESTAMP_FLAG ${2:-} "$1"
}
if [ -d "$TARGET_PATH" ]; then
# Newlines are the only valid separator character in find's output.
IFS=$'\n'
for framework in $(find "$TARGET_PATH" -depth -not -path "*/Helpers/*" -name '*.dylib' -or -name '*.framework'); do
sign "$framework"
done
unset IFS
fi
TARGET_EXTRA_CODESIGN_FLAGS="-o runtime"
if [ -n "$ENTITLEMENTS_FILE" ]; then
# "preserve" is a special keyword which tells us we should preserve the
# existing entitlements in the target.
if [ "$ENTITLEMENTS_FILE" == "preserve" ]; then
TARGET_EXTRA_CODESIGN_FLAGS+=" --preserve-metadata=entitlements"
else
TARGET_EXTRA_CODESIGN_FLAGS+=" --entitlements $ENTITLEMENTS_FILE"
fi
fi
sign "$TARGET_PATH" "$TARGET_EXTRA_CODESIGN_FLAGS"