Overlay ports — rationale
Full documentation for the vcpkg overlay ports in ports/ (wired via VCPKG_OVERLAY_PORTS in CMakePresets.json). The prose lives HERE, not in the port directories: vcpkg hashes every byte of a port dir into the port's ABI hash, so editing a README inside ports/<name>/ forces a full rebuild of that port on every triplet (macOS + iOS + Android). Keep the in-port READMEs to a single pointer line and batch any real port edits (see "Build speed" in CLAUDE.md).
For the supply-chain view — how the whole dependency closure is pinned (one vcpkg commit), which single-file asset parsers are vcpkg-managed vs. vendored in-tree, and the SHA-pinning of the GitHub Actions (and how to re-pin on a version bump) — see vendored-libs.md.
ports/ogre
Overlay of the upstream vcpkg ogre port, repinned from the v14.5.2 release tag to master commit 63c5e68c8200bb58044434ff0348067bcf733fa6 (2026-07-22, declares itself 14.6.0; version-date in the port's vcpkg.json) - the first reviewed pin that CONTAINS all EIGHT of our merged upstream PRs: the Metal/Vulkan trio (OGRECave/ogre #3667/#3668/#3669, merged 2026-07-07/08), the classic-master build/runtime fixes (#3673 zip fallback, #3674 null manualRender, #3675 Android cpufeatures, merged 2026-07-17) and the two Assimp animation-import fixes (#3680 keyframe predecessor + interpolation units, #3681 stray-scale-key times + keyless-track bind-pose fallback, merged 2026-07-22). Each was vendored as an overlay patch the day it went upstream and DROPPED here at this pin bump once it merged - the standing lifecycle. No release tag carries them yet; move the REF back to a release tag when one does. The pin moves like ogre-next's: a reviewed bump, full-suite verified, never implicit. Enabled from the root vcpkg.json. Delete this overlay if upstream ever grows equivalent features. Local additions:
-
metalfeature (OGRE_BUILD_RENDERSYSTEM_METAL=ON, Apple platforms) soRenderSystem_Metal is available next to GL3Plus - the upstream port has no way to enable it. The exported target carries its include dirs since our merged #3667 - the former
metal-export-include-dirs.patchis consumed from upstream via the pin. -
vulkanfeature (OGRE_BUILD_RENDERSYSTEM_VULKAN=ON+OGRE_BUILD_PLUGIN_GLSLANG=ON, deps: vulkan-headers, vulkan-loader, glslang). The VK_EXT_metal_surface window branch (Vulkan RS on macOS/iOS through MoltenVK, incl. VK_KHR_portability_enumeration/subset handling) and the baseRenderSystem::shutdown()call (debug builds aborted on exit with a VMA leak assertion without it) are upstream now - our merged #3669 and #3668, formerly thevulkan-metal-surface.patch/vulkan-shutdown-call-base.patchthis port vendored. MoltenVK itself stays driver-tier from Homebrew (see CLAUDE.md); static MoltenVK packaging into the app bundle is handled separately (see the feature description in vcpkg.json). One patch remains:-
vulkan-vcpkg-deps.patch- vcpkg-only: resolve vulkan-headers/glslangthrough their CMake configs and re-export them from OGREConfig.cmake.
-
-
Five former upstream-candidate patches were CONSUMED at the 2026-07-22 pin
bump, their PRs having merged into the range this REF spans - they now come from upstream through the pin, exactly like the Metal/Vulkan trio above:
zip-entry-open-nonstrict.patch(#3673: master's non-strictZipArchive::openfallback called a three-argumentzip_entry_openthe bundled zip library does not declare; upstream CI builds strict and preprocessed the branch out, this port builds non-strict), the twinmanual-render-null-renderable.patch(#3674: the GpuParamsDirty refactor dereferenced the null renderable thatmanualRender(RenderOperation*)documents, killing the classicDrawLayer2Dgui/editor surface),cpufeatures-build-interface.patch(#3675: static OgreMain's Android export leaked the internalcpufeaturestarget as a bare-lcpufeaturesno consumer can resolve),assimp-single-key-interpolation.patch(#3680: the Assimp keyframe-neighbour search skipped the immediate predecessor and mixed seconds with ticks in the interpolation factor - single-key channels collapsed to the inverse bind) andassimp-scale-track-fallback.patch(#3681: the Assimp loader keyed stray scale keyframes by the rotation time - garbage times + an OOB read - and fell keyless tracks back to a neutral placeholder instead of the bone's bind pose). Theplayer_character_rig_selfcheckhead-scale/pose legs are the standing proof the two Assimp fixes behave identically arriving from upstream. -
Future upstream-candidate fixes follow the same lifecycle these did: vendor
the patch in the port the same day the PR goes upstream, then drop the patch file at the next reviewed pin bump once it is merged.
-
fix-dependencies.patch(upstream vcpkg patch, locally amended): theOGREConfig.cmake template's
find_dependency(SDL2 CONFIG)is now guarded byif(NOT "@ANDROID@" AND NOT "@EMSCRIPTEN@")- the same condition OGRE's own CMake uses to skip SDL2 there, and the same platforms the port's vcpkg.json excludes the sdl2 dependency on. Without the guard the installed config hard-fails on arm64-android (SDL2 is never installed for it). Upstream-candidate for vcpkg's ogre port. -
ios-ninja-and-install-paths.patch- iOS builds with the Ninja generator(the arm64-ios-simulator triplet): OGRE's iOS branch injects the Xcode generator variable
$(PLATFORM_NAME)into the library output dirs (a literal$(...)in build.ninja, which Ninja rejects) and installs release static libs intolib/Release, breaking the vcpkg layout. Note the companion quirk handled intriplets/arm64-ios-simulator.cmake: OGRE only recognizes iOS throughAPPLE_IOS, which upstream sets exclusively in its own Xcode toolchain file - the triplet passes-DAPPLE_IOS=ONfor this port (plusVCPKG_OSX_ARCHITECTURES arm64, because OGRE pre-seedsCMAKE_OSX_ARCHITECTURES=x86_64beforeproject()).
ports/ogre-next
Locally authored port (pinned master commit ef2e8f35c3ac929b06f67c76cbc80c5577016b30, 2026-07-16, declared as version-date in the port's vcpkg.json; no upstream vcpkg port exists). Master over the v3.0.0 tag by decision: upstream maintains only master (no patch releases since the 2024 tag) and it carries Vulkan hardening the engine wants - device-loss recovery in VulkanRootLayout, an Adreno 6xx workaround - plus it absorbed part of this port's Apple patches (below). The current pin contains our merged OGRECave/ogre-next #582 (the NEON Math/Array include-order fix, merged 2026-07-15), which un-breaks the arm64 Linux build - the linux-debug-sanitize preset in the Linux rig container cold-builds this port natively. The pin moves deliberately (a reviewed bump, full-suite verified, roughly monthly), never implicitly. The Ogre-Next backend of the engine_render facade (Docs/render-abstraction.md); pulled in ONLY by the render-next manifest feature (root vcpkg.json), so classic-only development never builds it. Static, supports: (osx & arm64) | (linux & x64) | (windows & x64 & !uwp) | (ios & arm64) | (android & arm64) - Linux and Windows are the desktop Vulkan flavors (the CI linux-next/windows-next jobs); the iOS (Metal) and Android (Vulkan) halves carry the mobile next backend.
Coexistence with classic ogre in one installed tree is a hard requirement and holds by construction: OGRE_USE_NEW_PROJECT_NAME=ON gives include/OGRE-Next/ headers and libOgreNext*Static.a / libRenderSystem_MetalStatic.a lib names (classic: include/OGRE/, libOgre*.a, libRenderSystem_Metal.a - file-disjoint even for the Metal RS), CMake config + HLMS media live under share/ogre-next/ (classic: share/ogre/). Verified live: a render-next tree (the default macos-debug/macos-release presets) installs both into one vcpkg_installed tree.
Configuration: ONE render system per platform (four-way in the portfile) - Metal on macOS and iOS (first-class on Ogre-Next; the legacy GL3+ 4.1 path buys nothing there), Vulkan on Linux and Android:
-
Linux - XCB windowing; headers/loader from the vcpkg
vulkan-headers/vulkan-loaderports, glslang from theglslangport for the RS's runtime GLSL->SPIR-V compile. The upstream static archive has no link interface, so the shipped config carriesVulkan::Vulkan;glslang::glslang;glslang::SPIRV;xcb;X11-xcb;xcb-randronOgreNext::RenderSystem_Vulkan, andOgreNext::Main's Linux platform libs includeXt;Xaw;Xrandrfor the GLX config dialog compiled into OgreMain; the xcb/Xt/Xaw dev packages come from the system package manager, same rule as classic ogre on Linux. -
Windows - Vulkan with the Win32 window surface (Direct3D stays off -
the render facade drives Vulkan on every non-Apple platform); loader and headers from the vcpkg
vulkan-*ports, glslang from vcpkg; static libs follow the MSVC<name>.liblayout (the shipped config resolves both naming schemes). -
Android - Vulkan with the ANativeWindow surface (no X11/xcb). The Vulkan
loader and headers come from the NDK sysroot (API 28 >= Vulkan 1.1), NOT from vcpkg: Vulkan on a device is driver-tier, the same doctrine as MoltenVK on macOS (a platform-provided driver, not a vendored library).
vulkan-headers/vulkan-loaderstayplatform: linuxin the manifest (vcpkg'svulkan-loaderissupports: !androidanyway); glslang IS a vcpkg dependency here (platform: "linux | android") for the runtime compile. The shipped config carriesVulkan::Vulkan;glslang::glslang;glslang::SPIRV(CMake's built-inFindVulkanresolves the NDK loader intoVulkan::Vulkan). -
macOS / iOS - Metal only,
CMAKE_DISABLE_FIND_PACKAGE_Vulkan=ONforhermeticity. iOS additionally sets
OGRE_BUILD_PLATFORM_APPLE_IOS=ONin the portfile (Ogre-Next's own iOS switch, a plain option upstream never sets from the toolchain - selects the UIKit platform sources and codec set), which keeps thearm64-ios-simulatortriplet untouched. The Metal RS config interface is-framework Metal;-framework AppKit;-framework QuartzCoreon macOS,-framework Metal;-framework QuartzCoreon iOS (no AppKit).
All four also build the NULL render system (headless option), Hlms PBS + Unlit components and rapidjson (a hard OgreMain 3.0 dependency: OgreRootLayout.cpp includes it unconditionally).
Image codec is FreeImage on desktop (decode + encode - screenshots need an encoder). Mobile drops the FreeImage dependency (platform: "!ios & !android" in the manifest, matching the classic mobile flavor) and builds the in-tree STBI codec (OGRE_CONFIG_ENABLE_STBI=ON, decode-only - all device asset loading needs). A screenshot-based device check would have to account for the missing encoder, same as classic mobile.
Silent-disable guard: OGRE_BUILD_RENDERSYSTEM_VULKAN is a cmake_dependent_option gated on Vulkan_FOUND, so a failing Vulkan find-probe would drop the whole RS and STILL let the build complete "successfully" (only a feature-summary log line), surfacing later only as a missing interface include dir in the consumer's generate step. The portfile asserts (FATAL_ERROR) after install, on the Vulkan platforms, that libRenderSystem_VulkanStatic.a and the RenderSystems/Vulkan/include header dir actually landed - failing in the port build instead. (The Linux/Vulkan build is proven end-to-end by the linux-next CI job - it renders the full windowed desktop suite under Mesa lavapipe.)
The Atmosphere component is ON (OGRE_BUILD_COMPONENT_ATMOSPHERE): its AtmosphereNpr is the sky dome + HlmsPbs-integrated object fog + sun-linkage solution the engine_render environment surface wires (RenderWorld::setAtmosphere, Docs/render-abstraction.md). It exports the OgreNext::Atmosphere target (lib OgreNextAtmosphereStatic, headers under include/OGRE-Next/Atmosphere). Its sky material media is installed beside the Hlms templates under share/ogre-next/Media/Atmosphere - only the sky's own files (Atmosphere.material, a trimmed AtmosphereQuad.program in place of the samples' full Quad.program, the AtmosphereNprSky_ps fragment shader + QuadCameraDirNoUV_vs vertex shader per shading language, and the shared Any/AtmosphereNprSky_ps.any include), NOT the whole samples Common material set (which carries unrelated effects + heavyweight LUT .dds files). Two of those files are PORT-DIR copies rather than source-tree copies: AtmosphereQuad.program carries the default_params block the samples' Quad.program binds (worldViewProj + rsDepthRange auto params - without them the sky quad transforms by a zero matrix and silently never renders), and Any/AtmosphereNprSky_ps.any appends an in-shader gamma encode (sqrt) to the linear sky colour, because this engine renders into a non-sRGB swapchain with no hardware gamma-on-write (the same encode the patched HlmsPbs applies to lit content - see pbs-honour-non-srgb-target.patch below). The runtime registers Media/Atmosphere (the script dir plus each per-language shader subdir as its own location, so a script's bare source X.metal and shader includes resolve) alongside the Hlms media at boot; the HlmsPbs object-fog integration pieces (Pbs/Any/Atmosphere/*.any) already ride in the shipped Hlms Pbs templates.
The same media set also carries the cubemap sky material SkyCubemap.material (a port-dir trim of the samples' Sky.material to the cubemap method only - the equirectangular method and its sources stay out) plus the SkyCubemap_ps fragment sources per shading language. It defines the Ogre/Sky/Cubemap material SceneManager::setSky(SkyCubemap) loads by name - the atmosphere's skybox sky type (AtmosphereDesc::skyType, Docs/render-abstraction.md); the vertex program is the shipped QuadCameraDirNoUV_vs. The cubemap texel is emitted as-is (no gamma encode): skybox content is authored gamma-space artwork, the raw sample IS the colour - the classic flavor's sky box multiplies nothing either, which keeps the one .dds pixel-comparable across flavors.
Overlay/samples/tools and all other components OFF until a consumer needs them; zip archives OFF (would add zziplib - revisit when content work needs addResourceLocation(LT_ZIP)).
Upstream installs no CMake package config (only pkg-config templates whose static .pc unconditionally Requires: gl - removed); the port ships its own OGRE-NextConfig.cmake with namespaced imported targets (OgreNext::Main, OgreNext::HlmsPbs, OgreNext::HlmsUnlit, OgreNext::Atmosphere, OgreNext::RenderSystem_Metal on Apple / OgreNext::RenderSystem_Vulkan on Linux and Android, OgreNext::RenderSystem_NULL) plus OGRE_NEXT_MEDIA_DIR (the shipped Media/Hlms shader templates every Ogre-Next app must register). The config detects the consumer's platform (CMAKE_SYSTEM_NAME = iOS/Android) to pick the per-platform link interfaces: macOS vs iOS platform frameworks on OgreNext::Main (iOS uses Foundation/UIKit/QuartzCore/CoreGraphics, no Cocoa/Carbon/IOKit), Linux xcb libs vs Android's xcb-free Vulkan interface, and it drops freeimage::FreeImage (and its find_dependency) on mobile.
Patches (the same Xcode-oriented-CMake class as classic's ios/metal patches):
-
apple-ninja-objcxx-sysroot.patch- upstream assumes Xcode on Apple:(a) enable OBJC/OBJCXX so the
.mmsources (OgreMain/src/OSX, RenderSystem_Metal) compile under single-config generators; (b) do not clobber the iOSCMAKE_OSX_SYSROOTwith the symbolic "iphoneos" SDK name afterproject()(Ninja passes-isysrootverbatim; the hunk stops upstream from overwriting the simulator triplet'siphonesimulatorsysroot). The equivalent macOS "macosx" hunk this patch used to carry is upstream now - master guards that block withif(NOT CMAKE_OSX_SYSROOT), and CMake resolves the sysroot to a real path beforeproject(), so the guard skips it; the iOS block is still unguarded upstream; (c) mirror upstream's-DDEBUG=1debug flag into the OBJCXX/OBJC debug flags -OGRE_DEBUG_MODEis ABI-relevant (generateAbiCookie) and the Metal plugin's ObjC++ TUs must agree with OgreMain's C++ TUs. (A second patch this port used to carry, guarding OgreMain's framework-header POST_BUILD behindOGRE_BUILD_LIBS_AS_FRAMEWORKS, was dropped when the pin moved to master: upstream added the identical guard.) -
vulkan-no-shaderc-probe.patch- ogre-next's bundledCMake/Packages/FindVulkan.cmakerequireslibshaderc_combined(viaVulkan_SHADERC_LIB_REL/_DBG) in itsfind_package_handle_standard_args, a Windows-Vulkan-SDK-ism. The Vulkan RS compiles GLSL to SPIR-V through glslang only (OgreVulkanProgram.cppusesglslang/Public/ ShaderLang.hand self-declares theGlslangToSpvprototypes - zero shaderc usage underRenderSystems/Vulkan/), and neither vcpkg nor the NDK ships shaderc_combined, so the probe failed,Vulkan_FOUNDwent false, and thecmake_dependent_optionsilently dropped the RS. The patch drops the two shaderc vars from the probe and only appends theoptimized/debugshaderc entries toVulkan_LIBRARIESwhen found (an absent shaderc otherwise leaves a danglingoptimizedkeyword that reachestarget_link_librariesand hard-errors). Needed on both Linux and Android. -
lib-install-path.patch-CMake/Utils/OgreConfigTargets.cmakeinstalls iOS release static libs into
lib/Release(an Xcode-layout leftover); drop that so iOS keeps the standard vcpkglib/layout the shipped config'slib/lib*.apaths expect. (The$(PLATFORM_NAME)-under- Ninja output-path problem classic patched is already fixed upstream in ogre-next -OgreConfigTargets.cmakeexcludes Ninja.) -
pbs-honour-non-srgb-target.patch- upstream candidate (submitted asOGRECave/ogre-next #584). HlmsPbs hardcodes
hw_gamma_writeto 1 inpreparePassHash, assuming an sRGB colour target - on a UNORM swapchain (this engine's deliberate classic colour-parity convention) the LINEAR lighting result lands raw and every lit surface displays gamma-crushed. The patch derives the property from the live pass descriptor's colour format (PixelFormatGpuUtils::isSRgb), which engages the stock template's in-shadersqrtencode (!hw_gamma_write) on non-sRGB targets. HlmsUnlit is deliberately untouched (its raw passthrough IS the 2D parity convention). -
hlms-tls-init-symbol-visibility.patch- upstream candidate.Hlms::msThreadIdis a
thread_localstatic member declared inOgreHlms.hand defined, constant-initialized, inOgreHlms.cpp. A translation unit that sees only the declaration cannot know the initialization is constant, so it emits the Itanium ABI thread-local access wrapper_ZTW..., which weakly references the thread-local init function_ZTHN4Ogre4Hlms10msThreadIdE- a symbol a constant-initialized variable never defines anywhere. Resolving that dangling weak reference to zero needs a GOT entry, which clang only emits for a symbol that may bind externally;OGRE_SHADER_THREADING_USE_TLSis a static-build-only setting and_OgreExportisvisibility("hidden")there, so clang instead addresses the symbol directly and the object carriesR_X86_64_PC32 _ZTHN4Ogre4Hlms10msThreadIdE, which GNU ld refuses to link into a PIE. Only optimized builds hit it: unoptimized ones leave the reference inside the wrapper's own COMDAT section, which the linker discards in favour of the clean copyOgreHlms.cppcontributes, while inlining moves it into ordinary.textwhere it survives to the final link. GCC uses the GOT here regardless, and AArch64 does too, so the failure is clang-on-x86-64 only - which is exactly the Release Linux configuration. The patch declares the member with explicit default visibility, restoring the GOT indirection every other configuration already uses. The generated code is otherwise unchanged; the linker relaxes the resulting general-dynamic TLS access back to local-exec because the variable is defined in the executable.
Debug/release note: vcpkg ships ONE header tree for both configs, but ogre-next's generated OgreBuildSettings.h bakes OGRE_DEBUG_MODE per build type under single-config generators - a debug consumer compiling against the release header while linking the debug lib is a REAL ABI break (v2 debug bookkeeping changes struct layouts; observed as a scene-node crash). The port builds with OGRE_EMBED_DEBUG_MODE=never (level derived from _DEBUG/DEBUG/NDEBUG at compile time) and the shipped config propagates $<$<CONFIG:Debug>:DEBUG=1;_DEBUG=1> on OgreNext::Main so consumers always match the libs.
ports/sol2
Overlay of the upstream vcpkg sol2 port (3.5.0#1). Delete this overlay once upstream carries an equivalent fix. Local addition:
-
clang18-noexcept-member-variable.patch: clang >= 18 (the NDK r27toolchain used by the android-debug preset) rejects
lua_CFunction freefunc = &upvalue_this_member_variable<...>::call<...>because thosecall/real_call/operator()templates carry anoexcept(std::is_nothrow_copy_assignable_v<T>)specifier - the address of a noexcept function no longer matches the plainint(lua_State*)target type under clang's stricter overload resolution (upstream: sol2 issues #1581, #1678; hits every usertype MEMBER-VARIABLE binding, i.e. every OVAR in core_base/Meta_Lua.h). The noexcept there is cosmetic (the functions call luaL_error/trampolines anyway); the patch drops it. Upstream-candidate.
ports/imgui
The stock vcpkg imgui port (docking branch, the editor's UI library) plus one behavioral patch:
-
selected-tab-ignores-hover.patch— a SELECTED tab keeps its own colourwhile the cursor is over it; the hover colour applies only to UNSELECTED tabs (and the held/drag state keeps its feedback everywhere). The editor theme paints the selected tab in the exact panel-body colour so tab and content read as one connected surface — a hover flash on the active tab would break that surface apart. Upstream has no per-state colour slot for a hovered-selected tab (one
ImGuiCol_TabHoveredcovers all tabs), so the split lives in the tab render.
ports/imgui-color-text-edit
The Script panel's code-editor widget (goossens/ImGuiColorTextEdit — the actively maintained rework of the classic syntax-highlighting editor widget: language tokenizers, markers, line decorators, find/replace, autocomplete hooks), pinned to a known-good commit because the upstream repo tags no releases and ships no library CMake. Not in the vcpkg registry, hence the overlay port — same conventions as ports/imgui:
-
our
CMakeLists.txt+ config template are installed OVER the source; thestatic lib builds from
TextEditor.{h,cpp}ONLY.TextDiff.*and its bundleddtl.hdiff library are deliberately omitted (unused by the editor, and leaving them out keeps the port's license inventory MIT-only). -
PUBLIC dependency on
imgui::imgui, so it always compiles against thesame docking imgui the editor uses (the widget speaks the modern key API; it needs no imgui internals and no texture API).
IMGUI_USE_WCHAR32intentionally matches the imgui port's configuration (unset — the widget works onImWchareither way, but the two must agree). -
cxx_std_17(the widget's own requirement; the engine builds C++20).
Consumed only by orkige_editor (desktop platforms — the same !ios & !android & !emscripten gate as imgui itself).
ports/libvterm
The embedded Terminal panel's VT screen model (tools/editor/EditorTerminalScreen.cpp). libvterm is the LeoNerd/neovim abstract terminal library — the callback-driven, allocation-free-in-steady-state VT220/xterm/ECMA-48 screen model that neovim's :terminal uses (its existence proof is a shell — and Claude Code — running inside neovim every day). Pinned to a neovim-fork commit; not in the vcpkg registry, hence the overlay port.
NAMING TRAP recorded so nobody swaps it: there is an unrelated, ncurses/ROTE-based project that also calls itself libvterm (TragicWarrior/libvterm). This is NOT that one — it is the C99 abstract screen-model library.
-
upstream ships no library CMake (a Makefile plus a Perl step that turns the
encoding
.tbltables into.incheaders). The neovim fork COMMITS those generated.incfiles (src/encoding/*.inc,src/fullwidth.inc), so ourCMakeLists.txt(installed over the source, theports/imguiconvention) is a plain C99 compile ofsrc/*.cwith NO Perl at build time — it builds on arm64-osx, x64-linux and x64-windows-static-md (MSVC-clean: the fork is maintained against MSVC; a_CRT_SECURE_NO_WARNINGSdefine quiets the secure-CRT noise). Static only. -
the library exports
libvterm::vterm. It links PRIVATE intoorkige_editor_core: the headerEditorTerminalScreen.hexposes only the editor's own cell/grid/cursor vocabulary, and every libvterm type and call is confined to the one implementation TU (theFontBakeImpl.cppsingle-file-lib precedent). That confinement is the swap seam — if a maturing pure-VT library grows a stable API and a Windows build it can replace libvterm without a caller changing.
Consumed only by the editor (desktop platforms — the same !ios & !android & !emscripten gate as imgui).
nanosvg (stock port — no overlay)
nanosvg is a plain vcpkg-registry dependency (vcpkg.json), NOT an overlay port — it needs no patch. Recorded here only so the choice has a rationale: it is the ONE SVG reader in the tree, with two consumers: engine_gui/FontAtlas rasterises .svg UI sprites into the runtime font atlas at boot, and engine_gui/SvgShapeCook flattens an imported drawing into the native .oshape — so the editor imports a vector shape with no interpreter and no subprocess. nanosvg is a tiny, permissively-licensed (Zlib) single-file SVG parser + rasteriser. The vcpkg port precompiles the implementation into static libs (NanoSVG::nanosvg / NanoSVG::nanosvgrast), so — unlike the header-only stb libs — nothing defines NANOSVG_IMPLEMENTATION; the engine just links the targets. Its headers are confined to exactly two TUs (engine_gui/SvgRasterImpl.cpp and engine_gui/SvgShapeCookImpl.cpp, the StbVorbisImpl.cpp precedent) so the library stays out of every header and the precompiled header. SvgShapeCook.h depends on orkige_core alone, so the host-side tools/shapecook CLI compiles that one TU without the engine closure. The matching glyph rasteriser is stb_truetype.h from the already-vendored stb port, confined to engine_gui/FontBakeImpl.cpp.