Инструменты сборки FOnline Engine
Скрипты сборки
Сборка обычно начинается во встраивающем проекте. Поддерживаемый рабочий процесс описан в Build Workflow, а этот файл содержит команды и входные переменные, относящиеся к BuildTools.
Точная поверхность команд основного buildtools.py генерируется из его
исполняемого parser. Используйте справочник BuildTools CLI
или каноническую JSON-модель, а не поддерживайте
отдельный список команд вручную.
Скрипты-помощники движка имеют отдельную поверхность на основе manifest.
Используйте справочник helper CLI или
каноническую JSON-модель для codegen,
компиляции Mono, покрытия, оркестрации gameplay-тестов, проверки импортов
Windows 7, Android-device, локального web-сервера и MSI-команд. Исполняемые
parser владеют синтаксисом; HelperCliInterface.json владеет назначением,
аудиторией, владельцем вызова и явной границей с основным CLI и packager.
gameplay_test_runner.py выполняет проверенные multi-process smoke manifest с
ожиданием готовности, обязательными/запрещёнными маркерами, единым deadline
сценария, очисткой и компактным JSON-отчётом. Его переиспользуемый тестовый
контракт и реальное доказательство headless server/client описаны в
Gameplay- и integration-тестирование.
ai_control_client.py является эталонным клиентом стандартной библиотеки для
экспериментального независимого от проекта конверта AiControl NDJSON/TCP. Он
читает общие токены из переменной окружения, отклоняет удалённые endpoint без
явного разрешения и проверяется через протокол AiControl
и запускаемый образец протокола.
Возможности деклараций пакетов и payload, реализованные в package.py,
моделируются в PackageInterface.json, проверяются по реализации и отображаются
в справочнике package interface.
Конкретная матрица DefinePackage(...) встраивающего проекта остаётся
собственностью проекта.
Роли и hooks нативных расширений моделируются в
NativeExtensionInterface.json, проверяются по текущему поведению CMake/codegen
и отображаются в справочнике нативных расширений.
Рекомендации по authoring и совместимости находятся в Нативные расширения.
Грамматика прототипов и правила валидации версионируются в
PrototypeFormatInterface.json; docs_prototype_format.py проверяет живые
parser/baker anchors, выводит встроенный каталог metadata properties и строит
справочник формата прототипов.
Руководство по authoring и миграции находится в
Формат прототипов.
Грамматика карт, владение размещением, нормализация Mapper и правила baking по
сторонам версионируются в MapFormatInterface.json; docs_map_format.py
проверяет живые loader/baker/mapper anchors, выводит встроенный каталог свойств
Map/Critter/Item и строит справочник формата карт.
Руководство по authoring находится в Map Format.
Грамматика описания моделей, входные mesh, правила композиции и compile-time
лимиты версионируются в ModelFormatInterface.json; docs_model_format.py
сравнивает все допустимые написания с ModelDescriptionParser::ParseToken и
строит справочник формата моделей.
Руководство по authoring находится в формате моделей.
Синтаксис text pack, нормализация языков, $Text прототипов, runtime lookup и
цветовые теги renderer версионируются в TextFormatInterface.json;
docs_text_format.py проверяет живые source anchors, выводит языки по умолчанию
и имена генерируемых пакетов прототипов и строит
справочник текстового формата.
Руководство по authoring находится в
Текст и локализация.
Секции эффектов, состояние pass/render, встроенные shader resources, backend
outputs, runtime caching и script control версионируются в
EffectFormatInterface.json; docs_effect_format.py проверяет живые
baker/renderer/runtime anchors, выводит compile-limit defaults и строит
справочник формата эффектов.
Руководство по authoring находится в Effect Format.
Форматы исходных изображений, композиция FOFRM, legacy selectors имён файлов,
записи baked sprite, стандартные runtime factories, atlases, caches и
валидация версионируются в ImageFormatInterface.json; docs_image_format.py
проверяет живые baker/client/test anchors, выводит оба extension registry и
строит справочник изображений.
Руководство по authoring находится в
Форматы изображений и спрайтов.
Particle XML, зарегистрированные объекты SPARK, SparkQuadRenderer, поведение
редактора, raw-copy delivery, runtime caches/render paths и интеграции
версионируются в ParticleFormatInterface.json; docs_particle_format.py
выводит живые registry, descriptors, покрытие редактора, extensions и settings
и строит справочник particle format.
Руководство по authoring находится в
Формат и исполнение частиц.
Дескрипторы FOFNT/BMFont, привязка font slot, масштабирование при bind, layout
текста, rendering flags, inline colors и валидация версионируются в
FontFormatInterface.json; docs_font_format.py проверяет parser, resource,
enum, atlas, cache и bundled-descriptor anchors и строит
справочник формата шрифтов.
Руководство по authoring находится в
форматы шрифтов и компоновка текста.
Запекание WAV/Ogg, runtime decoding Vorbis, playback handles/spatial updates, identities эффектов и нумерованные
варианты, музыка по точному пути, repeat timing, frontend mixing и поведение
silent/headless версионируются в AudioInterface.json; docs_audio.py выводит
живые resource, decoder, frontend, setting и test evidence и строит
справочник audio. Руководство по authoring
находится в Audio Resources and Playback.
Доставка Ogg/Theora, декодирование ресурса целиком, поведение fullscreen
queue/input/music, embedded playback, rendering и пробелы в проверках
версионируются в VideoInterface.json; docs_video.py выводит живые decoder,
client, script, rendering, raw-copy, dependency и test evidence и строит
справочник video. Руководство по интеграции
находится в Video Resources and Playback.
Прежний generated-справочник GUI runtime выведен из эксплуатации вместе с принадлежавшей Engine GUI library AngelScript. Текущий маршрут владения и проверки находится в границе интеграции GUI; high-level GUI libraries и declarative formats принадлежат подключающим проектам.
Владение публичными примерами, порядок, точные Engine pins, compatibility lanes,
governance files, исключения source staging и release gates версионируются в
Examples/PublicRepositories.json; docs_examples.py проверяет общий overlay,
материализует чистый review candidate только когда точный checkout Engine чист
и доступен удалённо, создаёт
реестр публичных примеров и
проверяет внешние candidate repositories перед публикацией.
Сценарии валидации можно запускать по одному или группой одной командой:
Engine/BuildTools/validate.sh unit-tests
Engine/BuildTools/validate.sh android-arm64-client linux-client linux-server
Обычная validation target unit-tests выбирает toolchain нативного host:
MSVC на Windows, Xcode на macOS и Clang на Linux. Sanitizer validators остаются
явно platform-specific.
Python regression tests BuildTools находятся в Engine/BuildTools/tests/ и
могут запускаться напрямую:
pytest -q Engine/BuildTools/tests
Структура CMake
Все внутренние CMake modules находятся в Engine/BuildTools/cmake.
Публичная точка входа Init.cmake сохранена в корне Engine/BuildTools;
поэтапная реализация CMake находится в Engine/BuildTools/cmake/stages/, а
helpers - в Engine/BuildTools/cmake/helpers/.
cmake/ProjectInterface.json является версионированной документационной моделью
project options, порядка stages, entrypoints, hooks и выбранной поверхности
helpers. Configure-time authority остаётся у Init.cmake и файлов стадий и
helper-команд; структурный тест отклоняет расхождения реализации с моделью.
Используйте сгенерированный
справочник CMake project interface или его
каноническую JSON-модель, а не копируйте
декларации из файлов реализации stages. Для принадлежащих проекту targets и
SDK используйте Проектные зависимости.
Текущая ревизия не имеет объявленной helper-команды project libraries и
использует привязанное к ревизии integration state FO_*_LIBS.
Исполняемый opt-in starter project находится в Engine/Examples/MinimalProject
и предоставляет свой локальный validator. Он не является target текущего
обязательного workflow Engine.
Генераторы документации
docs_api.pyзапускает существующий metadata parsercodegen.pyв режиме только чтения, применяет source-owned классификации///@ ApiContractи записывает/проверяетDocs/generated/api.json.docs_api_diff.pyпредоставляет слой сравнения native symbols, включая overload families и source-owned stability.docs_contract_diff.pyсравнивает модели native API, CMake, main CLI, package, helper CLI, native-extension, prototype-format, map-format, model-format, text-format, effect-format, image-format, particle-format, font-format, audio, video, GUI runtime и AiControl protocol в одном отчёте по паре revisions и требует точных dispositions общего ledger для baseline-public или model-contract breaks.docs_public_api.pyзаписывает/проверяет канонические EN/RU индексы контрактов и корневой legacy-маршрутPUBLIC_API.mdиз всех восемнадцати машинных моделей и их сгенерированных human references; native inventory counts и default stability никогда не поддерживаются вручную.docs_external_evidence.pyпроверяет pinned Last Frontier/TLA discovery inventory, owner review policy, dispositions, priorities, Engine/planned targets и детерминированный внутренний отчёт. При наличии обоих точных checkout он также доказывает черезgit cat-file, что каждый записанный путь существует в pinned commit.docs_cmake.pyпроверяетcmake/ProjectInterface.jsonи записывает/проверяетDocs/generated/cmake.json, английский справочник Markdown вDocs/en/reference/cmake/и устойчивые указатели маршрутов вDocs/generated/cmake/.docs_cli.pyзагружает исполняемый parserargparseизbuildtools.pyи записывает/проверяетDocs/generated/cli.json, точный английский справочник Markdown на основе help вDocs/en/reference/buildtools/и устойчивые указатели маршрутов вDocs/generated/cli/.docs_helper_cli.pyпроверяетHelperCliInterface.json, доказывает полное покрытие inventorycreate_parser()и записывает/проверяетDocs/generated/helper-cli.json, точный английский справочник Markdown на основе help вDocs/en/reference/helper-cli/и устойчивые указатели маршрутов вDocs/generated/helper-cli/.docs_native_extension.pyпроверяет документационную модель native roles/hooks по текущим данным CMake/codegen и записывает/проверяетDocs/generated/native-extension.jsonвместе со страницами roles, hooks и bindings.docs_prototype_format.pyпроверяетPrototypeFormatInterface.jsonпо живым parser/baker sources, выводит применимость встроенных entity/property из metadata и записывает/проверяетDocs/generated/prototype-format.jsonвместе со страницами syntax, property и validation.docs_map_format.pyпроверяетMapFormatInterface.jsonпо живым loader/baker/mapper/runtime sources, выводит данные Map/Critter/Item property и ItemOwnership из metadata и записывает/проверяетDocs/generated/map-format.jsonвместе со страницами syntax, property, baking и validation.docs_model_format.pyпроверяетModelFormatInterface.jsonпо живому model parser, mesh baker, client runtime, limits и tests, затем записывает/проверяетDocs/generated/model-format.jsonвместе со страницами syntax, token, composition, asset, animation и validation.docs_text_format.pyпроверяетTextFormatInterface.jsonпо text-pack, baker, runtime, script API, settings, renderer и test sources, затем записывает/проверяетDocs/generated/text-format.jsonвместе со страницами syntax, language, prototype-text, runtime и validation.docs_effect_format.pyпроверяетEffectFormatInterface.jsonпо effect baker, render-effect/runtime/cache/script API, backend conventions, project limits и tests, затем записывает/проверяетDocs/generated/effect-format.jsonвместе со страницами syntax, render-state, resource, baking, runtime и validation.docs_image_format.pyпроверяетImageFormatInterface.jsonпо ImageBaker, FOFRM/import sources, стандартному client factory/sheet/atlas/cache behavior и tests, затем записывает/проверяетDocs/generated/image-format.json, канонические английские страницы вDocs/en/reference/image-format/и совместимые маршруты вDocs/generated/image-format/.docs_particle_format.pyпроверяетParticleFormatInterface.jsonпо raw-copy settings, SPARK XML/registry/descriptors, Engine renderer, ParticleEditor, client runtime, script/model integrations и tests, затем записывает/проверяетDocs/generated/particle-format.jsonвместе со страницами XML, object, renderer, tooling, runtime, integration и validation.docs_audio.pyпроверяетAudioInterface.jsonпо conversion/passthroughAudioBaker, indexing и Vorbis decodingAudioManager, script playback handles/spatial updates, frontend conversion/mixing, headless behavior и native-test inventory, затем записывает/проверяетDocs/generated/audio.jsonвместе со страницами format, delivery, decoding, playback и validation.docs_video.pyпроверяетVideoInterface.jsonпо raw-copy settings, декодированию Ogg/Theora, fullscreen queue/input/music/drawing, embedded script playback, renderer behavior, dependencies и native-test inventory, затем записывает/проверяетDocs/generated/video.jsonвместе со страницами format, delivery, decoding, fullscreen, embedded и validation.docs_ai_control_protocol.pyпроверяетAiControlProtocol.jsonпо reference client и запускаемому sample, затем записывает/проверяетDocs/generated/ai-control-protocol.jsonвместе со страницами wire, method, command/event, security и integration/validation.docs_package.pyпроверяет документационную модель package и исполняемый parserpackage.py, затем записывает/проверяетDocs/generated/package.jsonвместе со страницами package reference.docs_examples.pyпроверяетExamples/PublicRepositories.jsonи governance overlay, записывает/проверяетDocs/generated/public-examples.jsonи его registry page, материализует source-ready example в новом чистом candidate directory и проверяет metadata внешнего repository, точные gitlink pins, обязательные файлы и байты provenance file.docs_reference.pyотображает каноническую модель API в совместимый с GitHub Pages Markdown вDocs/generated/api/.docs_metadata.pyстрого декодирует project-bakedMetadata.fometa-server/client, проверяет согласованность обеих сторон и записывает/проверяет принадлежащий проекту JSON/Markdown catalog remote calls.docs_inventory.pyзаписывает/проверяет независимый inventory export methods, native tests и setting declarations.docs_localization.pyобеспечивает полное двуязычное покрытие, проверяет glossary, стабильные locale targets, нормализованные English hashes, точные переведённые fences и language-preserving links, затем записывает/проверяетDocs/generated/translation-status.json.docs_description_translations.pyинвентаризирует обращённый к читателю текст в 20 генерируемых контрактных моделях, применяет проверенный русский overlay со стабильными ID, отклоняет повторяющиеся, неизвестные, устаревшие, меняющие тип или код записи и записывает/проверяетDocs/generated/description-translation-status.json. Отсутствующие записи остаются явными, пока семантический каталог не сможет перейти изregistered-translations-currentвcomplete.docs_ai_delivery.pyпроецируетDocs/documentation-manifest.jsonи канонический Markdown в корневыеllms.txt, ограниченныйllms-full.txtи публичныйdocs-manifest.json; он нормализует content hashes и отклоняет stale, oversized или non-deterministic output.docs_site.pyразрешает manifest-owned stable document IDs в проверенные localized Jekyll navigation data, ограниченные статические English/Russian search indexes и публичный version/locale/legacy-route catalog; он отклоняет неизвестные, дублированные или пропущенные top-level pages, route collisions, неоднозначные canonical targets, отсутствующие locale pairs, cross-locale search ownership и oversized или stale output.docs_ai_eval.pyпроверяет версионированный standalone task set вDocs/ai-evaluation.jsonпо manifest и той же компактной search model, которую использует browser, затем записывает/проверяетDocs/generated/ai-evaluation-report.jsonс ranks, evidence checks, success rate и MRR.docs_ai_model_eval.pyнеобязательно запускает изолированные задачи через локальную модель Ollama, сохраняя точные хеши inputs/prompts/model, потоковые raw attempts, наблюдения evidence и возобновляемое состояние задач в игнорируемомWorkspace/ai-evaluation/. Он повторяет ограниченные дословные decision- и query-relevant-разделы найденных документов-кандидатов рядом с инструкцией ответа, сохраняя rubric ответа скрытым; это локальный инструмент проверяемых свидетельств, а не CI dependency.docs_ai_model_review.pyсоздаёт, финализирует и проверяет компактные semantic reviews для raw-прогонов семейств моделей;--require-runдополнительно доказывает сохранённый raw SHA-256 и встроенные метаданные прогона.docs_snippets.pyинвентаризует каждый fence в public/current/human documents, применяет language/harness contract изSnippetPolicy.json, записывает/проверяетDocs/generated/snippets.jsonи при необходимости требует реальные parser Bash и PowerShell без выполнения команд.docs_diagrams.pyпроверяетDocumentationDiagrams.json, alt/caption markup owning document, source provenance, canvas bounds, node overlap и local-only SVG safety; он записывает/проверяет desktop/mobile SVG variants для трёх teaching diagrams вместе сDocs/generated/diagrams.jsonс точными hashes.docs_screenshots.pyпроверяетDocumentationScreenshots.json, точные PNG bytes/dimensions, alt/caption markup owning document, capture environment, source provenance и recapture triggers; он записывает/проверяетDocs/generated/screenshots.jsonс точными image, manifest и source hashes.docs_site_artifact.pyпроверяет готовое дерево Jekyll_siteпо route catalog и source artifacts. Он отклоняет отсутствующие current/available-locale routes, изменённые или отсутствующие static endpoints, неверные canonical URL/languages, отсутствующие accessibility landmarks/names, duplicate IDs и сломанные ссылки на публикуемые локальные ресурсы; CI сохраняет его JSON report.docs-browser/audit.mjsлокально обслуживает готовое дерево_siteи применяет зафиксированный lock-файлом Playwright Chromium вместе с axe-core для проверки каждого route на desktop и mobile ширине. Он отклоняет нарушения WCAG 2.2 A/AA, runtime/resource errors, горизонтальную прокрутку уровня страницы, сломанный responsive layout и keyboard failures в skip navigation, search, theme, copy и mobile focus-trapped drawer; CI сохраняет JSON и screenshots.docs_validate.pyпроверяет documentation manifest, локальные links/anchors, source ownership, Pages contract и freshness каждого generated artifact.
Запускайте их сфокусированные тесты и проверки из корня движка; generated JSON и Markdown хранятся в repository и не должны редактироваться вручную.
Материализуйте review candidate только из чистого, удалённо доступного точного Engine commit:
python BuildTools/docs_examples.py --stage-repository minimal-multiplayer --engine-revision "$(git rev-parse HEAD)" --output Workspace/fonline-minimal-multiplayer
python -m unittest discover -s BuildTools/tests -p "test_docs*.py"
cmake -P BuildTools/tests/validate_project_interface.cmake
cmake -P BuildTools/tests/validate_native_extension_interface.cmake
cmake -P BuildTools/tests/validate_package_interface.cmake
python BuildTools/docs_cmake.py --check
python BuildTools/docs_cli.py --check
python BuildTools/docs_helper_cli.py --check
python BuildTools/docs_native_extension.py --check
python BuildTools/docs_prototype_format.py --check
python BuildTools/docs_map_format.py --check
python BuildTools/docs_model_format.py --check
python BuildTools/docs_text_format.py --check
python BuildTools/docs_effect_format.py --check
python BuildTools/docs_image_format.py --check
python BuildTools/docs_particle_format.py --check
python BuildTools/docs_font_format.py --check
python BuildTools/docs_audio.py --check
python BuildTools/docs_video.py --check
python BuildTools/docs_ai_control_protocol.py --check
python BuildTools/docs_package.py --check
python BuildTools/docs_examples.py --check
python BuildTools/docs_public_api.py --check
python BuildTools/docs_external_evidence.py --check
python BuildTools/docs_inventory.py --check
python BuildTools/docs_localization.py --check --enforce-complete
python BuildTools/docs_description_translations.py --check
python BuildTools/docs_diagrams.py --check
python BuildTools/docs_screenshots.py --check
python BuildTools/docs_snippets.py --check --external
python BuildTools/docs_site.py --check
python BuildTools/docs_ai_eval.py --check
python BuildTools/docs_site_artifact.py --site-dir _site
npm ci --prefix BuildTools/docs-browser
npx --prefix BuildTools/docs-browser playwright install chromium
npm --prefix BuildTools/docs-browser run audit
python BuildTools/docs_ai_delivery.py --check
python BuildTools/docs_validate.py
Компилятор проектов Effekseer
Source/Tools/EffekseerCompiler.h/.cpp является нативным C++ module,
скомпилированным в BakerLib. Для каждого фиксированного Editor-1.80.5 /
project-version-3 .efkproj он проверяет XML profile и возвращает raw SKFE
bytes вместе со ссылочными textures, models, sounds и curves. ParticleBaker
вызывает module напрямую и проверяет каждый результат vendored Effekseer Core
перед публикацией.
ParticleBaker разрешает dependency paths внутри физического directory resource
source проекта и хранит snapshot path/size/write-time для каждого эффекта в
<BakeOutput>/.baker-cache/Effekseer/. Исходный проект и dependency snapshot
независимо инвалидируют производный .efk; после изменений кода compiler
используйте ForceBakeResources. Изменённый эффект перекомпилируется по
требованию без invalidation несвязанных эффектов во время focus-triggered
resource reindex Mapper.
Compiler не линкуется в runtime clients и не упаковывается с ними. Нативные
Baker и Mapper hosts используют его, когда derived resources устарели; Web
clients используют заранее подготовленные host .efk resources.
Developer bundle Effekseer Editor
Зафиксированный upstream Effekseer Editor собирается как отдельный Windows
win64 developer tool. Он независим от FO_EFFEKSEER_PARTICLES и не представлен
как Engine CMake option, application target или универсальный target
buildtools.py build. Поэтому runtime builds никогда не получают toolchain
Editor или его Viewer/UI libraries.
Собирайте и размещайте его через общую точку входа auxiliary tools:
$env:FO_OUTPUT = (Get-Location).Path
python Engine\BuildTools\buildtools.py build-auxiliary effekseer-editor Release
Скрипт собирает managed .NET 10 UI и нативные Viewer/material tools в
изолированных output directories, затем размещает self-contained payload.
Languages, fonts, icons, meshes, LICENSE_TOOL, material editor и Direct3D
11/OpenGL material compilers являются частью payload. Запись GIF отключена в
этой сборке FOnline, что исключает неиспользуемую зависимость libgd; обычное
редактирование и интерактивный preview Editor остаются доступными.
Адаптация FOnline ориентирована на исходники. Save и Save As в Editor
принимают только .efkproj и атомарно записывают нормализованный UTF-8 XML без
BOM. Stock preview Editor предназначен для authoring iteration; preview Mapper
встраивающего проекта остаётся финальным путём проверки через renderer FOnline
и capability gate.
Переиспользуемая package schema не имеет Effekseer-specific binary role.
Встраивающий проект доставляет отдельно размещённый tool через общую package
declaration INCLUDE <source-path-glob> <target-path-in-pack>. Source globs
задаются относительно FO_OUTPUT_PATH; packager заменяет принадлежащее ему
target tree и обновляет существующий SingleZip без duplicate или stale entries.
Переменные окружения сборки
Build scripts (sh/bat) можно вызывать из текущего каталога (например,
./linux.sh) или из корня repository (например, BuildTools/linux.sh).
Перед запуском build scripts можно задать следующие переменные окружения.
BuildTools использует только project-specific overrides с префиксом FO_.
Любой объявленный project-interface option можно переопределить одноимённой
переменной окружения; точный список и precedence находятся в
сгенерированном справочнике options.
Стандартные tool variables ANDROID_HOME, ANDROID_SDK_ROOT и
ANDROID_NDK_ROOT зарезервированы для запускаемых внешних инструментов и не
читаются как inputs BuildTools.
FO_ENGINE_ROOT
Путь к корневому каталогу repository FOnline.
Если не задан, используется каталог на один уровень выше запускаемого script
file (вне BuildTools, в корне repository).
По умолчанию: $(dirname ./script.sh)/../
Пример: export FO_ENGINE_ROOT=/mnt/d/fonline
FO_WORKSPACE
Путь к каталогу хранения всех промежуточных build files.
По умолчанию сборка выполняется в каталоге Workspace внутри текущего каталога.
По умолчанию: $PWD/Workspace
Пример: export FO_WORKSPACE=/mnt/d/fonline-workspace
FO_ANDROID_HOME / FO_ANDROID_SDK_ROOT / FO_ANDROID_NDK_ROOT
Необязательные явные overrides Android SDK и NDK для BuildTools. Если они не
заданы, BuildTools использует подготовленные workspace locations, а затем
системный fallback /usr/lib/android-sdk в Linux, когда он доступен.
FO_CLANG_FORMAT
Необязательный явный путь к binary clang-format, используемому
buildtools.py format-source. Binary всё равно должен проходить gate версии 20.
Если переменная не задана, BuildTools ищет в системном PATH сначала
clang-format-20, затем clang-format. Встраивающий проект может направить
formatter Engine на собственный pinned или bundled binary.
Подготовка общего workspace
Общие части workspace подготавливаются через buildtools.py и оборачиваются
platform-specific scripts.
- Linux:
Engine/BuildTools/prepare-workspace.sh - macOS:
Engine/BuildTools/prepare-mac-workspace.sh - Windows:
Engine/BuildTools/prepare-win-workspace.ps1
Сейчас общий flow охватывает:
toolsetemscriptenandroid-ndkdotnetxwinwixmsan-libcxx
Установка системных пакетов Linux является явной и отделена от подготовки workspace:
common-packageslinux-packagesweb-packagesandroid-packageswindows-cross-packagesmsi-packagesall-packages
Workspace features linux, web, android-arm64 и windows-cross не
устанавливают apt packages. На чистом host сначала передайте соответствующий
feature *-packages. all-packages устанавливает все группы выше, включая
php-cli и msi-packages с toolset MSI installer wixl. Поскольку apt
существует только на host-provisioning path, ни одна часть prepare-workspace
не устанавливает системные пакеты, а параллельные CI jobs не конкурируют за apt
lock.
Проверки host prerequisites также доступны через основной tool:
buildtools.py host-check linuxbuildtools.py host-check macosbuildtools.py host-check windows
Host wrapper scripts делегируют unified-команде подготовки workspace:
buildtools.py prepare-host-workspace linux ...buildtools.py prepare-host-workspace windows ...buildtools.py prepare-host-workspace macos ...
Версия Emscripten фиксируется Engine/ThirdParty/emscripten и устанавливается
в Workspace/emsdk.
Примеры:
python3 Engine/BuildTools/buildtools.py prepare-workspace toolset
python3 Engine/BuildTools/buildtools.py prepare-workspace emscripten
python3 Engine/BuildTools/buildtools.py prepare-workspace android-ndk dotnet
python3 Engine/BuildTools/buildtools.py prepare-workspace wix
python3 Engine/BuildTools/buildtools.py prepare-workspace msan-libcxx
python3 Engine/BuildTools/buildtools.py prepare-workspace toolset emscripten android-ndk dotnet --check
python3 Engine/BuildTools/buildtools.py prepare-host-workspace linux web-packages web dotnet
wix доступен только в Windows и подготавливает portable release WiX v3,
закреплённый Engine/ThirdParty/wix, в Workspace/wix3. Downloads используют
FO_DOWNLOAD_MIRROR, как и другие workspace archives, и до распаковки проходят
проверку SHA-256. package.py находит этот directory относительно input output,
поэтому global install и постоянное изменение PATH не требуются. POSIX package
hosts продолжают использовать подготовленную команду wixl.
msan-libcxx доступен только в Linux и намеренно исключён из feature workspace
all по умолчанию, потому что загружает соответствующие исходники LLVM и
собирает libc++, libc++abi и libunwind с MemorySanitizer instrumentation.
Runtime build также передаёт BuildTools/sanitizers/msan-runtime-ignorelist.txt,
чтобы libunwind не выдавал self-report для ABI register snapshots во время
разворачивания C++ exception или sanitizer report. Validator
unit-tests-san-memory автоматически подготавливает его перед конфигурацией
San_Memory; используйте явную workspace-команду только для предварительного
прогрева CI host или отладки runtime build.
Linux hosts могут подготовить Windows cross-compilation SDK/CRT через ту же обёртку:
bash Engine/BuildTools/prepare-workspace.sh windows-cross-packages windows-cross
bash Engine/BuildTools/prepare-workspace.sh windows-cross
python3 Engine/BuildTools/buildtools.py prepare-workspace xwin
python3 Engine/BuildTools/buildtools.py build win64 client Release
python3 Engine/BuildTools/buildtools.py build win32 client Release
Feature windows-cross-packages устанавливает/проверяет Linux prerequisites.
Wrapper feature windows-cross и прямая команда prepare-workspace xwin
работают только с workspace: они используют версию xwin, зафиксированную в
Engine/ThirdParty/xwin, подготавливают деревья SDK/CRT для x86 и x86_64 в
Workspace/xwin и намеренно пропускают установку системных пакетов для заранее
подготовленных CI hosts. buildtools.py сначала выполняет splat основной
архитектуры, затем объединяет library directories вторичной архитектуры из
изолированных splat, чтобы избежать shared-symlink race xwin 0.6.6-rc.2 при
одном multi-arch вызове. Каждый splat передаёт --http-retry 5, поэтому
временные ошибки чтения тела Microsoft CDN повторяются до отказа подготовки.
Для win32 buildtools.py передаёт CMAKE_SYSTEM_PROCESSOR=x86; toolchain
сохраняет library paths x86 из xwin и принудительно использует
clang-cl --target=i686-pc-windows-msvc, чтобы compiler probes CMake не
создавали x64 objects для x86 link.
Исправление регистра путей checkout
python3 Engine/BuildTools/buildtools.py repair-checkout-case
python3 Engine/BuildTools/buildtools.py repair-checkout-case --check
Команда рекурсивно, включая submodules, переименовывает элементы рабочего дерева, чей регистр на диске отличается от имени в git. Case-only rename корректно записывается в index, но на файловой системе без учёта регистра git переписывает только имена файлов: существующий каталог навсегда сохраняет старое написание. Поэтому повторно используемый checkout продолжает отдавать устаревшее имя, хотя поиск ресурсов и include остаётся регистрозависимым.
Симптом проявляется далеко от причины: присутствующий на диске файл считается отсутствующим при baking. Обычно страдают долгоживущие checkout на собственных Windows runners; свежий clone не воспроизводит проблему. Поэтому CI на таких runners должен выполнять команду сразу после checkout.
--check только сообщает о расхождении и завершается с ненулевым кодом, не
изменяя рабочее дерево. Если index одновременно содержит один путь в двух
вариантах регистра, команда называет оба и отказывается что-либо исправлять:
это неоднозначный tracked collision, требующий решения владельца.
Отладочный workflow Web в Windows
Локальный отладочный flow Web в Windows использует общие команды:
buildtools.py build web client RelWithDebInfobuildtools.py package-web-debug
Для оптимизированной browser build используйте:
buildtools.py build web client Release
Упакованная browser build создаётся в
Workspace/web-debug/<ProjectDevName>-Client-<Config>-Web и может обслуживаться
генерируемым helper web-server.py.
Отладочный workflow Android
Локальный отладочный flow Android использует общие команды.
Поддерживаемые identifiers Android platform: android-arm32, android-arm64
и android-x86.
Развёртывание на device основано на ADB по Wi-Fi. На целевом device должна быть включена wireless debugging, и при запросе Android он должен быть спарен с этим host.
buildtools.py build android-arm64 client RelWithDebInfobuildtools.py package-android-debug <ProjectDevName> android-arm64 <Config>android_device.py --workspace-root Workspace connect
Сначала необходимо подготовить части workspace Android SDK и NDK. Используйте
android-packages только на чистом Linux host, которому ещё нужны системные
пакеты:
bash Engine/BuildTools/prepare-workspace.sh android-arm64bash Engine/BuildTools/prepare-workspace.sh android-packages android-arm64
Упакованная Android build создаётся в
Workspace/android-debug/<ProjectDevName>-Client-<Config>-Android как готовый
к сборке Gradle project. Сборка и развёртывание:
python3 Engine/BuildTools/android_device.py --workspace-root Workspace connect
cd Workspace/android-debug/<ProjectDevName>-Client-<Config>-Android
./gradlew assembleDebug
python3 Engine/BuildTools/android_device.py --workspace-root Workspace install --apk Workspace/android-debug/<ProjectDevName>-Client-<Config>-Android/app/build/outputs/apk/debug/app-debug.apk
python3 Engine/BuildTools/android_device.py --workspace-root Workspace launch --activity com.example.game/.FOnlineActivity
# Pass the host address for a project config that expects a remote server.
python3 Engine/BuildTools/android_device.py --workspace-root Workspace launch-game --activity com.example.game/.FOnlineActivity
launch-game автоматически определяет LAN IP host, который достигает
выбранного Wi-Fi Android device, и передаёт его как runtime override
ClientNetwork.ServerHost. Благодаря этому упакованный client
RemoteSceneLaunch подключается обратно к host server без редактирования baked
config files.
Во время выполнения FOnlineActivity размещает assets/Resources в app files
directory при первом запуске после установки или обновления, затем запускает
движок с абсолютными overrides Baking.ClientResources и
Baking.CacheResources, указывающими на runtime location.
Версия Android SDK command-line tools фиксируется
Engine/ThirdParty/android-sdk и устанавливается в Workspace/android-sdk.
BuildTools использует интерфейс android sdk install этого пакета с отключённой
метрикой; устаревший путь через sdkmanager не используется.
Версия Android NDK фиксируется Engine/ThirdParty/android-ndk и
устанавливается в Workspace/android-ndk.
Шаблон Gradle project находится в Engine/BuildTools/android-project/, фиксирует
Android Gradle Plugin 9.3.0 с Gradle 9.5.0, компилирует исходники Java на уровне
языка 17 и использует tokens $PLACEHOLDER$, которые package.py заменяет при
packaging.
Значения Android configuration поступают из authored root и выбранного
SubConfig; build-host directives $ENV/$FILE и
$TARGET_ENV/$TARGET_FILE разрешаются только при packaging, поэтому overrides
sub-config влияют на APK metadata без необходимости помещать signing values в
baked client config. Android SDK, которым нужна application manifest metadata,
могут использовать settings
Android.ManifestMetaData.<android:name> = <android:value>; packager создаёт из
них entries <meta-data> внутри <application>. Gradle setup SDK может
использовать Android.GradleMavenRepository.<name> = <url> и
Android.GradleDependency.<name> = <Gradle dependency statement> для
добавления package-config-specific Maven repositories и entries
dependencies { ... }. Package-specific Java sources могут использовать
Android.JavaSource.<name> = <path/to/File.java>; packager копирует каждый
непустой source в namespace сгенерированного app package и заменяет
$PACKAGE$ / $CONFIG$.
Packaging release APK для Android подписывает artifact. Настройте signing через
Android.Keystore, Android.KeystorePassword, Android.KeyAlias и
Android.KeyPassword в main config проекта. Для sensitive inputs используйте
$TARGET_ENV{...} или защищённый $TARGET_FILE{...} для значения, но не для
пути keystore, чтобы ConfigBaker не материализовал их. package.py передаёт
Android.KeystorePassword и Android.KeyPassword в Gradle через переменные
окружения FO_ANDROID_RELEASE_STORE_PASSWORD и
FO_ANDROID_RELEASE_KEY_PASSWORD, а не записывает их в сгенерированный Gradle
project. При ручной сборке сгенерированного Gradle project задайте эти
переменные перед ./gradlew assembleRelease; если signing settings пусты,
packaging использует fallback на Gradle debug signing key, чтобы
сгенерированные package APK оставались устанавливаемыми на development devices.
Полная граница описана в Security and Secrets.
При packaging APK Gradle использует GRADLE_USER_HOME внутри текущего workspace
output tree вместо общего ~/.gradle, поэтому параллельные CI package jobs не
конкурируют за глобальные Gradle caches.
android_device.py сначала вызывает adb mdns services, показывает найденные
Android Wi-Fi endpoints как нумерованный список, кеширует выбранный endpoint в
Workspace/android-debug/device-endpoint.txt и предлагает ручной ввод
IP[:port], если discovery ничего не вернул.
После сборки каждый клиентский и серверный пакет ресурсов открывается повторно — как ZIP-файлы, записанные на диск, так и пакет в памяти, встраиваемый в исполняемый файл. Packaging проверяет точный список записей и полностью читает каждую из них через ZIP reader с проверкой CRC, поэтому повреждённый архив ресурсов останавливает сборку пакета до того, как попадёт в загружаемый клиент или в источник обновлений сервера.
При сбое MSI compiler/linker его native file, ICE или Windows Installer
diagnostic остаётся в build log до завершения packaging. На Windows candle
и light считают предупреждения ошибками. Генератор подавляет только ICE91:
все создаваемые MSI явно устанавливаются per-user в LocalAppDataFolder,
поэтому предупреждение о смешанной области установки к ним неприменимо.
Первый запуск light сохраняет ICE validation и буферизует вывод до его
классификации; успешный link или окончательный сбой затем публикует вывод.
Только точное сообщение о недоступности Windows Installer service выбирает
одну повторную попытку того же link с -sval. При её успехе устаревшие строки
error не выводятся, чтобы MSBuild не принял успешный custom target за сбой.
Любая ошибка authoring, linker или обычной ICE завершает процесс сразу;
ошибка повторной попытки также остаётся фатальной.
Embedding build может задать FO_RESOURCE_ARCHIVE_CACHE_HELPER как Python
helper с интерфейсом restore|store|release --key <sha256> --archive <path>.
До deflate package.py хеширует стабильные имена и содержимое entries вместе с
compression level. Код 0 от restore предоставляет готовый archive, 2 означает
miss; после miss проверенный archive передаётся store, а прерванная запись
вызывает release. Код 3 сообщает о недоступности optional cache и отключает
следующие вызовы helper в этом package process. Обычные проверки entry list и
CRC обязательны независимо от источника archive. Повторный идентичный archive
в одном процессе копируется из первого проверенного результата без нового
вызова helper.
-resource-pack-jobs N (или FO_RESOURCE_PACK_JOBS, по умолчанию 1) ограничивает
создание независимых архивов ресурсов N spawned processes. Каждый worker
выполняет полный writer, cache protocol и проверки целостности. Одинаковое имя
pack или физический путь назначения остаётся у одного worker, сохраняя порядок
и локальное переиспользование между server/client outputs. Parent принимает
идентичности проверенных архивов и ждёт workers до runtime-specific rewriting
ресурсов или cleanup после сбоя. Группы распределяются по объёму исходных bytes,
начиная с крупнейших. Каждый batch сохраняет состояние unavailable cache между
своими архивами, поэтому число неудачных optional-cache probes ограничено числом
workers для invocation.
Packaging: изменение binary после сборки
Полный workflow declaration, build/bake/package, platforms, signing, provenance, acceptance и recovery приведён в Упаковка и выпуск. Эта секция описывает детали реализации BuildTools.
package.py внедряет несколько значений в уже слинкованные binaries вместо
повторной компиляции для каждого package. Каждая цель является placeholder
фиксированной ёмкости, зарезервированным во время компиляции через
FO_KEEP_DATA_SYMBOL, чтобы linker сохранил array. Функция
patch_data(file, marker, data, max_size) изменяет его на месте: находит marker,
записывает data с padding # до max_size и проверяет, что размер файла не
изменился. Ничего не перемещается, не сжимается, не шифруется и не генерируется:
layout файла до и после одинаков, меняются только зарезервированные data bytes.
Изменяемые области содержат прозрачный текст identity/config, а не code:
PACKAGED_BUILD_NAME- marker###NotPackaged###, array на 128 bytes. Строка identity package/build; каждый runtime variant изменяет собственную, чтобыIsPackaged()и build name отражали package.INTERNAL_CONFIG- markers###InternalConfig###.../###InternalConfigEnd###, фиксированная движком ёмкость 20000 bytes. Подключаемые проекты не могут менять размер baked bootstrap config blob.- Embedded resources - ёмкость
FO_EMBEDDED_DATA_CAPACITY(200000).
package.py также переписывает PE PDB path (patch_pe_pdb_path) и tokens
$PLACEHOLDER$ Android Gradle.
Примечание для антивирусов: большая placeholder region, изменяемая после сборки, внешне напоминает packer/dropper stub, но здесь это только прозрачный текст config/identity в зарезервированных data arrays: code не создаётся, не расшифровывается и не выполняется. Это документировано, чтобы release engineer или AV reviewer мог подтвердить безопасность. Не делайте ёмкости больше необходимого и добавляйте packaging step в allowlist. Любое product-specific antivirus exception фиксируйте в release-документации встраивающего проекта.
Packaging: подпись кода Windows
Упакованные Windows binaries можно подписать во время release, чтобы повысить доверие antivirus/SmartScreen к client. Self-update flow загружает и запускает runtime DLL, поэтому неподписанный client является главным heuristic trigger. Signing выключен по умолчанию, текущее поведение - unsigned, и не привязан к конкретному tool:
- Задайте
Packaging.CodeSigningHookв main config проекта как исполняемый script на packaging host. - Во время
finalize_output, до любого шага Zip/Tar/Wix/Raw,package.pyвызывает<hook> <absolute-pe-path>один раз для каждого*.exe/*.dllв package tree: launcher executables, включая OpenGL variant, runtime DLL и client-runtime update payloads. Подпись после patch покрывает финальные bytes; охват всего дерева подписывает archives, MSI и updater payloads. - Hook обязан завершаться с
0; ненулевой код останавливает package, поэтому release, для которого запросили signing, не выйдет unsigned. Hook должен запускаться непосредственно на host: shebang иchmod +xв Linux либо.cmd/.bat/.exeв Windows. - Hook владеет tool, certificate, timestamp URL и secrets. Храните passwords/tokens в environment variables, но не в repository или main config. Всегда используйте timestamp RFC-3161, чтобы signatures сохранялись после окончания cert.
Для публично доверенных signatures соблюдайте актуальные требования CA и
provider к хранению ключей; не предполагайте, что обычный .pfx на диске
допустим. Hook остаётся provider-neutral. Примеры форм интеграции:
# 1) Azure Trusted Signing on a Windows host through signtool and the provider dlib.
# Azure credentials come from environment variables (AZURE_* / managed identity).
# sign_windows.cmd (args: %1 = file)
# signtool sign /v /fd SHA256 /tr http://timestamp.acs.microsoft.com /td SHA256 ^
# /dlib "%TRUSTED_SIGNING_DLIB%" /dmdf "%TRUSTED_SIGNING_METADATA_JSON%" "%~1"
# 2) SSL.com eSigner CodeSignTool on a Linux packaging host (Java). Credentials/TOTP come from env.
# sign_windows.sh (args: $1 = file)
# CodeSignTool sign -username="$ESIGNER_USER" -password="$ESIGNER_PASS" \
# -totp_secret="$ESIGNER_TOTP" -input_file_path="$1" -override
# 3) osslsigncode on Linux with a PKCS#11 cloud-HSM certificate or hardware token.
# sign_windows.sh (args: $1 = file)
# tmp="$(mktemp)"; osslsigncode sign -pkcs11module "$PKCS11_MODULE" -key "$PKCS11_KEY_ID" \
# -certs "$CERT_PEM" -h sha256 -n "Example Game" -i https://example.com \
# -ts http://timestamp.digicert.com -in "$1" -out "$tmp" && mv -f "$tmp" "$1"
Для Android signing остаётся в Gradle, как описано в Android workflow выше; этот hook предназначен только для Windows.
Ключи защищённого канала
Статический ключ сервера для сетевого канала создаётся на том хосте, который хранит секрет:
python3 BuildTools/secure_channel_key.py generate /path/to/channel.key
python3 BuildTools/secure_channel_key.py public /path/to/channel.key
generate записывает 64 шестнадцатеричных знака в новый файл, доступный только владельцу, не перезаписывает существующий файл и выводит публичный ключ для закрепления в клиентах. public повторно выводит публичную половину имеющегося секрета. Для работы нужен только стандартный Python.
Форматирование исходного кода
buildtools.py format-source форматирует дерево Source/ Engine, включая
.fos, с помощью clang-format. discover_clang_format() разрешает binary в
таком порядке: override FO_CLANG_FORMAT, если задан, затем
clang-format-20/clang-format из PATH; разрешённый binary должен сообщать
major version 20. Затем BuildTools восстанавливает nullable и named-argument
forms AngelScript, которые clang-format разбирает как C++. Полный контракт и
граница встраивающего проекта описаны в
руководстве по стилю AngelScript и рефакторингу.
Срок временной совместимости
Код, распознающий старые сборки или данные, помечается FO_TEMPORARY_COMPAT(Id, "YYYY-MM-DD"); в native-части либо [TemporaryCompat("Id", "YYYY-MM-DD")] в managed-части; см. временную совместимость. temporary_compat.py сообщает все места с данным идентификатором и падает после истечения срока:
python3 BuildTools/temporary_compat.py # the engine Source tree
python3 Engine/BuildTools/temporary_compat.py Engine/Source SourceExt Scripts # an embedding project's directories
python3 BuildTools/temporary_compat.py --report # every marker and the days it has left
--today YYYY-MM-DD фиксирует дату для проверки. Сценарию достаточно стандартной библиотеки Python; его тесты находятся в tests/test_temporary_compat.py, а workflow validate запускает и тесты, и саму проверку.
Документация pipeline
Актуальное руководство по staged CMake pipeline находится в конвейер BuildTools.