Skip to content

Build the core for iOS, tvOS and webOS - #165

Merged
LibretroAdmin merged 8 commits into
libretro:masterfrom
WizzardSK:apple-embedded-pr
Sep 18, 2026
Merged

LibretroAdmin merged 8 commits into
libretro:masterfrom
WizzardSK:apple-embedded-pr

Conversation

@WizzardSK

Copy link
Copy Markdown
Contributor

Three platforms the core can be built for, none of which needed a change to the emulator itself - only to the parts of the build that go looking for things those systems do not have, and to two calls that are not portable across Apple's own SDKs.

There is no desktop GL to find on iOS or tvOS either. find_package(OpenGL REQUIRED) is skipped there the same way it already is on Android: the GL renderer resolves every entry point through the frontend's get_proc_address via glad, so there is nothing to link against - and there is no desktop libGL on those systems in the first place. APPLE_EMBEDDED is decided by system name, because APPLE is true for macOS too.

DEV9: the routing table is a macOS thing, not an Apple one. net/route.h and the PF_ROUTE socket the adapter and DHCP server use to find the gateway are macOS API. iOS and tvOS fall into the existing "Unsupported OS, can't find Gateway" branch instead, which is what every platform without one already does.

arm64: flush the icache with Apple's own call. clang lowers __builtin___clear_cache() to a call to ___clear_cache on iOS and tvOS, and the compiler-rt those SDKs ship does not define it, so the core failed to link with "Undefined symbols for architecture arm64". sys_icache_invalidate() is what the builtin becomes on macOS anyway. The fault handler's task_set_exception_ports() is a debugger convenience and the mach task API is marked unavailable on tvOS, so it is compiled out there.

No IOKit on tvOS. It is the one Apple platform without that framework and nothing in this tree calls into it.

The deployment target. CMAKE_OSX_DEPLOYMENT_TARGET was set unconditionally for every Apple build, so the version a job asked for was overwritten - on iOS that left the core stamped with a minimum of 10.13, which is not a version of that system at all, and the same number decided that aligned allocation was unavailable. It is macOS-only now, and only when the caller did not name one. The iOS job names 12.0: C++17 aligned new and delete come with the iOS 11 runtime and this core uses them.

webOS is another Linux with no desktop GL - the buildroot ships EGL and GLES - so it takes the same route. aarch64 only: the other half of the platform is armv7a, and the recompilers here are x86-64 and arm64.

What was actually run

iOS and tvOS were built against the real SDKs before this was opened, on a macOS 15 runner with the cmake lines of ios-cmake.yml and tvos-cmake.yml expanded by hand, plus this core's CORE_ARGS - the buildbot's Apple runners cannot be reached from a fork. Both produce an arm64 pcsx2_libretro.dylib:

platform IOS    minos 12.0
platform TVOS   minos 12.0

https://github.com/WizzardSK/lrps2-libretro/actions/runs/35264679499

webOS could not be built the same way: that SDK exists only on the buildbot. What was checked is the part of it this changes - configuring with -DWEBOS=ON finds no OpenGL, and the core's link line comes out with no -lGL. If the buildroot toolchain has something else to say, that commit is the one to drop.

JIT on a stock iOS or tvOS device still needs the process to be allowed to map executable pages, which is the same bargain every JIT core on those systems makes and not something a build can fix. These jobs produce a core; what a device lets it do is a separate question.

WizzardSK and others added 8 commits September 17, 2026 21:27
clang lowers __builtin___clear_cache() to a call to ___clear_cache on iOS
and tvOS, and the compiler-rt those SDKs ship does not define it, so the
core failed to link with "Undefined symbols for architecture arm64".
sys_icache_invalidate() is what the builtin becomes on macOS anyway.

The fault handler's task_set_exception_ports() call is a debugger
convenience; tvOS marks the mach task API unavailable, so it is compiled
out there.
tvOS ships no IOKit framework, and the link ended in "framework 'IOKit'
not found". Nothing in this tree calls into it.
Both are arm64 and both take the same path through the renderer that Android
does: no desktop GL to link against, the entry points come from the frontend.

The deployment target went with it. It was set unconditionally for every Apple
build, so the version the job asked for was overwritten - on iOS that left the
core stamped with a minimum of 10.13, which is not a version of that system at
all, and it is also what decided that aligned allocation was unavailable. It is
now macOS-only and only when the caller did not name one. The iOS job names
12.0: C++17 aligned new and delete come with the iOS 11 runtime and this core
uses them.
webOS is a Linux whose buildroot ships EGL and GLES and no desktop GL, so the
two places that look for libGL - the find_package and the link - now leave it
out the way they already do for Android and the Apple embedded systems. The GL
renderer resolves every entry point through the frontend's get_proc_address, so
there is nothing to link there in the first place.

aarch64 only: the other half of the platform is armv7a, and the recompilers
this core has are x86-64 and arm64.

Checked as far as a fork can: configuring with -DWEBOS=ON finds no OpenGL and
the core's link line comes out with no -lGL. The SDK itself only exists on the
buildbot, so the first real pipeline is the first time the toolchain sees this.
The tvOS fix in this branch changed a vendored copy of a RetroArch
file, where the next resync would have silently reverted it and broken
the tvOS job again. It is upstream now, as 68c1b7e, and this takes that
version: the same two guards, written defined-first so they do not
depend on TargetConditionals.h being in scope at the point of use.
Behaviour is identical -- both forms select the same branch on tvOS,
iOS, macOS and non-Apple, checked by preprocessing each.
ClearICacheRange and libretro-common's memsync do the same thing by the
same means -- sys_icache_invalidate on Apple, __builtin___clear_cache
elsewhere on ARM -- and AsmHelpers.cpp in this tree already calls
memsync for it in three places. The three call sites in the two arm64
recompilers call it too, and pcsx2/arm64/ICache.h goes.

The reason the header existed still holds and is upstream's now: clang
lowers the builtin to ___clear_cache on iOS and tvOS, whose compiler-rt
does not define it, and memsync's Apple branch names __aarch64__ beside
__arm__ so those platforms take sys_icache_invalidate instead of
falling through to a data-cache msync.

Both recompilers compile for macOS, iOS, tvOS and Linux arm64 shapes;
the full build links under make and CMake, and all thirteen suites
pass.
@LibretroAdmin
LibretroAdmin merged commit e8c5200 into libretro:master Sep 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants