-
Notifications
You must be signed in to change notification settings - Fork 0
user_impl_workflow
This page explains where you implement your extension, how the generated CMake project is intended to be used, and how the workflow differs by target/platform.
extgen generates a multi-platform CMake project, but the extension logic itself is always your responsibility and lives inside the src/ folder (plus target-specific glue for some platforms).
✅ Key idea: extgen generates the bridge + build system, you implement the feature code.
After running extgen, your folder usually looks like:
-
code_gen/→ generated bridge code (do not hand-edit) -
cmake/→ helper scripts (packaging, xcframework, etc.) -
src/✅ → your implementation lives here-
src/CMakeLists.txt✅ → you control which files build per platform -
src/native/,src/ios/,src/tvos/, etc. ✅ → your platform implementations
-
-
third_party/→ optional integration point for SDKs / libraries
The workflow is:
- Edit GMIDL → defines the public API
- Run extgen → regenerates bindings + project
- Implement platform behavior in
src/ - Build via CMake presets (or via IDE toolchains)
The root CMakeLists.txt provides platform classification booleans like:
set(EXTGEN_IS_IOS FALSE)
set(EXTGEN_IS_TVOS FALSE)
set(EXTGEN_IS_APPLE_MOBILE FALSE)
set(EXTGEN_IS_PS4 FALSE)
set(EXTGEN_IS_PS5 FALSE)
set(EXTGEN_IS_SWITCH FALSE)
if(EXTGEN_PLATFORM_SWITCH)
set(EXTGEN_IS_SWITCH TRUE)
endif()
if(APPLE)
if(CMAKE_OSX_SYSROOT MATCHES "iphone")
set(EXTGEN_IS_IOS TRUE)
set(EXTGEN_IS_APPLE_MOBILE TRUE)
elseif(CMAKE_OSX_SYSROOT MATCHES "appletv")
set(EXTGEN_IS_TVOS TRUE)
set(EXTGEN_IS_APPLE_MOBILE TRUE)
endif()
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "ORBIS")
set(EXTGEN_IS_PS4 TRUE)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Prospero")
set(EXTGEN_IS_PS5 TRUE)
endif()You can use these in src/CMakeLists.txt to decide what to compile, which defines to add, and which files belong to each platform.
Additionally, the following preprocessor defines are automatically set:
-
OS_SWITCH- Nintendo Switch builds -
OS_WINDOWS- Windows builds -
OS_ANDROID- Android builds -
OS_IOS/OS_TVOS- Apple mobile platforms
These defines control platform-specific behavior in generated code (export macros, platform APIs, etc.).
When building an XCFramework, we must tell the packaging step which public headers to include.
In your src/CMakeLists.txt, extgen places something like:
set(EXT_PUBLIC_HEADERS_IOS
"${CMAKE_SOURCE_DIR}/src/ios/${PROJECT_NAME}_ios.h;${CMAKE_SOURCE_DIR}/code_gen/ios/${PROJECT_NAME}Internal_ios.h"
CACHE STRING "Semicolon-separated list of public headers to embed in the iOS xcframework")
set(EXT_PUBLIC_HEADERS_TVOS
"${CMAKE_SOURCE_DIR}/src/tvos/${PROJECT_NAME}_tvos.h;${CMAKE_SOURCE_DIR}/code_gen/tvos/${PROJECT_NAME}Internal_tvos.h"
CACHE STRING "Semicolon-separated list of public headers to embed in the tvOS xcframework")✅ You must keep this list correct if you change your src/ios or src/tvos layout.
Why this matters:
xcodebuild -create-xcframeworkrequires a headers folder. extgen collects these files into that folder during packaging.
- No C/C++ library build
- Pure Java/Kotlin glue code emitted into the target output folder (default:
../AndroidSource/...)
You implement the platform behavior in the generated Java/Kotlin layer.
A module-named file is generated, for example:
../AndroidSource/Java/<ModuleName>.java
And an internal interface is generated, for example:
../AndroidSource/Java/code_gen/<ModuleName>Interface.java
✅ Your implementation should implement that interface.
- The interface forces your Java/Kotlin implementation to stay in sync with GMIDL
- When you regenerate, compile errors immediately point to missing functions
📝 Tip: Treat the interface as the “contract.” If GMIDL changes, you update your implementation accordingly.
This applies to:
- ✅ Windows
- ✅ macOS
- ✅ Linux
- ✅ Xbox
- ✅ PS4 / PS5
- ✅ Nintendo Switch (see dedicated section below for setup requirements)
- ✅ Android (JNI mode)
- ✅ iOS/tvOS (Native mode)
In src/, typically organized like:
-
src/native/(shared native implementation) -
src/windows/,src/macos/, etc. (optional splits) -
src/ios/,src/tvos/(platform wrappers if needed)
In src/CMakeLists.txt, you choose which sources compile per platform.
Example pattern:
if(WIN32)
file(GLOB TARGET_SRCS CONFIGURE_DEPENDS "${SRC_DIR}/native/*.cpp" "${SRC_DIR}/windows/*.cpp")
elseif(APPLE)
if(EXTGEN_IS_IOS)
file(GLOB TARGET_SRCS CONFIGURE_DEPENDS "${SRC_DIR}/native/*.cpp" "${SRC_DIR}/ios/*.mm")
elseif(EXTGEN_IS_TVOS)
file(GLOB TARGET_SRCS CONFIGURE_DEPENDS "${SRC_DIR}/native/*.cpp" "${SRC_DIR}/tvos/*.mm")
else()
file(GLOB TARGET_SRCS CONFIGURE_DEPENDS "${SRC_DIR}/native/*.cpp" "${SRC_DIR}/macos/*.mm")
endif()
elseif(ANDROID)
file(GLOB TARGET_SRCS CONFIGURE_DEPENDS "${SRC_DIR}/native/*.cpp")
else()
file(GLOB TARGET_SRCS CONFIGURE_DEPENDS "${SRC_DIR}/native/*.cpp")
endif()
target_sources(${PROJECT_NAME} PRIVATE ${TARGET_SRCS})- Most targets build a shared library
- iOS/tvOS build a static slice that is packaged into an XCFramework
🧩 Tip: If you support many platforms, use one “core” folder (like
src/native/) and keep platform folders thin.
iOS and tvOS development with extgen is designed to:
- ✅ Keep all implementation inside your repository (
src/) - ✅ Allow full Xcode debugging & real-device testing
- ✅ Avoid manual project injection
- ✅ Be repeatable and automation-friendly
The integration into the GameMaker-generated Xcode project is handled automatically via a dedicated CMake build target.
Generate bindings and project files from GMIDL:
extgen --config config.jsonRun configure (via preset or manually). This prepares the extension project and build targets.
You do not need to manually open or inject anything into Xcode.
From GameMaker:
- Build for iOS/tvOS
- Enable Suppress Run
This generates the Xcode project for the game.
In your CMake configuration (or preset), set:
# =============================================================================
# GameMaker iOS integration (optional)
# =============================================================================
set(EXT_GM_XCODEPROJ_OVERRIDE
"~/GameMakerStudio2/GM_IOS/YourGame/YourGame/YourGame.xcodeproj"
CACHE FILEPATH "" FORCE)
set(EXT_GM_APP_TARGET_OVERRIDE "" CACHE STRING "" FORCE)| Variable | Purpose |
|---|---|
EXT_GM_XCODEPROJ_OVERRIDE |
Path to the GameMaker-generated .xcodeproj
|
EXT_GM_APP_TARGET_OVERRIDE |
Optional override for the app target name |
Because EXT_GM_XCODEPROJ_OVERRIDE is a FILEPATH, CMake automatically:
- Expands
~ - Normalizes the path
- Validates it properly in GUIs and presets
Instead of manually injecting the extension project into Xcode, run:
cmake --build <build-folder> --target integrate_gamemakerThis target automatically:
- Adds the extension project to the GameMaker Xcode project
- Creates required project references
- Adds the static library dependency
- Links it into the correct GameMaker target
- Safely handles repeated runs (idempotent)
No Xcode UI steps required.
Now open the GameMaker-generated .xcodeproj or workspace.
Your extension is already integrated.
You can:
- Build for device or simulator
- Debug on real hardware
- Use full Xcode tooling
- Edit extension source directly from the injected reference
The integration adds a project reference, not copied files.
That means:
- Editing code inside Xcode edits your real extension source
- No duplicated files
- No manual syncing required
- Clean Git history
Switching between device/simulator is simply a configuration change.
-
Edit GMIDL
-
Run
extgen -
Implement logic in
src/ -
Export from GameMaker (Suppress Run)
-
Run:
cmake --build <build-folder> --target integrate_gamemaker
-
Open Xcode and build/debug normally
If you re-export from GameMaker, simply re-run the integration target.
When ready for distribution:
cmake --build <build-folder> --target package_ios_xcframework
cmake --build <build-folder> --target package_tvos_xcframeworkThis produces:
<ExtensionName>.xcframework- A zipped distribution artifact (if configured)
- No manual Xcode project editing
- Deterministic and repeatable
- CI-friendly
- Safe to re-run after every GameMaker export
- Single source of truth for extension code
- Works cleanly for teams
Nintendo Switch development with extgen is designed around NDA compliance and user-specific SDK configuration.
The extension project is structured to:
- Keep all SDK paths out of version control
- Use MSBuild integration with Nintendo's official props files
- Support out-of-the-box builds once configured
- Generate all required Switch output files (.nro, .nrr, .nrs)
Set the NINTENDO_SDK_ROOT environment variable to your Nintendo SDK installation:
# Windows (PowerShell)
$env:NINTENDO_SDK_ROOT = "D:\Nintendo\NativeSDK20.5.17\NintendoSDK"
# Windows (System Environment Variables - recommended)
# Control Panel → System → Advanced → Environment VariablesAfter running extgen, create CMakeUserPresets.json from the template:
cp templates/CMakeUserPresets.json.template CMakeUserPresets.jsonEdit the file to configure your SDK paths:
{
"version": 6,
"configurePresets": [
{
"name": "switch-paths",
"hidden": true,
"cacheVariables": {
"CMAKE_C_COMPILER": {
"type": "FILEPATH",
"value": "$env{NINTENDO_SDK_ROOT}/Compilers/NintendoClang/bin/clang-cl.exe"
},
"CMAKE_CXX_COMPILER": {
"type": "FILEPATH",
"value": "$env{NINTENDO_SDK_ROOT}/Compilers/NintendoClang/bin/clang-cl.exe"
},
"NINTENDO_SDK_PROPS_PATH": "Build/VcProjectUtility/ImportNintendoSdk.props"
}
}
]
}Note: This file is automatically gitignored and contains user-specific paths only.
# Configure (Debug or Release)
cmake --preset switch-debug
# Build
cmake --build --preset switch-debugOutput files are generated in the build directory and automatically copied to the extension output folder:
-
ExtensionName.nro- Nintendo Relocatable Object (main executable) -
ExtensionName.nrr- Nintendo Relocatable Resource -
ExtensionName.nrs- Debug symbols
The CMake project uses Visual Studio's MSBuild system with Nintendo SDK integration:
- Directory.Build.props is generated from a template during CMake configure
- This props file imports Nintendo SDK configuration from your SDK installation
- MSBuild automatically discovers and applies Nintendo's toolchain settings
- The compiler (clang-cl) and all build tools are provided by the Nintendo SDK
The committed project contains:
- Zero hardcoded Nintendo SDK paths
- Zero Nintendo SDK file structure references
- Only the requirement that users configure their own SDK
The user provides via CMakeUserPresets.json:
- Compiler paths (clang-cl.exe location)
- Props file path (relative to NINTENDO_SDK_ROOT)
Use the OS_SWITCH define for platform-specific behavior:
#ifdef OS_SWITCH
// Nintendo Switch implementation
#elif defined(OS_WINDOWS)
// Windows implementation
#endifThe generated export macros automatically use the correct syntax:
// In generated code - you don't write this
#ifdef OS_SWITCH
#define GMEXPORT extern "C" __attribute__((visibility("default")))
#elif defined(OS_WINDOWS)
#define GMEXPORT extern "C" __declspec(dllexport)
#endif- Edit GMIDL
- Run
extgen - Implement platform behavior in
src/ - Build:
cmake --build --preset switch-debug - Test the generated
.nrofile on devkit
The three output files (.nro, .nrr, .nrs) are automatically copied to your extension folder for packaging.
| Requirement | Description |
|---|---|
| Nintendo SDK | Official Nintendo SDK installed |
| NINTENDO_SDK_ROOT | Environment variable pointing to SDK root |
| CMakeUserPresets.json | User-specific configuration (gitignored) |
| Visual Studio Generator | CMake must use Visual Studio generator (automatic) |
| Windows | Nintendo Switch builds require Windows + VS tooling |
| Target Type | Where You Implement | What You Build |
|---|---|---|
| Android (Java/Kotlin) | Android output folder (../AndroidSource/...) |
No native lib |
| Desktop + Consoles + JNI |
src/ via CMakeLists |
Shared library |
| Nintendo Switch |
src/ + user-configured SDK paths |
.nro + .nrr + .nrs |
| iOS/tvOS Native mode |
src/ + XCFramework packaging |
XCFramework |
| iOS/tvOS ObjC/Swift modes |
src/ + Xcode dev workflow |
XCFramework (final) |
- ✅ Keep core logic platform-agnostic (
src/native/) - ✅ Use platform folders only for wrappers/entry points
- ✅ Keep
src/CMakeLists.txtclean and explicit - ✅ Always maintain the XCFramework public header list for Apple targets
- ✅ For Nintendo Switch: never commit SDK paths - always use
CMakeUserPresets.json(gitignored) - ✅ Use preprocessor defines (
OS_SWITCH,OS_WINDOWS, etc.) for platform-specific code - ✅ Regenerate often — treat “compile errors after regeneration” as your update checklist
GameMaker 2026