Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/armory3d/armorpaint/llms.txt

Use this file to discover all available pages before exploring further.

project.js is the build manifest for ArmorPaint. When amake runs, it feeds this file to the embedded QuickJS engine, which evaluates it to assemble the full list of C source files, include directories, libraries, preprocessor defines, shaders, and assets that make up the final build. Every platform-specific difference — which GPU backend to compile, which system libraries to link, which defines to set — is expressed as ordinary JavaScript conditional logic inside project.js.

Project API

The Project object is instantiated inside project.js and exposes the following methods:
Adds C source files matching the given glob pattern to the list of files to compile.
project.add_cfiles("sources/*.c");
project.add_cfiles("sources/backends/vulkan_gpu.*");
Adds a directory to the compiler’s include search path.
project.add_include_dir("sources");
project.add_include_dir("sources/libs");
Adds a preprocessor #define that is passed to the compiler for all source files.
project.add_define("IRON_VULKAN");
project.add_define("_POSIX_C_SOURCE=200809L");
Links an external library into the final binary.
project.add_lib("vulkan");
project.add_lib("d3d12");
Registers .kong shader files for compilation by ashader. These are compiled to the appropriate GPU API format at build time.
project.add_shaders("shaders/*.kong");
Bundles asset files into the output data/ directory. The options object accepts a destination template string using {name} as a placeholder for the original filename.
project.add_assets("assets/*", { destination: "data/{name}" });
project.add_assets("assets/licenses/**", { destination: "data/licenses/{name}" });
// Skip embedding for large mesh files
project.add_assets("assets/meshes/*", { destination: "data/meshes/{name}", noembed: true });
Subprojects another project.js file, merging its sources, defines, and assets into the current project.
project.add_project("../base");

Platform Conditionals

The platform global variable is set by amake before evaluating project.js. Source files, defines, and libraries are added conditionally based on its value:
if (platform == "windows") {
    project.add_cfiles("sources/backends/windows_system.*");
    project.add_cfiles("sources/backends/direct3d12_gpu.*");
    project.add_define("IRON_DIRECT3D12");
    project.add_lib("dxguid");
    project.add_lib("Winhttp");
    project.add_lib("dxgi");
    project.add_lib("d3d12");
    project.add_lib("Dwmapi");
}
else if (platform == "linux") {
    project.add_cfiles("sources/backends/linux_system.*");
    project.add_cfiles("sources/backends/vulkan_gpu.*");
    project.add_define("IRON_VULKAN");
}
else if (platform == "macos") {
    project.add_cfiles("sources/backends/macos_system.*");
    project.add_cfiles("sources/backends/metal_gpu.*");
    project.add_define("IRON_METAL");
}
else if (platform == "android") {
    project.add_cfiles("sources/backends/android_system.*");
    project.add_cfiles("sources/backends/vulkan_gpu.*");
    project.add_define("IRON_ANDROID");
    project.add_define("IRON_VULKAN");
}
else if (platform == "wasm") {
    project.add_cfiles("sources/backends/wasm_system.*");
    project.add_cfiles("sources/backends/webgpu_gpu.*");
    project.add_define("IRON_WASM");
    project.add_define("IRON_WEBGPU");
}

Graphics API Defines

Each platform sets exactly one graphics API define that gates the correct backend code throughout the engine sources:
DefinePlatformBackend File
IRON_DIRECT3D12Windowsdirect3d12_gpu.c
IRON_VULKANLinux, Androidvulkan_gpu.c
IRON_METALmacOS, iOSmetal_gpu.m
IRON_WEBGPUWASMwebgpu_gpu.c

Build Flags

The flags object is populated by the paint-level project.js before being passed to base/project.js. Each flag gates optional features:
FlagEffect
flags.with_audioEnables the audio backend (platform-specific: dsound, asound, OpenSLES)
flags.with_gamepadEnables gamepad input (dinput8 on Windows, udev on Linux)
flags.with_d3dcompilerEnables runtime shader compilation on Windows (d3dcompiler, d3d11)
flags.with_nfdEnables the native file dialog library (nfd.c)
flags.with_kongEmbeds the Kong shader compiler for runtime shader compilation
flags.with_physicsEnables the physics simulation library (asim.c)
flags.with_raytraceIncludes pre-compiled raytrace shader assets
flags.with_bc7Enables BC7 texture compression (bc7enc.c)
flags.with_evalEnables the MiniC scripting evaluator
flags.with_pluginsEnables the plugin subsystem
flags.embedEmbeds data files directly into the binary using C23 #embed
flags.idle_sleepEnables sleeping when the application is idle

Repository Structure: Two project.js Files

ArmorPaint uses two project.js files with a clear separation of concerns:
1

base/project.js — The Engine Layer

Defines the Base project containing the iron 3D engine, all platform backends, GPU abstraction, and shared libraries. It does not know anything about ArmorPaint-specific features.
2

paint/project.js — The Application Layer

Defines the ArmorPaint project. It sets all build flags, then calls project.add_project("../base") to pull in the engine as a subproject, and adds ArmorPaint-specific sources, shaders, and assets on top.
The combined build is invoked from the paint/ directory:
cd armorpaint/paint
../base/make --compile
The get_version_code() function inside project.js generates a numeric version identifier in YYMMDD format derived from the current build date. This value is used for Android versionCode and iOS build/version fields in the generated project files.

Build docs developers (and LLMs) love