-
Notifications
You must be signed in to change notification settings - Fork 2
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)
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.
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
- ✅ Switch
- ✅ 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.
This is the most “IDE-assisted” workflow because you often want:
- Xcode autocomplete & debugging
- Real-device testing
- A workflow that builds inside the GameMaker iOS pipeline
This approach keeps everything editable in VS Code, but testable in Xcode.
Generate the project from GMIDL:
extgen --config config.jsonUse your preset and run configure only.
This generates an Xcode project for the extension (or other Apple project files depending on your setup).
From GameMaker, build iOS with “Suppress Run” enabled.
✅ This generates the Xcode workspace/project for the game.
You should now be in Xcode with the game project.
In Xcode:
- Right click the workspace / project navigator
- Add Files to…
- Select the Xcode project generated by extgen for your extension
✅ Now your extension project is visible alongside the game.
In Xcode:
- Select the game target
- Go to General
- Under Frameworks, Libraries, and Embedded Content
- Click +
- Add your extension static library target
✅ Now the game links your extension during iOS builds.
- You can iterate rapidly using Xcode + real device debugging
- Your extension sources remain in your repo and are editable in VS Code
- When you’re done, you can still use extgen + CMake to package the final XCFramework
Once the implementation is done:
-
Run the CMake build preset that triggers:
package_ios_xcframeworkpackage_tvos_xcframework
This produces the final .xcframework (and zip if configured).
| 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 |
| 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
- ✅ Regenerate often — treat “compile errors after regeneration” as your update checklist
GameMaker 2026