Skip to content

fix(kernel): build the param.json parser with libc++ before macOS 26 - #5041

Merged
oneandonlydean merged 1 commit into
boykopovar:mainfrom
mariobob:fix/param-json-number-libcxx
Oct 14, 2026
Merged

oneandonlydean merged 1 commit into
boykopovar:mainfrom
mariobob:fix/param-json-number-libcxx

Conversation

@mariobob

Copy link
Copy Markdown
Contributor

What

Since #4558 the relinker-only build no longer compiles on macOS 15. ParamJsonParser.cpp converts JSON numbers with floating-point std::from_chars, which Apple's libc++ marks unavailable below a macOS 26 deployment target:

core/libs/prx/libkernel/AppMetadata/src/ParamJsonParser.cpp:234:33: error: 'from_chars' is unavailable: introduced in macOS 26.0

Both relinker and param_json_utf8_tests include that file, so the build stops there. CI does not see it because the macos-latest relinker job now runs on macOS 26.6, where the deployment target already satisfies the annotation.

The conversion moves into parseJsonNumberValue:

  • Where the standard library defines __cpp_lib_to_chars it uses std::from_chars exactly as on main. libstdc++ defines the macro and gates its own floating from_chars declarations on it, so the Linux and Windows builds keep the current code.
  • Otherwise it reads the number through an std::istringstream imbued with std::locale::classic(). libc++ does not define __cpp_lib_to_chars (it is commented out in libc++ 20's <version>), so this is the macOS path. libc++ converts with strtod_l and the C locale, so the result does not depend on LC_NUMERIC or the global C++ locale. libc++ already defines __cpp_lib_format and __cpp_lib_print only when floating-point to_chars is available for the deployment target, so a later version that defines __cpp_lib_to_chars can be expected to gate it the same way.
  • Both paths require the whole number to be consumed and throw number outside supported range in param.json when it does not convert to a double, as before.

A stream is not used everywhere because libstdc++'s generic locale model, which MinGW-w64 uses, switches the process-wide C locale to "C" around each stream conversion, and parseParamJson is reached from ensureTitleLoaded while guest threads run. from_chars stays where it is available.

This follows the same feature-test pattern as AtomicSharedPtr in #4629.

Tested

macOS 15.8 (24H23), Apple M4 Max, Apple clang 17.0.0 with the Xcode 26 SDK (libc++ 20.1), CMake 4.4.3, Unix Makefiles, Release, -DANYPS5_RELINKER_ONLY=ON -DBUILD_TESTING=ON. No title or PS5 hardware needed.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Unblocks: none
  • AI-assisted: yes

Apple's libc++ marks floating-point std::from_chars unavailable below a
macOS 26 deployment target, so the relinker-only build fails on macOS 15
since the JSON number conversion switched to it. Use from_chars where
the standard library defines __cpp_lib_to_chars and otherwise convert
through a stream imbued with the classic locale, which keeps the
conversion independent of the host locale and keeps the full-consumption
and range checks.
@simonbronk

Copy link
Copy Markdown
Contributor

Tested with a newer toolchain than the one above: macOS 27.0.1, Apple silicon, Apple clang 21 with the macOS 27 SDK (libc++ 22.1), CMake 4.4, Ninja, relinker-only Release. This PR (e10d7f1a8) merged into main 18c438b10, built with CMAKE_OSX_DEPLOYMENT_TARGET 15.0 and 27.0:

  • main, target 15.0: fails with the same 'from_chars' is unavailable: introduced in macOS 26.0 for relinker and param_json_utf8_tests. Target 27.0 builds and passes 146/146.
  • This PR: both targets build and pass 146/146. fr_FR locales are installed, so param_json_utf8 runs the comma-decimal check.
  • libc++ 22.1 still does not define __cpp_lib_to_chars at any of these targets, so the stream path is the one taken on macOS here too.

AI-assisted: yes (Claude Code).

@oneandonlydean oneandonlydean self-assigned this Oct 14, 2026
@oneandonlydean
oneandonlydean merged commit e2cd213 into boykopovar:main Oct 14, 2026
2 checks passed
@mariobob
mariobob deleted the fix/param-json-number-libcxx branch October 14, 2026 06:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants