macOS
macOS Developer Environment Setup
Polyphase builds and runs natively on Apple Silicon (arm64) and Intel (x86_64) Macs. Rendering goes through Vulkan on top of MoltenVK, the window and input layer is native Cocoa, and audio uses CoreAudio. The shipped editor is a universal binary. A source build targets the Mac it runs on unless you set MAC_ARCH (see Architectures).
What to install
Everything not marked optional is required. Polyphase always packages for GameCube, Wii and 3DS, so the devkitPro toolchains are part of the baseline setup, not an extra.
| Install | Needed for | Verify with |
|---|---|---|
Xcode Command Line Tools (clang, make, lipo, codesign) |
Everything | xcode-select -p prints a path |
Homebrew with cmake and python3 |
libgit2 prebuild, asset-stub generator, native addons that ship a CMake project | cmake --version, python3 --version |
| Vulkan SDK 1.4.357.1 (LunarG, macOS) | Editor and every game build: MoltenVK, loader, glslc, shaderc, SPIRV-Cross |
vulkaninfo --summary lists driverName = MoltenVK |
| Rosetta 2 (Apple Silicon only, optional) | Running the Intel slice of a universal build, and cwavtool for 3DS banners |
arch -x86_64 /usr/bin/true |
Homebrew curl (optional) |
wss:// connections from the editor |
ls /opt/homebrew/opt/curl/lib (/usr/local/opt/curl/lib on Intel) |
devkitPro pacman with wii-dev and 3ds-dev |
Packaging for Wii, GameCube and 3DS (the devkitPPC and devkitARM compilers) | powerpc-eabi-g++ --version, arm-none-eabi-g++ --version |
libogc2, libogc2-libdvm, gamecube-tools-git |
Packaging for GameCube (its libraries come from libogc2, not the stock libogc) | ls /opt/devkitpro/libogc2/lib/cube |
makerom, bannertool, cwavtool, pycgfx |
The Nintendo 3DS (CIA) installable target | Packaging a 3DS installable |
Not needed on a Mac: Docker (macOS targets cannot be built in a container, and the console toolchains above run natively), Visual Studio, MSYS2.
Pull Submodules
git submodule update --init --recursive
Download and Install:
- Xcode Command Line Tools (clang, make, lipo, codesign, install_name_tool):
bash
xcode-select --install
A full Xcode install also works. Nothing here uses Xcode projects.
- Homebrew, then the build helpers:
bash
brew install cmake python3
Homebrew lives in /opt/homebrew on Apple Silicon and /usr/local on Intel Macs. The editor looks in both when it spawns build tools.
- Vulkan SDK for macOS version 1.4.357.1 (LunarG). MoltenVK, the Vulkan loader,
glslc,libshaderc_combined.aandlibspirv-cross-core.aall come from this package. Installation steps are in the next section.
Note: cmake is only used to build the bundled libgit2 once (Tools/prebuild_mac.sh) and by native addons that ship a CMake project. The engine itself builds with make.
Note: The system curl on macOS has no WebSocket support, so wss:// connections from the editor need Homebrew's curl: brew install curl and export POLYPHASE_LIBCURL=/opt/homebrew/opt/curl/lib/libcurl.4.dylib (/usr/local/opt/curl/lib/libcurl.4.dylib on Intel Macs). Plain http(s):// works with the system library.
Installing Dependencies
Install Vulkan SDK version 1.4.357.1:
One installer covers both architectures. The SDK's dylibs and static libraries are universal, so the same install serves native, Intel and universal builds.
- Download the macOS SDK from https://vulkan.lunarg.com/sdk/home#mac
- Run the installer (or unzip it and run
vulkansdk-macOS-<ver>.app/Contents/MacOS/vulkansdk-macOS-<ver> --root ~/VulkanSDK/<ver> --accept-licenses --default-answer --confirm-command installfrom a terminal). Install into~/VulkanSDK/<ver>; the editor looks there whenVULKAN_SDKis not set. - Add these to your
~/.zshrc(replace1.4.357.1with the version you installed).VULKAN_SDKmust point at themacOSsubdirectory, which holdsinclude/,lib/andbin/:
export VULKAN_SDK=$HOME/VulkanSDK/1.4.357.1/macOS
export PATH=$VULKAN_SDK/bin:$PATH
export VK_ICD_FILENAMES=$VULKAN_SDK/share/vulkan/icd.d/MoltenVK_icd.json
export VK_DRIVER_FILES=$VULKAN_SDK/share/vulkan/icd.d/MoltenVK_icd.json
export VK_ADD_LAYER_PATH=$VULKAN_SDK/share/vulkan/explicit_layer.d
The SDK ships the same thing as ~/VulkanSDK/<ver>/setup-env.sh; source it instead if you prefer. The make commands below need VULKAN_SDK exported in the shell they run from. A shell that skipped ~/.zshrc (an SSH session, a CI runner, a script started from Finder) must export it explicitly.
Note: the release workflow's build-mac job installs this same version through .github/actions/install-vulkan-sdk-mac (engine-repo mirror first, LunarG CDN fallback). Bumping the SDK version here means bumping that action's default and the actions/cache key in .github/workflows/release.yml too. Uploading the unmodified vulkansdk-macos-<ver>.zip as an asset on a vulkan-sdk-<ver> GitHub Release makes CI independent of LunarG cycling old SDKs off their CDN.
- Close and reopen your terminal (or run source ~/.zshrc)
- Verify the driver is visible:
bash
vulkaninfo --summary | grep -E "deviceName|driverName"
Expect driverName = MoltenVK and your GPU as deviceName. which glslc should print a path inside the SDK.
Note: VK_ICD_FILENAMES / VK_DRIVER_FILES are only needed for the editor binary you build from source. A packaged .app carries its own MoltenVK and ICD manifest under Contents/Resources/vulkan/icd.d, and the editor also fills these in itself at startup when it finds an SDK under ~/VulkanSDK (or the path set in Preferences > External > Vulkan SDK Root), so a Finder launch works without a shell environment.
Install devkitPro toolchains
Required: Polyphase packages for GameCube, Wii and 3DS, and the editor's Build Dependencies window flags whichever of these it cannot find. It also sets DEVKITPRO, DEVKITPPC and DEVKITARM itself when /opt/devkitpro exists, so an editor started from Finder works without shell exports.
| Target | Needs |
|---|---|
| Wii | devkitPro pacman + wii-dev (devkitPPC, libogc, wiiload) |
| GameCube | devkitPro pacman + wii-dev (for the devkitPPC compiler) + libogc2, libogc2-libdvm, gamecube-tools-git |
| Nintendo 3DS | devkitPro pacman + 3ds-dev (devkitARM, libctru, citro3d, 3dsxtool, smdhtool) |
| Nintendo 3DS (CIA) | 3ds-dev plus the extra tools in Packaging a 3DS installable |
- Install devkitPro Pacman for macOS (https://devkitpro.org/wiki/devkitPro_pacman). Download the
.pkgfrom the devkitPro pacman releases and install it; it supports Intel and Apple Silicon Macs. It creates/opt/devkitproand setsDEVKITPRO,DEVKITPPC,DEVKITARMin/etc/profile.d/devkit-env.sh. - Install the Wii/3DS toolchains (https://devkitpro.org/wiki/Getting_Started). This is required for GameCube too:
wii-devprovides devkitPPC (powerpc-eabi-g++), which the GameCube build compiles with even though its libraries come fromlibogc2in step 3.
bash
sudo dkp-pacman -S wii-dev 3ds-dev
- Restart the terminal so the
DEVKIT*variables are picked up, then checkpowerpc-eabi-g++ --versionandarm-none-eabi-g++ --version. - Install
libogc2, which GameCube builds link against (https://github.com/extremscorner/pacman-packages#readme)
bash
sudo dkp-pacman-key --recv-keys C8A2759C315CFBC3429CC2E422B803BA8AA3D7CE --keyserver keyserver.ubuntu.com
sudo dkp-pacman-key --lsign-key C8A2759C315CFBC3429CC2E422B803BA8AA3D7CE
If --recv-keys fails with keyserver receive failed: No route to host (the HKP port 11371 is often blocked), fetch the key over HTTPS and import the file instead:
bash
curl -o ~/Downloads/libogc2-key.asc "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xC8A2759C315CFBC3429CC2E422B803BA8AA3D7CE"
sudo dkp-pacman-key --add ~/Downloads/libogc2-key.asc
sudo dkp-pacman-key --lsign-key C8A2759C315CFBC3429CC2E422B803BA8AA3D7CE
- Add this entry to /opt/devkitpro/pacman/etc/pacman.conf above the existing [dkp-libs] entry. This is file content, not commands. The two Server lines are mirrors of the same repository (pacman falls back to the second if the first is unreachable), and both lines belong in the file:
```ini
[libogc2-devkitpro]
Server = https://packages.libogc2.org/devkitpro/macos/$arch
Server = https://packages.extremscorner.org/devkitpro/macos/$arch
```
-
Then sync and install (accept overwriting if asked):
bash sudo dkp-pacman -Syuu sudo dkp-pacman -S gamecube-tools-git libogc2 libogc2-libdvm -
Check that
ls /opt/devkitpro/libogc2/lib/cubelistslibogc.a.
Note: the
libogc2packages are only the GameCube/Wii libraries.wii-devand3ds-devare the meta-packages that pull in the actual compilers, devkitPPC (powerpc-eabi-g++) and devkitARM (arm-none-eabi-g++). Without them the editor works, but GameCube/Wii/3DS packaging fails partway throughmakewith a missing-compiler error.
Running the result: Wii builds go to a console over the network with wiiload (see Platforms/Wii/Wiiload.md) or into Dolphin. GameCube builds run in Dolphin. 3DS .3dsx files run in Citra/Azahar or from the Homebrew Launcher. Set the emulator paths in Preferences > External > Launchers.
Compile Shaders, libgit2, and Standalone embedded-asset stubs
bash Tools/prebuild_mac.sh
This is the macOS counterpart of Tools/prebuild.sh. It checks that VULKAN_SDK, cmake and the Command Line Tools are present, then runs three steps: builds libgit2 (for the slices MAC_ARCH selects, SecureTransport TLS), compiles shaders with the SDK's glslc, and writes minimal stubs for Standalone/Generated/EmbeddedAssets.{h,cpp}, EmbeddedScripts.{h,cpp}, and AddonPlugins.cpp. The stub step only writes files that are missing. These are gitignored and normally regenerated by the Editor's "Build Data" action, but a fresh clone needs the stubs so the Standalone build succeeds.
Architectures: Apple Silicon, Intel, universal
The Makefiles take a MAC_ARCH variable, on the command line or in the environment:
MAC_ARCH |
Builds | When |
|---|---|---|
native (default) |
This Mac's arch (uname -m: arm64 on Apple Silicon, x86_64 on Intel) |
Day-to-day development |
universal |
arm64 + x86_64 in one binary | What the release .dmg ships. About twice the compile time |
arm64 / x86_64 |
A single slice, cross-compiled if it is not the host's | Testing the other architecture |
MAC_ARCH=universal bash Tools/prebuild_mac.sh # libgit2 must be built for the same slices
make -C Standalone -f Makefile_Mac_Editor -j$(sysctl -n hw.ncpu) MAC_ARCH=universal
Switching MAC_ARCH prints MAC_ARCH arm64 -> universal: cleaning ... lines and rebuilds the affected objects. That is expected, not an error. Which directories get cleaned is described in Platforms/Mac/Overview.md.
Intel Macs need nothing extra: the same Vulkan SDK, Command Line Tools and devkitPro installers work, and native builds x86_64. On Apple Silicon, install Rosetta 2 once (softwareupdate --install-rosetta --agree-to-license) to run the Intel slice of a universal build with arch -x86_64 Standalone/Build/Mac/PolyphaseEditor. A terminal running under Rosetta reports uname -m as x86_64, so native builds Intel there. lipo -archs <binary> shows which slices a file contains.
Build and Run the Editor
VS Code: open the repo root, install the C/C++ Extension Pack, and pick Polyphase Editor - Mac in Run and Debug (it runs the Make Standalone Editor - Mac task, then launches under lldb with the repo root as the working directory). Polyphase Game - Mac does the same for the runtime.
Terminal:
- From the repo root:
cd Standalone - Run
make -f Makefile_Mac_Editor -j$(sysctl -n hw.ncpu) - Go back to the root directory
cd .. - Run
Standalone/Build/Mac/PolyphaseEditor. As on Linux, run it from the repo root soEngine/AssetsandEngine/Shadersresolve. A copy of the binary is also placed at the repo root after every build.
The game runtime used by packaging is built the same way: make -f Makefile_Mac_Editor is the editor, make -f Makefile_Mac_Game produces Standalone/Build/Mac/Polyphase.macho, which the Packaging window reuses for script-only projects.
Build outputs live under Build/Mac/ and Intermediate/Mac/ next to their Linux siblings. Engine/Makefile_Mac, Standalone/Makefile_Mac_Editor, Standalone/Makefile_Mac_Game, External/Bullet/Makefile_Mac and External/Assimp/Makefile_Mac mirror the Linux makefiles line for line: same targets, same variables, with Apple's clang/ar/ld64 flags (-arch <MAC_ARCH> -mmacosx-version-min=12.0, -Wl,-rpath,@loader_path, -dynamiclib) and the platform sources under Source/{System,Input,Audio,Network,Serial}/Mac.
Keyboard note: the editor's Ctrl-based hotkeys accept the Command key as well (⌘S saves, ⌘Z undoes). F-keys need Use F1, F2, etc. keys as standard function keys in System Settings > Keyboard, or the Fn key.
Packaging a macOS App Bundle
The macOS (App Bundle) build target compiles a Mach-O with Makefile_Mac_Game (slices per the profile's Architecture option: Native, Universal, arm64 or x86_64) and wraps it into Packaged/Mac/<Project>.app with MoltenVK and the Vulkan loader inside Contents/Frameworks. It needs the same tools as building the editor (Command Line Tools + Vulkan SDK); nothing else. macOS targets can only be built on a macOS host. The "Use Docker" option is disabled for them.
Signing: every bundle is at least ad-hoc signed so it runs on the machine that built it. For distribution set Signing Identity (Developer ID Application: ...) in the profile's Target Options, optionally Notarize with a keychain profile created by xcrun notarytool store-credentials, and tick Create .dmg. Details in Platforms/Mac/Packaging.md.
To ship the editor itself, bash Installers/build_app_mac.sh produces dist/Polyphase.app and bash Installers/build_dmg_mac.sh wraps it into dist/PolyphaseEditor-<version>-macos-<universal|arm64|x86_64>.dmg (see Platforms/Mac/Overview.md).
Packaging a 3DS installable (.cia)
The plain Nintendo 3DS build target needs nothing beyond 3ds-dev above. The Nintendo 3DS (CIA) target, which produces an installable HOME Menu title, shells out to tools that devkitPro does not ship. None of them are needed unless you use that target.
| Tool | Needed for | Where it comes from |
|---|---|---|
makerom |
the .cia (required) |
3DSGuy/Project_CTR releases, makerom-v0.19.0-macos_arm64.zip (Intel Macs: the macos_x86_64 zip) |
bannertool |
HOME Menu banner and tune (optional) | No macOS binary is published. Build from source: carstene1ns/3ds-bannertool bannertool-1.2.3.tar.gz, then make and set the path in Preferences > External > Launchers |
cwavtool |
DSP-ADPCM tune encoding (optional, experimental) | PabloMK7/cwavtool releases, cwavtool.zip, use mac-x86_64/cwavtool (runs under Rosetta on Apple Silicon) |
| Python 3.12 + pycgfx | 3D scene banners (optional) | brew install python@3.12 and skyfloogle/pycgfx |
Easiest: in the editor open Preferences > External > Launchers, scroll to 3DS CIA Tools, and click Download makerom + bannertool + cwavtool. makerom and cwavtool are fetched from the release pages above into ~/Library/Application Support/PolyphaseEditor/Tools/3DS, made executable, and picked up immediately (bannertool is skipped with a warning on macOS, see the table). Downloaded binaries are quarantined by Gatekeeper; if one refuses to run, xattr -d com.apple.quarantine <tool>.
Manual: extract the binaries, chmod +x makerom bannertool cwavtool, and either copy them into /opt/devkitpro/tools/bin, put them somewhere on PATH such as ~/.local/bin, or set the path fields in the same Preferences page.
3D banners additionally need Python 3 with pip. Then click Install pycgfx in the same Preferences page (it downloads pycgfx, pinned to a fixed commit, and runs python3 -m pip install --user gltflib pillow). pycgfx has no license file, which is why the editor only fetches it on request and never bundles it.
Details on the target, its options and the HOME Menu limits are in Platforms/3DS/Overview.md.
Where the editor keeps its files
| What | Path |
|---|---|
| Preferences, hotkey and input presets, downloaded tools | ~/Library/Application Support/PolyphaseEditor/ |
Game saves when the project directory is read-only (e.g. inside a .app) |
~/Library/Application Support/<Project>/Saves/ |
| Addon-recovery sentinel | ~/Library/Application Support/Polyphase/ |
Troubleshooting
Failed to find platform surface extension/No physical device found: the Vulkan loader cannot see MoltenVK. ExportVK_DRIVER_FILES(see above) or install the SDK under~/VulkanSDKso the editor can find it by itself.vulkaninfo --summarymust list MoltenVK.ERROR: VULKAN_SDK is not setfromprebuild_mac.shormake: the shell did not load~/.zshrc(SSH, CI, a script). ExportVULKAN_SDK=$HOME/VulkanSDK/<ver>/macOSin that shell.dyld: Library not loaded: @rpath/libvulkan.1.dylib: the editor was linked against aVULKAN_SDKthat has since moved. Rebuild with the currentVULKAN_SDK, or setDYLD_LIBRARY_PATH=$VULKAN_SDK/libfor that run.- Shaders fail to compile in
prebuild_mac.sh:VULKAN_SDKmust containbin/glslc. Check it points at~/VulkanSDK/<ver>/macOS, not the version directory above it. MAC_ARCH ... cleaning ...lines and a long rebuild: you changed the architecture (or a build profile's Architecture option did). The Makefiles discard objects of the other arch on purpose.MAC_ARCH must be native, arm64, x86_64 or universalmeans a typo in the value.ld: ... building for macOS-x86_64 but attempting to link with file built for macOS-arm64: a static library was built before the arch switch. Runbash Tools/prebuild_mac.sh(libgit2) with the sameMAC_ARCH, ormake cleaninStandaloneand rebuild.Validation layers requested (ValidateGraphics=1) but VK_LAYER_KHRONOS_validation is not available: a packaged game (or an editor started from Finder) cannot see the SDK's validation layer. The engine continues without validation instead of aborting. To validate a game, run it from a terminal with the SDK environment exported.ar: ... has no symbolswarnings while building: harmless. Those objects come from sources compiled out on macOS.powerpc-eabi-g++: command not foundwhen packaging for Wii/GameCube (orarm-none-eabi-g++for 3DS):wii-dev/3ds-devare not installed, or the terminal was not restarted after installing devkitPro.dkp-pacman -Qlists what is installed.- GameCube link errors about missing
libogc2: step 3 of the devkitPro section was skipped. The stocklibogcfromwii-devis not enough for GameCube. wss://connections report "no WebSocket support": install Homebrew curl and setPOLYPHASE_LIBCURLas described above.- Gatekeeper blocks a downloaded editor or game: ad-hoc signed builds are not notarized. Right-click > Open once, or
xattr -dr com.apple.quarantine <app>. - Debugging:
lldb Standalone/Build/Mac/PolyphaseEditorfrom the repo root, or VS Code with the CodeLLDB extension pointing at the same binary withcwdset to the repo root.