[macOS] Build infrastructure and portability fixes
Build system: - Enable ObjC++, macOS deployment target, framework linking - Fix AppleClang detection - macOS platform name for output directories - Skip Vulkan on macOS, null graphics without Vulkan dependency - macOS SDL2 framework detection and discord-rpc macOS sources Portability fixes: - mach_absolute_time for macOS tick counting - _NSGetExecutablePath for macOS - guard MAP_FIXED_NOREPLACE, ftruncate64->ftruncate - guard Vulkan include/usage, fix data root for all POSIX
This commit is contained in:
@@ -1,5 +1,11 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
project(xenia LANGUAGES C CXX)
|
||||
if(APPLE)
|
||||
project(xenia LANGUAGES C CXX OBJCXX)
|
||||
set(CMAKE_OBJCXX_STANDARD 20)
|
||||
set(CMAKE_OBJCXX_STANDARD_REQUIRED ON)
|
||||
else()
|
||||
project(xenia LANGUAGES C CXX)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
@@ -52,6 +58,8 @@ set(CMAKE_STATIC_LINKER_FLAGS_CHECKED "${CMAKE_STATIC_LINKER_FLAGS_DEBUG}" CACHE
|
||||
# Platform name for output paths
|
||||
if(WIN32)
|
||||
set(XE_PLATFORM_NAME "Windows")
|
||||
elseif(APPLE)
|
||||
set(XE_PLATFORM_NAME "macOS")
|
||||
else()
|
||||
set(XE_PLATFORM_NAME "Linux")
|
||||
endif()
|
||||
@@ -178,7 +186,7 @@ else()
|
||||
)
|
||||
|
||||
# Clang-specific C++ warnings
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
add_compile_options(
|
||||
$<$<COMPILE_LANGUAGE:CXX>:-Wno-deprecated-register>
|
||||
$<$<COMPILE_LANGUAGE:CXX>:-Wno-deprecated-volatile>
|
||||
@@ -216,7 +224,23 @@ else()
|
||||
$<$<COMPILE_LANGUAGE:C>:-Wno-implicit-function-declaration>
|
||||
)
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
if(APPLE)
|
||||
# macOS-specific settings
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "15.0" CACHE STRING "Minimum macOS version")
|
||||
add_compile_options(
|
||||
$<$<COMPILE_LANGUAGE:CXX>:-Wno-shorten-64-to-32>
|
||||
-Wno-deprecated-declarations
|
||||
-Wno-character-conversion
|
||||
)
|
||||
add_link_options(-Wl,-no_warn_duplicate_libraries)
|
||||
link_libraries(
|
||||
"-framework CoreFoundation"
|
||||
"-framework Foundation"
|
||||
"-framework IOKit"
|
||||
dl
|
||||
pthread
|
||||
)
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
# GTK3 via pkg-config
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(GTK3 REQUIRED gtk+-x11-3.0)
|
||||
|
||||
@@ -48,7 +48,9 @@
|
||||
|
||||
// Available graphics systems:
|
||||
#include "xenia/gpu/null/null_graphics_system.h"
|
||||
#if !XE_PLATFORM_MAC
|
||||
#include "xenia/gpu/vulkan/vulkan_graphics_system.h"
|
||||
#endif
|
||||
#if XE_PLATFORM_WIN32
|
||||
#include "xenia/gpu/d3d12/d3d12_graphics_system.h"
|
||||
#endif // XE_PLATFORM_WIN32
|
||||
@@ -401,7 +403,9 @@ std::unique_ptr<gpu::GraphicsSystem> EmulatorApp::CreateGraphicsSystem() {
|
||||
#if XE_PLATFORM_WIN32
|
||||
factory.Add<gpu::d3d12::D3D12GraphicsSystem>("d3d12");
|
||||
#endif // XE_PLATFORM_WIN32
|
||||
#if !XE_PLATFORM_MAC
|
||||
factory.Add<gpu::vulkan::VulkanGraphicsSystem>("vulkan");
|
||||
#endif
|
||||
std::unique_ptr<gpu::GraphicsSystem> gpu_implementation =
|
||||
factory.Create(gpu_implementation_name);
|
||||
if (!gpu_implementation) {
|
||||
@@ -475,12 +479,9 @@ bool EmulatorApp::OnInitialize() {
|
||||
if (!cvars::portable &&
|
||||
!std::filesystem::exists(storage_root / "portable.txt")) {
|
||||
storage_root = xe::filesystem::GetUserFolder();
|
||||
#if defined(XE_PLATFORM_WIN32) || defined(XE_PLATFORM_LINUX)
|
||||
storage_root = storage_root / "Xenia";
|
||||
#if XE_PLATFORM_ANDROID
|
||||
// TODO(Triang3l): Point to the app's external storage "files" directory.
|
||||
#else
|
||||
// TODO(Triang3l): Point to the app's external storage "files" directory
|
||||
// on Android.
|
||||
#warning Unhandled platform for the data root.
|
||||
storage_root = storage_root / "Xenia";
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
*/
|
||||
|
||||
#include <sys/time.h>
|
||||
#ifdef __APPLE__
|
||||
#include <mach/mach_time.h>
|
||||
#endif
|
||||
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/base/clock.h"
|
||||
@@ -15,6 +18,12 @@
|
||||
namespace xe {
|
||||
|
||||
uint64_t Clock::host_tick_frequency_platform() {
|
||||
#ifdef __APPLE__
|
||||
mach_timebase_info_data_t info;
|
||||
mach_timebase_info(&info);
|
||||
return (uint64_t)((1000000000ull * (uint64_t)info.denom) /
|
||||
(uint64_t)info.numer);
|
||||
#else
|
||||
timespec res;
|
||||
int error = clock_getres(CLOCK_MONOTONIC_RAW, &res);
|
||||
assert_zero(error);
|
||||
@@ -22,14 +31,19 @@ uint64_t Clock::host_tick_frequency_platform() {
|
||||
|
||||
// Convert nano seconds to hertz. Resolution is 1ns on most systems.
|
||||
return 1000000000ull / res.tv_nsec;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t Clock::host_tick_count_platform() {
|
||||
#ifdef __APPLE__
|
||||
return mach_absolute_time();
|
||||
#else
|
||||
timespec tp;
|
||||
int error = clock_gettime(CLOCK_MONOTONIC_RAW, &tp);
|
||||
assert_zero(error);
|
||||
|
||||
return tp.tv_nsec + tp.tv_sec * 1000000000ull;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t Clock::QueryHostSystemTime() {
|
||||
|
||||
@@ -23,6 +23,10 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#if XE_PLATFORM_MAC
|
||||
#include <limits.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#endif
|
||||
|
||||
namespace xe {
|
||||
|
||||
@@ -43,10 +47,26 @@ std::filesystem::path to_path(const std::u16string_view source) {
|
||||
namespace filesystem {
|
||||
|
||||
std::filesystem::path GetExecutablePath() {
|
||||
#if XE_PLATFORM_MAC
|
||||
char path[PATH_MAX];
|
||||
uint32_t size = sizeof(path);
|
||||
if (_NSGetExecutablePath(path, &size) == 0) {
|
||||
char real_path[PATH_MAX];
|
||||
if (realpath(path, real_path)) {
|
||||
return std::string(real_path);
|
||||
}
|
||||
return std::string(path);
|
||||
}
|
||||
return std::string();
|
||||
#else
|
||||
char buff[FILENAME_MAX] = "";
|
||||
readlink("/proc/self/exe", buff, FILENAME_MAX);
|
||||
std::string s(buff);
|
||||
return s;
|
||||
ssize_t len = readlink("/proc/self/exe", buff, sizeof(buff) - 1);
|
||||
if (len != -1) {
|
||||
buff[len] = '\0';
|
||||
return std::string(buff);
|
||||
}
|
||||
return std::string();
|
||||
#endif
|
||||
}
|
||||
|
||||
std::filesystem::path GetExecutableFolder() {
|
||||
|
||||
@@ -146,7 +146,9 @@ void* AllocFixed(void* base_address, size_t length,
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
#ifdef MAP_FIXED_NOREPLACE
|
||||
flags |= MAP_FIXED_NOREPLACE;
|
||||
#endif
|
||||
}
|
||||
|
||||
void* result = mmap(base_address, length, prot, flags, -1, 0);
|
||||
@@ -296,7 +298,7 @@ FileMappingHandle CreateFileMappingHandle(const std::filesystem::path& path,
|
||||
if (ret < 0) {
|
||||
return kFileMappingHandleInvalid;
|
||||
}
|
||||
if (ftruncate64(ret, length) < 0) {
|
||||
if (ftruncate(ret, length) < 0) {
|
||||
close(ret);
|
||||
shm_unlink(full_path.c_str());
|
||||
return kFileMappingHandleInvalid;
|
||||
@@ -335,7 +337,9 @@ void* MapFileView(FileMappingHandle handle, void* base_address, size_t length,
|
||||
|
||||
int flags = MAP_SHARED;
|
||||
if (base_address != nullptr) {
|
||||
#ifdef MAP_FIXED_NOREPLACE
|
||||
flags |= MAP_FIXED_NOREPLACE;
|
||||
#endif
|
||||
}
|
||||
|
||||
void* result = mmap(base_address, length, prot, flags, handle, file_offset);
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
add_library(xenia-gpu-null STATIC)
|
||||
xe_platform_sources(xenia-gpu-null ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_include_directories(xenia-gpu-null PRIVATE
|
||||
${PROJECT_SOURCE_DIR}/third_party/Vulkan-Headers/include
|
||||
)
|
||||
target_link_libraries(xenia-gpu-null PUBLIC xenia-base xenia-gpu xenia-ui xenia-ui-vulkan xxhash)
|
||||
if(APPLE)
|
||||
target_link_libraries(xenia-gpu-null PUBLIC xenia-base xenia-gpu xenia-ui xxhash)
|
||||
else()
|
||||
target_include_directories(xenia-gpu-null PRIVATE
|
||||
${PROJECT_SOURCE_DIR}/third_party/Vulkan-Headers/include
|
||||
)
|
||||
target_link_libraries(xenia-gpu-null PUBLIC xenia-base xenia-gpu xenia-ui xenia-ui-vulkan xxhash)
|
||||
endif()
|
||||
xe_target_defaults(xenia-gpu-null)
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
#include "xenia/gpu/null/null_graphics_system.h"
|
||||
|
||||
#include "xenia/gpu/null//null_command_processor.h"
|
||||
#if !XE_PLATFORM_MAC
|
||||
#include "xenia/ui/vulkan/vulkan_provider.h"
|
||||
#endif
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
namespace xe {
|
||||
@@ -25,9 +27,13 @@ X_STATUS NullGraphicsSystem::Setup(cpu::Processor* processor,
|
||||
kernel::KernelState* kernel_state,
|
||||
ui::WindowedAppContext* app_context,
|
||||
bool with_presentation) {
|
||||
#if XE_PLATFORM_MAC
|
||||
provider_ = nullptr;
|
||||
#else
|
||||
// This is a null graphics system, but we still setup vulkan because UI needs
|
||||
// it through us :|
|
||||
provider_ = xe::ui::vulkan::VulkanProvider::Create(false, with_presentation);
|
||||
#endif
|
||||
return GraphicsSystem::Setup(processor, kernel_state, app_context,
|
||||
with_presentation);
|
||||
}
|
||||
|
||||
6
third_party/CMakeLists.txt
vendored
6
third_party/CMakeLists.txt
vendored
@@ -121,6 +121,12 @@ if(WIN32)
|
||||
discord-rpc/src/connection_win.cpp
|
||||
discord-rpc/src/discord_register_win.cpp
|
||||
)
|
||||
elseif(APPLE)
|
||||
target_sources(discord-rpc PRIVATE
|
||||
discord-rpc/src/connection_unix.cpp
|
||||
discord-rpc/src/discord_register_osx.m
|
||||
)
|
||||
target_link_libraries(discord-rpc PRIVATE "-framework AppKit")
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
target_sources(discord-rpc PRIVATE
|
||||
discord-rpc/src/connection_unix.cpp
|
||||
|
||||
Reference in New Issue
Block a user