Building SpicyRPN Release 2.0.0

SpicyRPN supports iOS/iPadOS 18.0 and later and macOS 15.0 Sequoia and later on compatible Apple-silicon and Intel Macs. Each platform recipe builds GMP 6.3.0, MPFR 4.2.2, and MPC 1.4.1 in that dependency order. The app and both native test targets use the same minimum operating-system versions.

Prerequisites

Download SpicyRPN-2.0.0-source.zip from spicyrpn.com and extract it into a path without spaces. The archive expands to SpicyRPN-2.0.0/. Open Terminal in that source root; all commands below start there.

Use a native Terminal session on a Mac supported by your full Xcode installation, with the required platform SDKs. The selected Xcode and SDK paths must also contain no whitespace. Launch Xcode once to complete setup. The macOS builder accepts native arm64 and x86_64 hosts; the compiler and SDK must support both Mac target architectures for a universal build. If needed, select the intended Xcode for this Terminal session before checking the tools, adjusting the path:

export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer

Check the selected tools:

uname -m
xcode-select --print-path
xcodebuild -version
xcodebuild -showsdks

Expect arm64 on Apple silicon or x86_64 on Intel, and a developer directory inside the intended Xcode application.

The recipes use the system Bash, Make, curl, shasum, tar, patch, and Xcode compiler/SDK tools. No Homebrew GMP, MPFR, or MPC installation is needed. The deployment minimum describes where the built app runs; the Xcode installation may require a newer development Mac operating system.

Sources and deployment settings

The release source ZIP includes the complete GMP, MPFR, and MPC source archives under ThirdParty/. The builder verifies and extracts these pinned archives locally; a complete release source ZIP needs no dependency download. Edits to the expanded ThirdParty/gmp-6.3.0/ or ThirdParty/mpfr-4.2.2/ trees do not affect these builds. To modify a library, use the optional patch directory described in Rebuilding with modified libraries; the builder applies those patches after verified extraction.

The MPC archive is ThirdParty/mpc-1.4.1.tar.xz. If it is absent in a working source tree, the builder checks build/downloads/mpc-1.4.1.tar.xz, then downloads the pinned archive from https://ftp.gnu.org/gnu/mpc/mpc-1.4.1.tar.xz. Its SHA-256 is:

91204cd32f164bd3b7c992d4a6a8ce6519511aadab30f78b6982d0bf8d73e931

A checksum mismatch stops the build. The release packager copies a verified cached MPC archive into ThirdParty/ inside the source ZIP. Dependency archives contain their full sources and upstream license notices. See LICENSING.md and RELEASING.md.

All three pinned SHA-256 values are recorded in ThirdParty/SHA256SUMS.txt and enforced by the shared builder. For a complete release tree with all three archives under ThirdParty/, verify them before building:

(cd ThirdParty && shasum -a 256 -c SHA256SUMS.txt)

All three libraries use the same explicit minimum for their destination:

Environment override Default
MACOSX_DEPLOYMENT_TARGET 15.0
IOS_SIM_DEPLOYMENT_TARGET 18.0
IOS_DEVICE_DEPLOYMENT_TARGET 18.0

Use the defaults for the supported baseline. An exported override changes library compilation, not Xcode's app/test settings. For reproducible defaults in a Terminal that previously set overrides, run this before rebuilding:

unset MACOSX_DEPLOYMENT_TARGET IOS_SIM_DEPLOYMENT_TARGET IOS_DEVICE_DEPLOYMENT_TARGET

Build the libraries for your destinations

Choose the destinations before running their build commands:

Destination Build host and execution
Universal Mac Build on native Apple silicon or Intel with a suitable Xcode SDK. Execute each slice on its matching native Mac.
iOS Simulator, arm64 Build with the iOS Simulator SDK; execute the Simulator app on Apple silicon.
iPhone/iPad, arm64 Build with the iOS device SDK; execute on a supported device with signing configured.

Run only the commands for the destinations you need. Each rebuilds all three libraries, including MPC:

bash Scripts/build-math-macos-universal.sh --clean
bash Scripts/build-math-ios-simulator-arm64.sh --clean
bash Scripts/build-math-ios-device-arm64.sh --clean

Both --clean and -clean are accepted; --help describes the options. Every invocation extracts fresh verified sources and rebuilds the selected destination. The clean option additionally removes older generated library work directories. It retains source archives and the MPC download cache. The universal Mac command rebuilds both architecture slices and merges them. Device, Simulator, and Mac libraries cannot substitute for one another, even when their architecture names match. The iOS device and Simulator recipes remain arm64-only.

The entry scripts share Scripts/lib/build-math.sh. There is no separate MPC build step. Each target installs:

Destination Install prefixes under build/install/
Universal Mac (arm64 + x86_64) gmp-macos-universal/, mpfr-macos-universal/, mpc-macos-universal/
iOS Simulator gmp-ios-simulator-arm64/, mpfr-ios-simulator-arm64/, mpc-ios-simulator-arm64/
iPhone/iPad gmp-ios-device-arm64/, mpfr-ios-device-arm64/, mpc-ios-device-arm64/

Each prefix contains include/ and lib/. Xcode's SDK-specific paths select these installations and link -lmpc -lmpfr -lgmp. Universal Mac libraries contain exactly arm64 and x86_64; their header wrappers select the corresponding generated architecture headers. Intel iOS Simulator libraries are not supplied.

For library development, build-math-macos-arm64.sh and build-math-macos-x86_64.sh build one architecture into the matching macos-arm64 or macos-x86_64 prefixes. They accept the same clean/help options. These thin installs are retained by the universal build, but Xcode uses the merged prefixes. Run the universal builder to refresh both slices and merged outputs after a library change.

Build the app and run tests

Finish the required library builds first. Open the project to select the SpicyRPN scheme, choose a destination whose libraries you built, and configure your signing team before building for a physical device or creating a signed archive:

open SpicyRPN.xcodeproj

Then use Product → Clean Build Folder, followed by Product → Build (Cmd-B) or Run (Cmd-R). Xcode does not run the library scripts automatically, and its clean command does not clean those libraries.

For a clean Mac app build for the current native host:

spicy_mac_arch="$(uname -m)"
xcodebuild clean build -project SpicyRPN.xcodeproj -scheme SpicyRPN \
  -configuration Debug -destination "platform=macOS,arch=$spicy_mac_arch" \
  -derivedDataPath "build/DerivedData-mac-$spicy_mac_arch"

Keep the selected device unlocked and available for automation. The full suite can take hours; see UI-Testing.md for scope and diagnosis. Cmd-U runs both native unit and UI suites. Run both suites on Apple silicon and on a compatible Intel Mac. For a shorter non-UI run, add -only-testing:SpicyRPNTests to the command below; omit it for the complete run:

spicy_mac_arch="$(uname -m)"
xcodebuild test -project SpicyRPN.xcodeproj -scheme SpicyRPN \
  -destination "platform=macOS,arch=$spicy_mac_arch" \
  -derivedDataPath "build/DerivedData-mac-$spicy_mac_arch"

Keep results for each architecture; a successful arm64 run does not establish that the Intel slice executes correctly.

On Apple silicon with Rosetta installed, an available platform=macOS,arch=x86_64 destination can run an additional translated test pass. Confirm it with xcodebuild -project SpicyRPN.xcodeproj -scheme SpicyRPN -showdestinations, then use a separate derived-data directory, such as build/DerivedData-mac-rosetta. This is additional coverage; retain a native Intel test run. Intel cannot execute the arm64 slice.

Rebuilding with modified libraries

The MIT application sources and complete GNU library sources support rebuilding and relinking under LGPLv3 section 4(d)(0). Start with a separate extraction of the release ZIP for experiments. Complete the Xcode/tool setup above and use your own signing team before running an app on a device.

  1. Keep your changes as unified-diff .patch files. Patch paths must have one leading directory to strip, such as a/src/file.c and b/src/file.c, so patch -p1 addresses files relative to the library's source root.
  2. Create the patch directories below, then put each patch in its library's subdirectory. Number multiple patches in application order, such as 01-change.patch and 02-followup.patch. A library with no patches builds unchanged. Keep patch files outside the generated build/math-*, build/install, and old per-library work directories.
mkdir -p build/library-patches/gmp build/library-patches/mpfr build/library-patches/mpc

After saving the patches there, enable them and run only the destination builds you need:

export SPICYRPN_MATH_PATCH_DIR="$PWD/build/library-patches"
bash Scripts/build-math-macos-universal.sh --clean
bash Scripts/build-math-ios-simulator-arm64.sh --clean
bash Scripts/build-math-ios-device-arm64.sh --clean

The builder verifies the original source archives, extracts fresh sources, then applies each library's patches in C-locale filename order before configuring any library. A failed patch stops the build. Both Mac slices receive the same patches. The pinned archives and their checksums remain unchanged, and the patch directory survives clean builds. Native upstream tests and bridge/link checks still run as described below.

Next open SpicyRPN.xcodeproj. For a personal build, select your Apple Account and team in Signing & Capabilities, use bundle identifiers available to your team, and check the app and both test targets. For iPhone/iPad, connect and trust the device and enable Developer Mode when prompted. The manual's Signing and personal runs section covers this setup.

Select the destination whose libraries you rebuilt, choose Product → Clean Build Folder, then Run to relink and launch the app. Run Cmd-U to check the changed build. Library changes are incorporated by linking a new app; rebuilding the libraries alone does not replace an installed application. The app does not need the maintainer's private signing keys for this workflow.

For a command-line Mac rebuild after personal signing is configured:

spicy_mac_arch="$(uname -m)"
xcodebuild clean build -project SpicyRPN.xcodeproj -scheme SpicyRPN \
  -configuration Debug -destination "platform=macOS,arch=$spicy_mac_arch" \
  -derivedDataPath "build/DerivedData-modified-$spicy_mac_arch"

Keep the patch files and build settings with any modified distribution and follow LICENSING.md. To return to the unmodified release, first run unset SPICYRPN_MATH_PATCH_DIR, then rebuild the selected libraries and clean/relink the app again. For a different upstream library version, update archive pins, source directory names, build configuration, and bridge compatibility together; the patch setting operates on the pinned versions.

Archive the universal Mac app

Debug uses the selected active architecture. Release includes both Mac architectures. Complete the universal dependency build, native tests, and signing setup above before archiving the Release configuration:

xcodebuild archive -project SpicyRPN.xcodeproj -scheme SpicyRPN \
  -configuration Release -destination 'generic/platform=macOS' \
  -archivePath build/SpicyRPN-macOS.xcarchive \
  'ARCHS=arm64 x86_64' ONLY_ACTIVE_ARCH=NO
spicy_mac_app=build/SpicyRPN-macOS.xcarchive/Products/Applications/SpicyRPN.app
xcrun lipo -archs "$spicy_mac_app/Contents/MacOS/SpicyRPN"
xcrun lipo -verify_arch arm64 x86_64 "$spicy_mac_app/Contents/MacOS/SpicyRPN"

The release verifier requires Python 3.9 or later and the selected Xcode tools. Run it on the same application bundle:

python3 Scripts/verify-macos-universal.py "$spicy_mac_app"

It checks Release 2.0.0/build 1, the macOS deployment minimum, and both architectures in the main and bundled Mach-O files. Verify the executable in the actual signed archive or exported .app. The lipo check confirms architecture presence, not runtime behavior, signing, or App Store validation. See RELEASING.md for release validation and packaging.

Build checks and troubleshooting

The Mac builds retain GMP's optimized assembly for each architecture. The builder sets CCAS to the selected compiler command plus -c, as required by GMP's compile-only assembly probes and build rules. iOS builds disable GMP assembly.

The recipes check archive architectures, platform metadata, and minimum-OS metadata. They link both the calculator's actual C bridge and an MPC program calling the six complex inverse functions, then check those outputs' platform and minimum OS too. For the Mac slice matching the physical host architecture, the builder runs each library's upstream make check and executes the MPC program. The other Mac slice is compiled and linked without execution. Rosetta is not required for the universal build, and the scripts do not automatically use it for cross-architecture runtime tests. The universal merge validates both library slices and rechecks bridge/MPC linking using the merged headers and libraries. iOS device and Simulator checks also compile/link only; their executables are not run on the host Mac. These checks do not replace native calculator tests.

The minimum-OS check reads the deployment field from its Mach-O load command; embedded linker/tool versions are separate metadata. The following build and release-tool regressions require Python 3.9 or later, Bash, Make, tar, patch, and a C preprocessor (cc or clang). They do not require Xcode or installed math libraries:

bash Scripts/tests/test-math-metadata.sh
python3 Scripts/tests/test-math-builds.py
python3 Scripts/tests/test-macos-release.py

The build-flow test substitutes Apple-tool fixtures while exercising the actual build scripts, dependency ordering, optional patch application to both Mac slices and iOS, header selection, and rejection of invalid slices. These tests check build orchestration and release validation, not compiled Mac numerical behavior.

For missing Mac slices, rebuild with build-math-macos-universal.sh and verify that Xcode uses the macos-universal prefixes. Do not restrict the Mac Release archive to ARCHS=arm64 or ARCHS=x86_64. For missing headers or libraries on another platform, build the destination selected in Xcode. For a wrong-platform link error, rebuild that platform even if the existing archive reports arm64. Start with the first build error and the affected dependency's config.log in the generated work directory. After changing an SDK, deployment target, dependency, or build recipe, rebuild the libraries and clean/relink the app.

Numerical integration

The C bridge transfers MPFR components directly to MPC without conversion through Double or decimal strings. RPN and ALG share MPC arithmetic and elementary functions, with MPFR real-axis shortcuts where applicable. Composite and special-function algorithms retain their own precision and convergence limits; MPC's correctly rounded primitive operations do not make an entire composed calculation correctly rounded. The manual's complex-number chapter and mathematical appendix describe branch conventions and accuracy limits.