diff --git a/.gitignore b/.gitignore index e39a3bd3d..e49baff2e 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,6 @@ CMakeLists.txt.user # python bytecode __pycache__ + +# other repos +/dep/mac diff --git a/CMakeModules/DolphinPostprocessBundle.cmake b/CMakeModules/DolphinPostprocessBundle.cmake new file mode 100644 index 000000000..ba412ba48 --- /dev/null +++ b/CMakeModules/DolphinPostprocessBundle.cmake @@ -0,0 +1,46 @@ +# This module can be used in two different ways. +# +# When invoked as `cmake -P DolphinPostprocessBundle.cmake`, it fixes up an +# application folder to be standalone. It bundles all required libraries from +# the system and fixes up library IDs. Any additional shared libraries, like +# plugins, that are found under Contents/MacOS/ will be made standalone as well. +# +# When called with `include(DolphinPostprocessBundle)`, it defines a helper +# function `dolphin_postprocess_bundle` that sets up the command form of the +# module as a post-build step. + +if(CMAKE_GENERATOR) + # Being called as include(DolphinPostprocessBundle), so define a helper function. + 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="$/../.." + -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 +# needed. +file(GLOB_RECURSE extra_libs "${DOLPHIN_BUNDLE_PATH}/Contents/MacOS/*.dylib") + +# BundleUtilities doesn't support DYLD_FALLBACK_LIBRARY_PATH behavior, which +# makes it sometimes break on libraries that do weird things with @rpath. Specify +# equivalent search directories until https://gitlab.kitware.com/cmake/cmake/issues/16625 +# is fixed and in our minimum CMake version. +set(extra_dirs "/usr/local/lib" "/lib" "/usr/lib") + +# BundleUtilities is overly verbose, so disable most of its messages +function(message) + if(NOT ARGV MATCHES "^STATUS;") + _message(${ARGV}) + endif() +endfunction() + +include(BundleUtilities) +set(BU_CHMOD_BUNDLE_ITEMS ON) +fixup_bundle("${DOLPHIN_BUNDLE_PATH}" "${extra_libs}" "${extra_dirs}") diff --git a/src/duckstation-qt/CMakeLists.txt b/src/duckstation-qt/CMakeLists.txt index 3efd34db4..5a5d186ce 100644 --- a/src/duckstation-qt/CMakeLists.txt +++ b/src/duckstation-qt/CMakeLists.txt @@ -105,3 +105,63 @@ if(WIN32) COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/qt.conf.win" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/qt.conf" ) endif() + +if(APPLE) + include(BundleUtilities) + set(BUNDLE_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/DuckStation.app) + + # Ask for an application bundle. + set_target_properties(duckstation-qt PROPERTIES + MACOSX_BUNDLE true + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in + OUTPUT_NAME DuckStation + ) + + # Copy qt.conf into the bundle + target_sources(duckstation-qt PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/qt.conf") + set_source_files_properties("${CMAKE_CURRENT_SOURCE_DIR}/qt.conf" PROPERTIES MACOSX_PACKAGE_LOCATION Resources) + + # Copy icon into the bundle + target_sources(duckstation-qt PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/DuckStation.icns") + set_source_files_properties("${CMAKE_CURRENT_SOURCE_DIR}/DuckStation.icns" PROPERTIES MACOSX_PACKAGE_LOCATION Resources) + + # Copy Qt plugins into the bundle + get_target_property(qtcocoa_location Qt5::QCocoaIntegrationPlugin LOCATION) + target_sources(duckstation-qt PRIVATE "${qtcocoa_location}") + set_source_files_properties("${qtcocoa_location}" PROPERTIES MACOSX_PACKAGE_LOCATION MacOS/platforms) + + get_target_property(qtmacstyle_location Qt5::QMacStylePlugin LOCATION) + target_sources(duckstation-qt PRIVATE "${qtmacstyle_location}") + set_source_files_properties("${qtmacstyle_location}" PROPERTIES MACOSX_PACKAGE_LOCATION MacOS/styles) + + # Copy resources into the bundle + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${CMAKE_SOURCE_DIR}/data") + file(GLOB_RECURSE resources RELATIVE "${CMAKE_SOURCE_DIR}/data" "${CMAKE_SOURCE_DIR}/data/*") + foreach(res ${resources}) + target_sources(duckstation-qt PRIVATE "${CMAKE_SOURCE_DIR}/data/${res}") + get_filename_component(resdir "${res}" DIRECTORY) + set_source_files_properties("${CMAKE_SOURCE_DIR}/data/${res}" PROPERTIES + MACOSX_PACKAGE_LOCATION "MacOS/${resdir}") + source_group("Resources" FILES "${CMAKE_SOURCE_DIR}/data/${res}") + endforeach() + + # Copy translations into the bundle + add_custom_command(TARGET duckstation-qt + POST_BUILD + COMMAND mkdir $/translations + COMMAND cp ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/translations/*.qm $/translations) + + # Copy MoltenVK into the bundle + target_sources(duckstation-qt PRIVATE "${CMAKE_SOURCE_DIR}/dep/mac/MoltenVK/libvulkan.dylib") + set_source_files_properties("${CMAKE_SOURCE_DIR}/dep/mac/MoltenVK/libvulkan.dylib" PROPERTIES MACOSX_PACKAGE_LOCATION Frameworks) + + # Update library references to make the bundle portable + include(DolphinPostprocessBundle) + dolphin_postprocess_bundle(duckstation-qt) + # Fix rpath + add_custom_command(TARGET duckstation-qt + POST_BUILD COMMAND + ${CMAKE_INSTALL_NAME_TOOL} -add_rpath "@executable_path/../Frameworks/" + $) +endif() + diff --git a/src/duckstation-qt/DuckStation.icns b/src/duckstation-qt/DuckStation.icns new file mode 100644 index 000000000..fe463b16e Binary files /dev/null and b/src/duckstation-qt/DuckStation.icns differ diff --git a/src/duckstation-qt/Info.plist.in b/src/duckstation-qt/Info.plist.in new file mode 100644 index 000000000..572ee0d29 --- /dev/null +++ b/src/duckstation-qt/Info.plist.in @@ -0,0 +1,45 @@ + + + + + CFBundleDocumentTypes + + + CFBundleTypeExtensions + + bin + cue + img + chd + m3u + psexe + psf + + CFBundleTypeIconFile + DuckStation.icns + CFBundleTypeName + PlayStation File + CFBundleTypeRole + Viewer + + + CFBundleExecutable + DuckStation + CFBundleIconFile + DuckStation.icns + CFBundleIdentifier + com.github.stenzek.duckstation + CFBundleDevelopmentRegion + English + CFBundlePackageType + APPL + NSHumanReadableCopyright + Licensed under GPL version 3 + LSMinimumSystemVersion + ${CMAKE_OSX_DEPLOYMENT_TARGET} + NSHighResolutionCapable + + CSResourcesFileMapped + + + diff --git a/src/duckstation-qt/qt.conf b/src/duckstation-qt/qt.conf new file mode 100644 index 000000000..e69de29bb