Skip to content

user_impl_workflow

Francisco Dias edited this page Apr 10, 2026 · 8 revisions

Implementation Workflow

This page explains where you implement your extension logic, how the generated CMake project is intended to be used, and how the workflow differs by target.

extgen generates the bridge code and build system. The extension logic itself always lives in the src/ folder (plus target-specific glue for some platforms).


Project Layout

After running extgen, the folder structure is:

  • code_gen/ - generated bridge code (do not hand-edit)
  • cmake/ - helper scripts (packaging, xcframework, etc.)
  • src/ - your implementation lives here
    • src/CMakeLists.txt - controls which files build per platform
    • src/native/, src/ios/, src/tvos/, etc. - platform implementations
  • third_party/ - optional integration point for SDKs and libraries

The general workflow:

  1. Edit GMIDL to define the public API.
  2. Run extgen to regenerate bindings and the project.
  3. Implement platform behavior in src/.
  4. Build via CMake presets or via IDE toolchains.

Platform Detection Helpers (CMake)

The root CMakeLists.txt provides platform classification booleans:

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()

Use these in src/CMakeLists.txt to control which files compile, which defines are added, and which files belong to each platform.

The following preprocessor defines are set automatically:

Define Platform
OS_SWITCH Nintendo Switch
OS_WINDOWS Windows
OS_ANDROID Android
OS_IOS iOS
OS_TVOS tvOS
OS_PS4 PlayStation 4
OS_PS5 PlayStation 5

iOS / tvOS XCFramework Headers

When building an XCFramework, the packaging step requires a list of public headers. extgen places these variables in src/CMakeLists.txt:

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")

Important

Keep this list correct if you change your src/ios or src/tvos layout. xcodebuild -create-xcframework requires a headers folder; extgen collects these files into that folder during packaging.


Workflow by Target


Android (Java & Kotlin modes)

What gets generated

  • No C/C++ library build
  • Pure Java/Kotlin glue code emitted into the target output folder (default: ../AndroidSource/...)

What you implement

Implement platform behavior in the generated Java/Kotlin layer.

A module-named file is generated:

  • ../AndroidSource/Java/<ModuleName>.java

And an internal interface:

  • ../AndroidSource/Java/code_gen/<ModuleName>Interface.java

Your implementation should implement that interface. When you regenerate, compile errors immediately surface any missing functions.


Native Targets (Desktop, Consoles, JNI, Apple Native)

This applies to: Windows, macOS, Linux, Xbox, PS4/PS5, Nintendo Switch, Android (JNI mode), iOS/tvOS (Native mode).

Where you implement

In src/, typically:

  • src/native/ - shared native implementation
  • src/windows/, src/macos/, etc. - optional platform splits
  • src/ios/, src/tvos/ - platform wrappers if needed

Controlling source selection in CMake

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})

Build output

  • Most targets build a shared library.
  • iOS/tvOS build a static slice that is packaged into an XCFramework.

iOS / tvOS (ObjC, Swift, Native Modes)

The integration into the GameMaker-generated Xcode project is handled automatically via a dedicated CMake build target.

Recommended Workflow (macOS)

1) Run extgen

extgen --config config.json

2) Configure CMake

Run configure via preset or manually. No manual Xcode steps are needed at this stage.

3) Export the GameMaker iOS/tvOS Project

From GameMaker, build for iOS/tvOS with Suppress Run enabled. This generates the Xcode project for the game.

4) Configure the GameMaker Xcode Project Path

In your CMake configuration or preset, set:

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

EXT_GM_XCODEPROJ_OVERRIDE is a FILEPATH cache variable, so CMake expands ~, normalizes the path, and validates it correctly in GUIs and presets.

5) Run the Integration Target

Visual Studio Code
  1. Select configure: iOS: Integrate into GameMaker Xcode project

  2. The edit the build options

  3. Finally select integrate_gamemaker from the drop down menu

  4. Build the project

Command Line Interface
cmake --build <build-folder> --target integrate_gamemaker

This target adds the extension project to the GameMaker Xcode project, creates the required project references, adds the static library dependency, links it into the correct GameMaker target, and handles repeated runs safely (idempotent).

6) Check the GameMaker Xcode Project

The extension will be automatically integrated - build for device or simulator, debug on real hardware, and edit extension source directly from the injected reference.

The integration adds a project reference, not copied files, so edits made in Xcode edit the real extension source.

Typical Iteration Cycle

  1. Edit GMIDL.
  2. Run extgen.
  3. Implement logic in src/.
  4. Export from GameMaker (Suppress Run).
  5. Run the integration target: cmake --build <build-folder> --target integrate_gamemaker
  6. Open Xcode and build/debug.

Re-export from GameMaker, then re-run the integration target whenever the game project changes.

Final Packaging

Visual Studio Code

  1. Select configure (iOS XCFramework) and edit the build options

  2. Select package_ios_xcframework this will create a xcframework

  3. Build your project (builds and zips the framework into the output directory)

Command Line Interface

cmake --build <build-folder> --target package_ios_xcframework
cmake --build <build-folder> --target package_tvos_xcframework

Produces <ExtensionName>.xcframework and a zipped distribution artifact (if configured).


Nintendo Switch / PlayStation 4 / PlayStation 5

Console target setup - SDK paths, environment variables, presets, and output artifacts - is covered in the dedicated Console Setup page.


Summary Table

Target 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
PS4 / PS5 src/ + user-configured SDK paths _ps4.prx / _ps5.prx
iOS/tvOS Native mode src/ + XCFramework packaging XCFramework
iOS/tvOS ObjC/Swift modes src/ + Xcode dev workflow XCFramework

Best Practices

  • Keep core logic platform-agnostic in src/native/. Use platform folders only for wrappers and entry points.
  • Keep src/CMakeLists.txt explicit about which sources compile on which platform.
  • Maintain the XCFramework public header list for Apple targets whenever you change the src/ios or src/tvos layout.
  • For console targets (Switch, PS4, PS5): never commit SDK paths. Always use CMakeUserPresets.json (gitignored). See Console Setup.
  • Use the provided preprocessor defines (OS_SWITCH, OS_WINDOWS, etc.) for platform-specific code.
  • Regenerate often. Compile errors after regeneration indicate which functions need updating - treat them as a checklist.

Clone this wiki locally