---
title: "Export for Linux, Windows and macOS"
url: https://recursiveai.org/onegame/cookbook/export-desktop/
description: "Package a C# game for Linux, Windows and macOS with onegame export: NativeAOT where the host allows it, a folder and an archive per target, and a JSON…"
version: "1.2.0"
---

# Export for Linux, Windows and macOS

Package a C# game for Linux, Windows and macOS with onegame export: NativeAOT where the host allows it, a folder and an archive per target, and a JSON report of every file to check in CI.

Desktop exports work for a game made from the NuGet packages, with no engine checkout. An export is always the Release build without the development tools: no live control, no scenario runner, no capture or replay options.

## Linux

```shell
onegame export --target linux
```

```text
exported orchard 1.0.0 for linux-x64 (nativeaot): 6 files, 7614 KiB
  folder:  /tmp/onegame/orchard/export/orchard-1.0.0-linux-x64
  archive: /tmp/onegame/orchard/export/orchard-1.0.0-linux-x64.tar.gz (3684 KiB)
  skipped TestResults/: not a content folder (shipped folders: fonts, art, data)
  skipped shots/: not a content folder (shipped folders: fonts, art, data)
  warning glibc_too_new: Orchard needs glibc 2.38, newer than 2.31 in Steam's Linux runtime (and so on the Steam Deck). Build on an older system, or inside the Steam Linux Runtime SDK: see docs/exporting.md.
```

```text
orchard-1.0.0-linux-x64/
  Orchard                    the NativeAOT program
  run.sh                     starts the program from its own folder, from any current directory
  THIRD-PARTY-NOTICES.txt    always
  art/                       the game's pictures (here the scaffold's ship.png)
  fonts/                     the game's fonts and their licences
```

The program gives the same state hash as the Debug build:

```shell
export/orchard-1.0.0-linux-x64/run.sh --headless --frames 60 --json
```

```text
{"ok":true,"game":"orchard","headless":true,"frames":60,"tick":60,"hash":"2408d99a0aa89d5d","width":1280,"height":720}
```

The archive is a `.tar.gz` with one top folder, sorted entries and a fixed timestamp, so the same folder gives the same archive. The `glibc_too_new` warning only matters for Steam: see [Ship a game for Steam and the Steam Deck](https://recursiveai.org/onegame/cookbook/steam-and-steam-deck/).

## Windows and macOS from a Linux host

NativeAOT links with the target system’s toolchain, so from Linux the Windows and macOS exports are self-contained, trimmed CoreCLR builds, and the export says so:

```shell
onegame export --target win
```

```text
exported orchard 1.0.0 for win-x64 (coreclr-self-contained): 59 files, 25408 KiB
  folder:  /tmp/onegame/orchard/export/orchard-1.0.0-win-x64
  archive: /tmp/onegame/orchard/export/orchard-1.0.0-win-x64.zip (11800 KiB)
  skipped TestResults/: not a content folder (shipped folders: fonts, art, data)
  skipped shots/: not a content folder (shipped folders: fonts, art, data)
  warning not_native_aot: NativeAOT for win-x64 needs a Windows host; this is a self-contained, trimmed CoreCLR build. Run the same command on a matching host for the NativeAOT build.
```

```shell
onegame export --target osx
```

```text
exported orchard 1.0.0 for osx-arm64 (coreclr-self-contained): 61 files, 27000 KiB
  folder:  /tmp/onegame/orchard/export/orchard-1.0.0-osx-arm64
  archive: /tmp/onegame/orchard/export/orchard-1.0.0-osx-arm64.tar.gz (11013 KiB)
  skipped TestResults/: not a content folder (shipped folders: fonts, art, data)
  skipped shots/: not a content folder (shipped folders: fonts, art, data)
  warning not_native_aot: NativeAOT for osx-arm64 needs a Mac with Apple silicon host; this is a self-contained, trimmed CoreCLR build. Run the same command on a matching host for the NativeAOT build.
  warning not_signed: The bundle was made on a host that is not a Mac, so it is not signed. Apple silicon refuses unsigned programs: sign it on a Mac (codesign --force --sign - <app>).
```

Run the same commands on Windows, or on an Apple-silicon Mac, for NativeAOT builds. On a Mac the bundle `Orchard.app` is signed ad hoc, which lets it run on the Mac that made it; giving it to other people needs a Developer ID signature and notarization from your Apple developer account, which the tool doesn’t do.

`TestResults/` was left by the C# tests and `shots/` by the screenshot tests. Only `fonts/`, `art/` and `data/` are shipped; other folders are listed under `skipped`.

## Options and the JSON report

`--target linux|win|osx` (default: the host’s), `--out <dir>` (default `export/`), `--project <dir|csproj>`, `--no-archive`, `--no-aot`, `--steam`. The version in the names is the project’s `<Version>`, 1.0.0 when unset.

With `--json` the result lists every file with its size and SHA-256, the `runtime` (`nativeaot` or `coreclr-self-contained`), `devTools: false`, what was `skipped` and the `warnings`. Read the warnings in CI: they say why a build isn’t NativeAOT, a font without a licence text (`font_licence_missing`), or a file over 64 MiB (`large_file`).

## Good to know

- Content folders are copied as they are: `fonts/` takes `.ttf .otf` and their licence texts, `art/` takes `.svg .png .jpg .jpeg .psd .webp`, and `data/` takes anything.
- The game finds `fonts/` and `art/` next to the program, so the working directory doesn’t matter. A picture drawn by path (`d.Sprite("art/ship.png", ...)`) is read from there; an export doesn’t watch it for changes.
- The repository’s docs list the C++ toolchain NativeAOT needs: `clang` and `zlib1g-dev` on Linux, the Visual Studio C++ tools on Windows.
- `--live` on an exported program exits 5 with `no_dev_tools`.
- Dedicated servers export with `--server`, for linux-x64 only: see [Client/server sync with a dedicated server](https://recursiveai.org/onegame/cookbook/client-server-sync/).
- Web, Android and iOS: see [Export for the web, Android and iOS](https://recursiveai.org/onegame/cookbook/export-web-android-ios/).

Every detail is in [Exporting](https://recursiveai.org/onegame/docs/exporting/).
