Milestro's native library is built with CMake. Binding generation, Unity plugin packaging, and C# source formatting are handled by Gradle.
The normal CMake flow also prepares the native third-party dependencies needed by Milestro. No separate Skia build step is required for a standard local build.
- CMake 3.26 or newer.
- A C++20 compiler.
- Ninja, Python 3, and Git for third-party dependency setup, plus a CMake generator suitable for the target platform.
- Java/Gradle for
h2csbinding generation and Unity plugin packaging. - Optional:
clang-formatfor generated binding formatting. - Optional:
dotnet formatfor C# formatting.
Apple builds also enable Swift, Objective-C, and Objective-C++. Swift 5.9 or newer is required because the CMake project checks for Swift C++ interop support.
Milestro: native library used by Unity.MilestroCli: CLI executable, enabled by default withMILESTRO_ENABLE_CLI=ON.H2CS: regenerates C# and iOS bridge bindings from the exported game API.milestro_unity_plugin: runs the Gradle Unity plugin packaging task.- Native tests:
MilestroTest_ReadFont,MilestroTest_ReadImage,MilestroTest_Icu,MilestroTest_SkiaUnicodeFallback,MilestroTest_InputBoxApiSpike, andMilestroTest_InputBox.
Configure and build from the repository root:
cmake -S . -B cmake-build-relwithdebinfo -G Ninja \
-DCMAKE_BUILD_TYPE=RelWithDebInfo
cmake --build cmake-build-relwithdebinfo --target MilestroOn the first configure, CMake may download native dependency sources into
ignored paths under ext/. Generated dependency build output stays under the
chosen CMake build directory.
Do not set CMake's global BUILD_SHARED_LIBS; the project intentionally forces
third-party dependencies to static libraries.
| Option | Default | Notes |
|---|---|---|
MILESTRO_BUILD_SHARED_LIBS |
ON |
Builds Milestro as a shared library. |
MILESTRO_BUILD_FRAMEWORK_LIBS |
OFF |
Builds Milestro as an Apple framework when building for iOS. |
MILESTRO_ENABLE_CLI |
ON |
Builds MilestroCli. Turn off for Unity plugin-only builds. |
MILESTRO_ENABLE_TESTS |
ON |
Builds GoogleTest-based native tests. |
MILESTRO_WITH_ADDRESS_SANITIZER |
OFF |
Adds ASan flags for Clang builds. |
MILESTRO_ENABLE_RELEASE_SYMBOLS |
ON |
Keeps debug info in release-style builds for split symbol packages. |
MILESTRO_REMAP_SOURCE_PATHS |
ON |
Remaps absolute source/build paths in debug info. |
MILESTRO_ENABLE_ANDROID_VULKAN_RENDER |
ON |
Android only: requires API 24+ and Vulkan. Set OFF for an API 23 GLES-only build. |
MILESTRO_ENABLE_DESKTOP_OPENGL_RENDER |
OFF |
Enables the experimental Unity OpenGLCore RenderTexture backend on desktop Linux. |
MILESTRO_ENABLE_DESKTOP_VULKAN_RENDER |
OFF |
Enables the experimental Unity Vulkan RenderTexture backend on desktop. |
MILESTRO_UNITY_PLUGIN_OUTPUT_DIR |
unset | Optional output directory for the milestro_unity_plugin target. Defaults to <build-dir>/unity-plugin. |
Build and run tests from a configured tree:
cmake --build cmake-build-relwithdebinfo
ctest --test-dir cmake-build-relwithdebinfo --output-on-failureThe non-Android tests copy tests/data into the runtime output directory.
ICU-related tests use ext/icu-cmake/common/icudtl.dat.
Full Android device test execution is still manual. The Android build workflow runs dependency-free backend configuration checks, NDK header/ABI compilation for arm64 and ARMv7, and host-side platform contract tests. These do not validate GPU rendering. See Android for commands and the device acceptance matrix.
./scripts/build-android-unity.ps1 `
-UnityRoot 'D:\UnityHub\Editor\6000.3.7f1' -RunContractTests -PackageUnityThis selects that installation's SDK/NDK/JDK, defaults to ARM64 / API 26 with
Vulkan and GLES, enables flexible page-size linking, and packages matching
native/C#/ICU files. See docs/android.md for toolchain results and
tests/android_unity/README.md for isolated Demo APK validation. The helper
restores its process environment and supports -GlesOnly -ApiLevel 23 and
-ConfigureOnly for separate native GLES-only configurations.
When include/Milestro/game/milestro_game_interface.h changes, regenerate the
Unity binding files:
./gradlew h2csor through a configured CMake build:
cmake --build cmake-build-relwithdebinfo --target H2CSThis updates:
apps/unity-plugins/Milestro/Binding/BindingC.csapps/unity-plugins/Milestro/Plugins/iOS/FrameworkBinding.cpp
The generated iOS bridge is written under the Unity plugin tree. That plugin tree is used as generated/local build output; generated native plugin content is not tracked by git in the current repository state.
clang-format is optional. The Gradle task skips generated binding formatting if
it is not installed.
Format C# files under apps/unity-plugins:
./gradlew formatThis uses dotnet format when available.
Package the Unity asset tree with Gradle:
./gradlew packageUnityPluginThe default output is:
build/unity-plugin/
Override it with:
./gradlew packageUnityPlugin -PmilestroUnityPluginOutputDir=/path/to/outputor through CMake:
cmake --build cmake-build-relwithdebinfo --target milestro_unity_pluginSet MILESTRO_UNITY_PLUGIN_OUTPUT_DIR at configure time to choose the CMake
target's output directory. The output directory must be dedicated to this
package: every package run validates the path and completely rebuilds the
directory before copying files. On first use, the destination must be absent or
empty; clear a pre-existing non-empty directory before adopting it. Later runs
verify task ownership before rebuilding the directory. Existing package outputs
created before ownership validation must therefore be cleared once. Project/
source roots, their unsafe ancestors, source descendants, and a symbolic link
used as the output directory are rejected.
The package task uses an explicit release-root allowlist. It recursively copies
the complete Milestro, Milestro.Editor, Milestro.Experimental,
Milestro.InputSystem, and Resources directories, plus each selected root's
existing top-level .meta file. It does not package Milestro.Tests,
Milestro.InputSystem.Tests, the formatting solution/project, or future unknown
top-level entries until the allowlist is intentionally extended and reviewed.
Packaging also generates:
Resources/Milestro/icudtl.dat.bytes
from:
ext/icu-cmake/common/icudtl.dat
Every packageUnityPlugin run performs a structural verification after the
output rebuild and copy. The output file set must exactly equal the recursively
expanded release roots and their top-level metadata plus the generated ICU
asset; missing entries and unexpected or stale files fail the task. The verifier
also rejects metadata files without GUIDs and duplicate GUIDs.
Run the verifier directly with:
./gradlew verifyUnityPluginPackageThe task does not compile native platform binaries. Any native binaries or
generated iOS bridge files that already exist under
apps/unity-plugins/Milestro/Plugins/ are copied as part of the Milestro
asset tree.
For Unity integration, place the built native binary under the Unity plugin assets. In this repository those paths are under:
apps/unity-plugins/Milestro/Plugins/
That directory is treated as generated/local plugin output. Generated platform binaries and generated iOS bridge files under it are ignored by git.
The managed bindings expect:
- Non-iOS:
DllImport("libMilestro") - iOS player builds:
DllImport("__Internal")with theFrameworkBindingentry-point prefix
If you use packageUnityPlugin, the ICU Unity TextAsset is generated into the
package output automatically. If you use apps/unity-plugins directly, create
the file at:
apps/unity-plugins/Resources/Milestro/icudtl.dat.bytes
Copy it from:
ext/icu-cmake/common/icudtl.dat
The copied .bytes asset is ignored by git.
This section covers the current Windows build flow.
Run commands from a Visual Studio x64 Developer PowerShell, or make sure
clang-cl, lld-link, CMake, Ninja, and the Windows SDK tools are on PATH.
Build Milestro from the repo root:
cmake -S . -B cmake-build-nocli-debug -G Ninja `
-DCMAKE_BUILD_TYPE=Debug `
-DCMAKE_C_COMPILER=clang-cl `
-DCMAKE_CXX_COMPILER=clang-cl `
-DMILESTRO_ENABLE_CLI=OFF
cmake --build cmake-build-nocli-debug --target MilestroBuild Milestro from the repo root:
cmake -S . -B cmake-build-nocli-relwithdebinfo -G Ninja `
-DCMAKE_BUILD_TYPE=RelWithDebInfo `
-DCMAKE_C_COMPILER=clang-cl `
-DCMAKE_CXX_COMPILER=clang-cl `
-DMILESTRO_ENABLE_CLI=OFF
cmake --build cmake-build-nocli-relwithdebinfo --target Milestro