Support macOS bundling for binary distribution

This commit is contained in:
vit9696 2018-11-24 03:27:33 +03:00 committed by Ivan
parent c50d459b1e
commit 5a40c1802b
9 changed files with 109 additions and 39 deletions

View File

@ -15,7 +15,9 @@ unzip -: sdk-*.zip
mkdir vulkan-sdk
ln -s ${PWD}/Vulkan-Headers*/include vulkan-sdk/include
mkdir vulkan-sdk/lib
ln target/release/libportability.dylib vulkan-sdk/lib/libVulkan.dylib
cp target/release/libportability.dylib vulkan-sdk/lib/libVulkan.dylib
# Let macdeployqt locate and install Vulkan library
install_name_tool -id ${PWD}/vulkan-sdk/lib/libVulkan.dylib vulkan-sdk/lib/libVulkan.dylib
export VULKAN_SDK=${PWD}/vulkan-sdk
git submodule update --quiet --init asmjit 3rdparty/ffmpeg 3rdparty/pugixml 3rdparty/GSL 3rdparty/libpng 3rdparty/cereal 3rdparty/hidapi 3rdparty/xxHash 3rdparty/yaml-cpp Vulkan/glslang

View File

@ -1376,10 +1376,16 @@ const std::string& fs::get_config_dir()
dir.resize(dir.rfind('/') + 1);
#else
#ifdef __APPLE__
if (const char* home = ::getenv("HOME"))
dir = home + "/Library/Application Support"s;
#else
if (const char* home = ::getenv("XDG_CONFIG_HOME"))
dir = home;
else if (const char* home = ::getenv("HOME"))
dir = home + "/.config"s;
#endif
else // Just in case
dir = "./config";

View File

@ -41,6 +41,15 @@ file(GLOB RPCS3_SRC "*.cpp")
if(WIN32)
add_executable(rpcs3 WIN32 ${RPCS3_SRC})
elseif(APPLE)
set(MACOSX_BUNDLE_BUNDLE_NAME rpcs3)
set(MACOSX_BUNDLE_GUI_IDENTIFIER "net.rpcs3.rpcs3")
set(MACOSX_BUNDLE_INFO_STRING "Open-source Sony PlayStation 3 emulator")
set(MACOSX_BUNDLE_ICON_FILE "rpcs3.icns")
set(MACOSX_BUNDLE_LONG_VERSION_STRING "0.0.5")
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "0.0.5")
set(MACOSX_BUNDLE_BUNDLE_VERSION "0.0.5")
add_executable(rpcs3 MACOSX_BUNDLE ${RPCS3_SRC} "${RPCS3_SRC_DIR}/rpcs3.icns")
else()
add_executable(rpcs3 ${RPCS3_SRC})
endif()
@ -84,8 +93,17 @@ set_target_properties(rpcs3 PROPERTIES
cotire(rpcs3)
if (UNIX)
# Copy icons to executable directory
# Copy icons to executable directory
if(APPLE)
add_custom_command(TARGET rpcs3 POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${RPCS3_SRC_DIR}/rpcs3.icns $<TARGET_FILE_DIR:rpcs3>/../Resources/rpcs3.icns
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_SOURCE_DIR}/bin/Icons $<TARGET_FILE_DIR:rpcs3>/../Resources/Icons
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_SOURCE_DIR}/bin/GuiConfigs $<TARGET_FILE_DIR:rpcs3>/../Resources/GuiConfigs
COMMAND "${Qt5_DIR}/../../../bin/macdeployqt" "${PROJECT_BINARY_DIR}/bin/rpcs3.app")
elseif(UNIX)
add_custom_command(TARGET rpcs3 POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_SOURCE_DIR}/bin/Icons $<TARGET_FILE_DIR:rpcs3>/Icons)

View File

@ -15,6 +15,10 @@
#include <libgen.h>
#endif
#ifdef __APPLE__
#include <mach-o/dyld.h>
#endif
// STB_IMAGE_IMPLEMENTATION and STB_TRUETYPE_IMPLEMENTATION defined externally
#include <stb_image.h>
#include <stb_truetype.h>
@ -505,24 +509,37 @@ namespace rsx
if (info->data == nullptr)
{
// Resource was not found in config dir, try and grab from relative path (linux)
info = std::make_unique<image_info>(("Icons/ui/" + res).c_str());
auto src = "Icons/ui/" + res;
info = std::make_unique<image_info>(src.c_str());
#ifndef _WIN32
// Check for Icons in ../share/rpcs3 for AppImages and /usr/bin/
// Check for Icons in ../share/rpcs3 for AppImages,
// in rpcs3.app/Contents/Resources for App Bundles, and /usr/bin.
if (info->data == nullptr)
{
char result[ PATH_MAX ];
#ifdef __linux__
ssize_t count = readlink( "/proc/self/exe", result, PATH_MAX );
#if defined(__APPLE__)
uint32_t bufsize = PATH_MAX;
bool success = _NSGetExecutablePath( result, &bufsize ) == 0;
#elif defined(__linux__)
bool success = readlink( "/proc/self/exe", result, PATH_MAX ) >= 0;
#else
ssize_t count = readlink( "/proc/curproc/file", result, PATH_MAX );
bool success = readlink( "/proc/curproc/file", result, PATH_MAX ) >= 0;
#endif
std::string executablePath = dirname(result);
info = std::make_unique<image_info>((executablePath + "/../share/rpcs3/Icons/ui/" + res).c_str());
// Check if the icons are in the same directory as the executable (local builds)
if (info->data == nullptr)
if (success)
{
info = std::make_unique<image_info>((executablePath + "/Icons/ui/" + res).c_str());
std::string executablePath = dirname(result);
#ifdef __APPLE__
src = executablePath + "/../Resources/Icons/ui/" + res;
#else
src = executablePath + "/../share/rpcs3/Icons/ui/" + res;
#endif
info = std::make_unique<image_info>(src.c_str());
// Check if the icons are in the same directory as the executable (local builds)
if (info->data == nullptr)
{
src = executablePath + "/Icons/ui/" + res;
info = std::make_unique<image_info>(src.c_str());
}
}
}
#endif
@ -530,7 +547,6 @@ namespace rsx
{
// Install the image to config dir
auto dst_dir = fs::get_config_dir() + "Icons/ui/";
auto src = "Icons/ui/" + res;
auto dst = dst_dir + res;
if (!fs::is_dir(dst_dir))

View File

@ -18,6 +18,10 @@
#include <sys/resource.h>
#endif
#ifdef __APPLE__
#include <dispatch/dispatch.h>
#endif
#include "rpcs3_version.h"
inline std::string sstr(const QString& _in) { return _in.toStdString(); }
@ -50,23 +54,38 @@ static semaphore<> s_qt_mutex{};
static QApplication app0{argc, argv};
}
QMessageBox msg;
msg.setWindowTitle(tr("RPCS3: Fatal Error"));
msg.setIcon(QMessageBox::Critical);
msg.setTextFormat(Qt::RichText);
msg.setText(QString(R"(
<p style="white-space: nowrap;">
%1<br>
%2<br>
<a href='https://github.com/RPCS3/rpcs3/wiki/How-to-ask-for-Support'>https://github.com/RPCS3/rpcs3/wiki/How-to-ask-for-Support</a><br>
%3<br>
</p>
)")
.arg(Qt::convertFromPlainText(QString::fromStdString(text)))
.arg(tr("HOW TO REPORT ERRORS:"))
.arg(tr("Please, don't send incorrect reports. Thanks for understanding.")));
msg.layout()->setSizeConstraint(QLayout::SetFixedSize);
msg.exec();
auto show_report = [](const std::string& text)
{
QMessageBox msg;
msg.setWindowTitle(tr("RPCS3: Fatal Error"));
msg.setIcon(QMessageBox::Critical);
msg.setTextFormat(Qt::RichText);
msg.setText(QString(R"(
<p style="white-space: nowrap;">
%1<br>
%2<br>
<a href='https://github.com/RPCS3/rpcs3/wiki/How-to-ask-for-Support'>https://github.com/RPCS3/rpcs3/wiki/How-to-ask-for-Support</a><br>
%3<br>
</p>
)")
.arg(Qt::convertFromPlainText(QString::fromStdString(text)))
.arg(tr("HOW TO REPORT ERRORS:"))
.arg(tr("Please, don't send incorrect reports. Thanks for understanding.")));
msg.layout()->setSizeConstraint(QLayout::SetFixedSize);
msg.exec();
};
#ifdef __APPLE__
// Cocoa access is not allowed outside of the main thread
if (!pthread_main_np())
{
dispatch_sync(dispatch_get_main_queue(), ^ { show_report(text); });
}
else
#endif
{
show_report(text);
}
std::abort();
}

BIN
rpcs3/rpcs3.icns Normal file

Binary file not shown.

View File

@ -422,9 +422,13 @@ void rpcs3_app::OnChangeStyleSheetRequest(const QString& path)
QFile file(path);
#if !defined(_WIN32) && !defined(__APPLE__)
// If we can't open the file, try the /share folder
// If we can't open the file, try the /share or /Resources folder
#if !defined(_WIN32)
#ifdef __APPLE__
QString share_dir = QCoreApplication::applicationDirPath() + "/../Resources/";
#else
QString share_dir = QCoreApplication::applicationDirPath() + "/../share/rpcs3/";
#endif
QFile share_file(share_dir + "GuiConfigs/" + QFileInfo(file.fileName()).fileName());
#endif
@ -451,7 +455,7 @@ void rpcs3_app::OnChangeStyleSheetRequest(const QString& path)
setStyleSheet(file.readAll());
file.close();
}
#if !defined(_WIN32) && !defined(__APPLE__)
#if !defined(_WIN32)
else if (share_file.open(QIODevice::ReadOnly | QIODevice::Text))
{
QDir::setCurrent(share_dir);

View File

@ -9,5 +9,6 @@ namespace rpcs3
return RPCS3_GIT_BRANCH;
}
//TODO: Make this accessible from cmake and keep in sync with MACOSX_BUNDLE_BUNDLE_VERSION.
const extern utils::version version{ 0, 0, 5, utils::version_type::alpha, 1, RPCS3_GIT_VERSION };
}

View File

@ -338,10 +338,14 @@ QStringList gui_settings::GetStylesheetEntries()
{
QStringList nameFilter = QStringList("*.qss");
QStringList res = gui::utils::get_dir_entries(m_settingsDir, nameFilter);
#if !defined(_WIN32) && !defined(__APPLE__)
// Makes stylesheets load if using AppImage or installed to /usr/bin
QDir linuxStylesheetDir = QCoreApplication::applicationDirPath() + "/../share/rpcs3/GuiConfigs/";
res.append(gui::utils::get_dir_entries(linuxStylesheetDir, nameFilter));
#if !defined(_WIN32)
// Makes stylesheets load if using AppImage (App Bundle) or installed to /usr/bin
#ifdef __APPLE__
QDir platformStylesheetDir = QCoreApplication::applicationDirPath() + "/../Resources/GuiConfigs/";
#else
QDir platformStylesheetDir = QCoreApplication::applicationDirPath() + "/../share/rpcs3/GuiConfigs/";
#endif
res.append(gui::utils::get_dir_entries(platformStylesheetDir, nameFilter));
res.removeDuplicates();
#endif
res.sort(Qt::CaseInsensitive);