Guides Build & Release Export a Current-Platform Build

Build & Release 8 min read Updated Apr 2026

Export a Current-Platform Build

Use this guide when you want to stage a build of your game for the machine and operating system you are developing on.

Lenga's current export flow is straightforward:

  • it stages a current-platform player build
  • on macOS, it creates a one-click .app bundle
  • it runs that packaged player in player mode

Use this workflow when you want a packaged player build for the same platform you are developing on.

Before You Export

Make sure your project has:

  • a valid ProjectSettings/lenga.json
  • a startup scene configured
  • a bootstrap.php
  • a composer.json
  • a populated vendor/ folder

Lenga exports the standard project layout, so if those pieces are missing the export will fail.

Step 1: Open Build Settings

In the editor, open:

Project -> Build Settings...

You can configure:

  • Product Name
  • Version
  • Identifier
  • Build Profile
  • Launch Mode
  • Window Width
  • Window Height
  • Target FPS
  • Frame Rate Cap
  • Icon Path
  • Default Output
  • Minimum macOS
  • Startup Scene
  • Restricted PHP APIs

Product Name

This is the shipping-facing name Lenga uses for the exported build.

It is saved to the root name field in ProjectSettings/lenga.json, and it is also used for things like the exported executable name and export folder naming.

Version

This is the shipping version string stored in ProjectSettings/lenga.json.

Lenga also carries it into the exported build manifest so publish tooling and release checks can inspect it without guessing.

Identifier

This is the application identifier or bundle-style id for the project, such as:

com.lenga.rollerworld

It is saved to the root id field in ProjectSettings/lenga.json and carried into the export manifest.

Build Profile

Lenga supports two export profiles:

  • Development
  • Release

Development is the default. It keeps runtime debug-mode support enabled in the packaged project, which is useful when you want to hand a build to a teammate or test on another machine without losing debug visibility.

Release is opt-in. It disables runtime debugMode in the packaged ProjectSettings/lenga.json and turns off the runtime diagnostics overlay for the exported build.

Launch Mode

This controls how the game window opens when the exported build starts.

Lenga supports:

  • Windowed
  • Bordered Fullscreen
  • Borderless Fullscreen

Use Windowed when you want a normal game window.

Use Bordered Fullscreen when you want the game to open as a maximized window with normal window chrome.

Use Borderless Fullscreen when you want the game to cover the monitor without normal window borders.

Target FPS

This controls the default frame-rate target saved to ProjectSettings/lenga.json.

The default is 60.

Raise it when your game is designed for a higher refresh target. Lower it when you want a more conservative default for menus, slower-paced games, or lower-power hardware.

Frame Rate Cap

This controls whether the packaged game uses the configured Target FPS value or leaves the frame rate uncapped.

When Leave uncapped is enabled, Lenga does not apply the project frame-rate cap at startup. The Target FPS value is still kept in project settings so you can turn the cap back on later without re-entering it.

Window Width and Window Height

These control the default window size saved to ProjectSettings/lenga.json.

Lenga uses these values for normal windowed launches, and it also uses them as the starting size before fullscreen-style launch modes adjust the window.

Icon Path

This is the image the exported build should use when supported by the current platform and build layout.

On macOS, app bundles use .icns icons. If you configure a different image format, the build can still export, but the app bundle icon will not use that image.

Default Output

This is the default folder Lenga opens to when you start an export.

If you leave it at the default value, Lenga exports into:

build/dist

Relative paths are resolved from the project root.

When you actually export, Lenga opens a folder picker so you can choose a different destination for that export without rewriting the saved default first.

Minimum macOS

On macOS, this controls the minimum system version written into the exported app bundle.

This setting does not magically make the current engine build compatible with older macOS releases. Export validation still checks the runtime executable and bundled native dylibs, and export fails if any bundled Mach-O artifact requires a newer macOS version than the one you configured.

Startup Scene

This is the scene the packaged player will boot into by default.

If you leave it on First Enabled Scene, Lenga will use the first enabled scene from your build scene list.

Restricted PHP APIs

This build setting controls what happens when Lenga finds project PHP code that references APIs or wrappers player mode blocks.

Default behavior:

  • export stops
  • the Console lists the first reported violations

Override behavior:

  • turn on Allow packaging anyway
  • export continues, but the build is knowingly non-compliant with the default player-mode sandbox

Step 2: Export the Build

You can export in either of two ways:

Project -> Export Current Platform...

or from the Build Settings modal:

Export Current Platform

Before export, Lenga will save the active scene if it is dirty.

Lenga then opens a destination picker so you can choose where the export should be staged for that run.

If the chosen export name already exists, Lenga creates the next numbered sibling instead of trying to replace the older export in place.

Lenga scans your project PHP files for common APIs and wrappers that player mode blocks, such as shell execution, process spawning, FFI, direct socket or cURL calls, and remote wrapper usage like http:// or phar://.

By default, export stops when those references are found. That keeps the shipping path aligned with the actual player-mode sandbox instead of letting a build stage successfully and fail later at runtime.

Those export messages now call out the kind of restriction involved, such as:

  • process execution or unsafe host access
  • outbound networking
  • native code loading
  • remote or special stream wrappers

Step 3: Understand the Output Layout

On macOS, the exported folder looks like this:

build/dist/my-game-macos-dev/
  MyGame.app/
    Contents/
      Frameworks/
        libraylib.550.dylib
        libbox2d.3.dylib
        libssl.3.dylib
        libcrypto.3.dylib
        libiconv.2.dylib
        libxml2.16.dylib
      Info.plist
      MacOS/
        MyGame
      Resources/
        Game/
          Assets/
          ProjectSettings/
          bootstrap.php
          composer.json
          vendor/
          Saved/
  build-manifest.json

Notes:

  • the .app bundle is the launch artifact you double-click
  • the native runtime executable is renamed to match your project and placed inside Contents/MacOS/
  • non-system native dependencies are bundled into Contents/Frameworks/
  • export stages into a clean temporary folder first, then replaces the chosen destination only after validation succeeds
  • the packaged project lives inside Contents/Resources/Game/
  • Lenga writes a build-manifest.json file with metadata like name, version, identifier, profile, platform, launch artifact, project root, executable name, startup scene, sandbox profile, writable root, and the explicit shipped permissions contract
  • the export folder name includes the selected build profile, such as -release or -dev

The packaged runtime can detect the bundled Game/ folder automatically, so it does not need --project passed manually in normal exported use.

Step 4: Know What Player Mode Does

Exported builds automatically run in player mode.

That means the packaged runtime uses a stricter PHP sandbox than your normal editor/development workflow.

Player-mode protections include:

  • disabled process and shell execution
  • disabled dynamic extension loading
  • disabled FFI
  • disabled URL wrappers
  • tighter filesystem confinement
  • an engine-written packaged player marker so exported builds opt into the stricter packaged policy intentionally
  • a packaged include_path narrowed to the exported game root and exported vendor/
  • PHP temp files and PHP error logs redirected into the packaged Game/Saved/
  • bundled default gamepad mappings when an engine or project mapping database is available

The permissions contract recorded in build-manifest.json is:

  • packaged game content is read-only
  • packaged game reads are allowed from the exported Game/ root
  • writes are limited to Game/Saved/
  • Preferences writes stay engine-managed and do not widen general PHP filesystem access
  • outbound networking is denied
  • process and shell execution are denied
  • dynamic extension loading is denied
  • remote and special stream wrappers are denied
  • stream-wrapper registration is denied

If you want the full security model explained in one place, read:

The export workflow blocks by default when it sees common blocked APIs or wrappers in your project code, so you get earlier feedback than a late runtime failure. If you intentionally need to stage a non-compliant build, Build Settings exposes an explicit Allow packaging anyway override.

If a packaged build still reaches a blocked path at runtime, the failure surfaces through normal PHP/runtime error output and the packaged PHP error log under:

MyGame.app/Contents/Resources/Game/Saved/Logs/php-runtime.log

Before export completes, Lenga also validates the staged macOS app bundle for missing packaged files, packaged engine-asset resolution, remaining symlinks, the written sandbox manifest contract, and unresolved external native dylib paths.

In the exported layout, Lenga also marks packaged game content read-only and leaves only:

MyGame.app/Contents/Resources/Game/Saved/

writable for save data, logs, and player-mode temporary files.

Small local settings that use Preferences are written through Lenga's engine-managed per-user preferences location instead of writing directly beside the exported app.

Step 5: Test the Exported Build

After export, run the packaged build directly from the exported folder.

On macOS, double-click:

MyGame.app

Then check:

  • the game boots into the expected startup scene
  • save files and logs are written under Game/Saved/
  • Preferences settings are written through the engine-managed per-user preferences location
  • your project does not rely on blocked PHP features like shell execution
  • gamepads still behave correctly on the packaged build, especially on macOS if you use a controller database file

Limitations

This workflow does not cover:

  • cross-platform export from one machine
  • signing and notarization workflows
  • installers or archive generation
  • a richer permissions manifest
  • DMG generation

This export workflow gives you:

  • a real packaged player build
  • for the current development platform
  • with a practical default-deny PHP sandbox
  • with a one-click macOS .app launch artifact

Use this workflow to validate packaged builds during development and internal testing.

Optional: Ship a Gamepad Mapping Database

Lenga already ships with a bundled SDL controller mapping database and exported builds carry that default forward automatically.

If your project needs to override that default, Lenga can also load a project-specific database:

  • a project-specific path in ProjectSettings/lenga.json
  • the engine-default bundled path at res/input/gamecontrollerdb.txt

Example project setting:

{
  "input": {
    "gamepadMappingsPath": "ProjectSettings/gamecontrollerdb.txt"
  }
}

This is especially useful on macOS, where controller mappings can vary more from one device to another. In most cases, though, you should be able to rely on the engine-shipped default database without any extra setup.