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
# permisions needed for ARM builds
"codesign_identity": "-",
# Entitlements file to use for code signing
"entitlements": "../Source/Core/DolphinQt/DolphinEmu.entitlements",
# Minimum macOS version for each architecture slice
"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",
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",
default=conf["run_unit_tests"])
@ -317,8 +310,6 @@ def build(config):
+ config[arch+"_mac_os_deployment_target"],
"-DMACOS_CODE_SIGNING_IDENTITY="
+ config["codesign_identity"],
"-DMACOS_CODE_SIGNING_IDENTITY_UPDATER="
+ config["codesign_identity"],
'-DMACOS_CODE_SIGNING="ON"',
"-DSTEAM="
+ python_to_cmake_bool(config["steam"]),
@ -354,21 +345,21 @@ def build(config):
src_app1 = ARCHITECTURES[1]+"/Binaries/"
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":
continue
if config["autoupdate"]:
subprocess.check_call([
"codesign",
"-d",
"--force",
"-s",
"../Tools/mac-codesign.sh",
"-t",
"-e", "preserve",
config["codesign_identity"],
"--options=runtime",
"--entitlements", config["entitlements"],
"--deep",
"--verbose=2",
path])
dst_app+"/Dolphin.app/Contents/Helpers/Dolphin Updater.app"])
subprocess.check_call([
"../Tools/mac-codesign.sh",
"-t",
"-e", "preserve",
config["codesign_identity"],
dst_app+"/Dolphin.app"])
print("Built Universal Binary successfully!")

View File

@ -14,14 +14,13 @@ if(CMAKE_GENERATOR)
set(_DOLPHIN_POSTPROCESS_BUNDLE_MODULE_LOCATION "${CMAKE_CURRENT_LIST_FILE}")
function(dolphin_postprocess_bundle target)
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}"
)
endfunction()
return()
endif()
get_filename_component(DOLPHIN_BUNDLE_PATH "${DOLPHIN_BUNDLE_PATH}" ABSOLUTE)
message(STATUS "Fixing up application bundle: ${DOLPHIN_BUNDLE_PATH}")
# 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(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_UPDATER "-" CACHE STRING "The identity used for codesigning, for the updater.")
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")

View File

@ -30,3 +30,59 @@ endif()
if (WIN32 AND ENABLE_AUTOUPDATE)
add_subdirectory(WinUpdater)
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)
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.
set_target_properties(dolphin-emu PROPERTIES
MACOSX_BUNDLE true
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_BINARY_DIR}/Info.plist"
XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_CURRENT_SOURCE_DIR}/DolphinEmu.entitlements"
XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS "--deep --options=runtime"
OUTPUT_NAME Dolphin
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ""
OUTPUT_NAME DolphinQt
)
# Copy qt.conf into the bundle
@ -638,9 +637,13 @@ if(APPLE)
endif()
if(MACOS_CODE_SIGNING)
# Code sign make file builds
add_custom_command(TARGET dolphin-emu 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>")
add_custom_command(TARGET dolphin-emu
POST_BUILD
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()
else()
install(TARGETS dolphin-emu RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

View File

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

View File

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

View File

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

View File

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