219 lines
21 KiB
Markdown
219 lines
21 KiB
Markdown
# KaM r16020 — Android Architecture Probe 0.3.1
|
||||
|
|
|
|||
|
|
**Кодовый тест архитектуры: KaM core + Free Pascal + Castle Game Engine → Android.**
|
|||
|
|
|
|||
|
|
Здесь нет desktop target, готовой игры, игровых бинарных ресурсов или собственного заменителя KaM core. Тест не требует `data/` для проверки компиляции и линковки. Он проверяет, какие **настоящие исходные модули r16020** можно включить в Android-библиотеку вместе с Castle и где возникают конкретные препятствия.
|
|||
|
|
|
|||
|
|
**Архив содержит код стенда и автоматизацию, не заранее собранный APK.** Во время подготовки проверены Python-скрипты и их контрольные сценарии. Настоящая компиляция Pascal/Android здесь не выполнялась: FPC, Castle, Docker и ADB в среде подготовки отсутствовали. Подробнее: `reports/preparation/VALIDATION.md`.
|
|||
|
|
|
|||
|
|
## 1. Запуск на сервере — без ресурсов
|
|||
|
|
|
|||
|
|
Требуются Linux x86_64 или Linux-среда WSL2, Bash, Python **3.10+**, работающий Docker и доступ в интернет. Папка проекта должна быть доступна на запись. На сервере ARM64 Docker-образ Linux/amd64 потребует отдельно настроенной эмуляции; это не основной путь этого теста.
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
unzip kam-android-architecture-probe-r16020.zip
|
|||
|
|
cd kam-android-architecture-probe-r16020
|
|||
|
|
chmod +x build-android.sh test-harness.sh
|
|||
|
|
./build-android.sh
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Команда выполняет весь **Android ARM64** цикл, а не сборку Linux-версии игры:
|
|||
|
|
|
|||
|
|
1. Получает официальный Docker-образ инструментов CGE. При первом запуске фиксирует его неизменяемый digest в `config/toolchain.lock.json`; при следующих использует его же.
|
|||
|
|
2. Загружает **только текстовые исходники** KaM по commit `962fb850324b79bbe5480e1c2087d98f83a60917` и исходники PascalScript по gitlink из этого commit. Полный checkout, история Git, release-архивы и игровые ресурсы не скачиваются.
|
|||
|
|
3. Создаёт 15 изолированных Android-проектов: компилирует и полностью линкует каждый, продолжая остальные проверки после ошибки одной подсистемы.
|
|||
|
|
4. По умолчанию упаковывает три ключевых проекта в APK, когда их линковка успешна: `platform`, `core_types`, `integration`.
|
|||
|
|
5. Сохраняет результаты, конкретные ошибки, версии инструментов, идентификаторы исходников и архив журналов без содержимого ресурсов.
|
|||
|
|
|
|||
|
|
**Системные инструменты сборки — бинарные программы и будут скачаны Docker на сервере. Запрет на скачивание игровых бинарных ресурсов соблюдён; полностью автономный комплект SDK/NDK/FPC в этот ZIP не вложен.** Полный оригинальный код KaM также не вложен: его автоматически получает серверный загрузчик по фиксированному commit. В архиве нет ссылок на изменяемый `master` KaM.
|
|||
|
|
|
|||
|
|
`config/toolchain.lock.json` появляется при первом реальном получении Docker-образа, а не содержит выдуманный digest. Для одинакового окружения на другом сервере перенесите этот lock вместе с проектом. Сам первый выбор CGE-образа зависит от даты запуска; KaM всегда зафиксирован на r16020.
|
|||
|
|
|
|||
|
|
## 2. Что проверяется
|
|||
|
|
|
|||
|
|
| Проба | Реальные модули / граница | По умолчанию |
|
|||
|
|
|---|---|---|
|
|||
|
|
| `platform` | CGE + FPC: Android shell, системные потоки, файловые пути, zlib, изображение, input, audio API | Compile + native link + APK |
|
|||
|
|
| `core_types` | `KM_CommonTypes`, `KM_Points`; настоящие функции координат | Compile + native link + APK |
|
|||
|
|
| `core_streams` | `KM_CommonClasses`; настоящая сериализация и зависимости | Compile + native link |
|
|||
|
|
| `mission_tokens` | `KM_MissionScript` | Compile + native link |
|
|||
|
|
| `mission_info` | `KM_MissionScript_Info` | Compile + native link |
|
|||
|
|
| `terrain_io` | `KM_TerrainUtils` | Compile + native link |
|
|||
|
|
| `sprite_loader` | `KM_ResSprites` и его реальные зависимости | Compile + native link |
|
|||
|
|
| `terrain_pathfinding` | `KM_Terrain` и его реальные зависимости | Compile + native link |
|
|||
|
|
| `mission_world` | `KM_MissionScript_Standard` | Compile + native link |
|
|||
|
|
| `simulation` | `KM_Game` как исходный модуль, **не desktop executable** | Compile + native link |
|
|||
|
|
| `script_vm` | `uPSCompiler`, `uPSRuntime` из закреплённого PascalScript | Compile + native link |
|
|||
|
|
| `scripting` | `KM_ScriptingEvents` | Compile + native link |
|
|||
|
|
| `legacy_render` | `KM_Render`, диагностика прежнего backend | Compile + native link; необязательная проба |
|
|||
|
|
| `legacy_audio` | `KM_Sound`, диагностика прежнего backend | Compile + native link; необязательная проба |
|
|||
|
|
| `integration` | Основные корни KaM **вместе с Castle в одной Android-библиотеке** | Compile + native link + APK |
|
|||
|
|
|
|||
|
|
Никаких `test_shims`, пустых `KM_*.pas` вместо оригиналов или самостоятельно переписанных MAP/RXX readers в сборочных проектах нет. Модули с транзитивными зависимостями компилируются как есть; их ошибка не скрывается.
|
|||
|
|
|
|||
|
|
Используется один уже существующий upstream define: **`DBG_SKIP_SECURE_AUTH`**. Он отключает необязательный приватный модуль аутентификации multiplayer, недоступный в обычном исходном комплекте. Это локальный Android-проект, не тест сетевого сервиса. Define записывается в каждый соответствующий `target.json`. Остальные игровые подсистемы не отключаются для получения зелёного отчёта.
|
|||
|
|
|
|||
|
|
Линковка не отключена через `-Cn`. Стенд запрашивает пересборку (`-B`), отключает smart linking/удаление неиспользуемых секций и включает проверку undefined symbols. Это намеренно более строгая проверка зависимостей, чем пустой вызов одной функции с выброшенным остальным кодом. Проверяются свежие корневые `.ppu`, ELF нужного ABI, отсутствие `DT_TEXTREL`, структура APK и его native dependencies. Если упаковщик удалил только debug symbols, библиотека сопоставляется по неизменным allocated sections и program headers, а не ошибочно отклоняется из-за другой полной SHA-256. Подпись APK проверяется `apksigner`, когда он найден; иначе проверка подписи помечена `NOT_RUN`.
|
|||
|
|
|
|||
|
|
## 3. Результаты и коды возврата
|
|||
|
|
|
|||
|
|
Начинайте с:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
reports/LATEST-SUMMARY.md
|
|||
|
|
reports/LATEST.json
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Полный результат конкретного запуска:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
reports/runs/<build-id>/SUMMARY.md
|
|||
|
|
reports/runs/<build-id>/result.json
|
|||
|
|
reports/runs/<build-id>/<profile>/compile-link.log
|
|||
|
|
reports/runs/<build-id>/<profile>/package.log
|
|||
|
|
reports/runs/<build-id>/source-inventory.json
|
|||
|
|
reports/runs/<build-id>/evidence.zip
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
При успешной упаковке:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
dist/<build-id>/kam_probe_platform-aarch64-debug.apk
|
|||
|
|
dist/<build-id>/kam_probe_core_types-aarch64-debug.apk
|
|||
|
|
dist/<build-id>/kam_probe_integration-aarch64-debug.apk
|
|||
|
|
dist/LATEST.json
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Каждый APK появляется **только если соответствующая проба действительно собрана и упакована**. Ошибка `integration` не удаляет успешно полученный `platform` APK. Старые артефакты лежат в своих каталогах build-id и не засчитываются в новый результат.
|
|||
|
|
|
|||
|
|
| Итог | Exit code | Значение |
|
|||
|
|
|---|---:|---|
|
|||
|
|
| `ANDROID_BUILD_GATE_PASS` | 0 | Все обязательные Android compile/link-пробы и три обязательных APK прошли. Runtime ещё не подразумевается. |
|
|||
|
|
| `NOT_BUILDABLE_AS_IS` | 1 | Обязательная проба встретила ошибку компиляции, линковки или упаковки. Смотреть конкретный журнал. |
|
|||
|
|
| `BLOCKED` | 2 | Проверке мешает отсутствующий инструмент, исходник, окружение или другой незавершённый этап. Не успех. |
|
|||
|
|
| `PARTIAL_SELECTION` | 2 | Выбрана лишь часть профилей. Даже успешный platform APK не считается подтверждением всего core. |
|
|||
|
|
|
|||
|
|
Отдельные неудачи `legacy_render`/`legacy_audio` не требуют сохранения старых backend и не проваливают gate сами по себе. Но если эти зависимости реально входят в обязательный KaM-корень, ошибка будет видна и заблокирует этот корень.
|
|||
|
|
|
|||
|
|
**`PASS` означает только указанную проверку.** Компиляция `KM_Game` не означает, что экономика/AI уже запущены, и ошибка `Graphics` не означает «весь KaM нужно переписать». Результат даёт конкретную точку для небольшого Android-адаптера, доработки или подключения существующей библиотеки. Матрица интерпретации есть в `SUMMARY.md` и `docs/COVERAGE.md`.
|
|||
|
|
|
|||
|
|
## 4. Другие режимы
|
|||
|
|
|
|||
|
|
Уже установленный CGE/FPC Android toolchain, без Docker:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
./build-android.sh --local
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
`--local` означает использовать инструменты сервера; **target остаётся Android**. `castle-engine`, `fpc`, Java, Android SDK/NDK и cross-compiler должны быть согласованно настроены. Стенд не устанавливает SDK через root и не изменяет системную конфигурацию.
|
|||
|
|
|
|||
|
|
Повторный запуск с уже загруженным и проверенным кодом:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
./build-android.sh --no-fetch
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Только проверка Android shell и типов:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
./build-android.sh --profiles platform,core_types
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Получить APK для каждой успешно слинкованной пробы:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
./build-android.sh --package-all
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Другие Android ABI, отдельные запуски:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
./build-android.sh --cpu arm
|
|||
|
|
./build-android.sh --cpu x86_64
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Android x86_64 — вариант для соответствующего Android-устройства/эмулятора, **не десктопная сборка**. Успех одного ABI не засчитывается за другой.
|
|||
|
|
|
|||
|
|
Пути к дополнительному исходному пакету или Android native libraries задаются в `config/extra-paths.json`. Пути относительно корня проекта предпочтительны, чтобы одинаково работать внутри Docker и снаружи. По умолчанию списки пусты. Стенд не подставляет другую библиотеку автоматически и не принимает extra path, который обнаруженно перекрывает оригинальный KaM unit.
|
|||
|
|
|
|||
|
|
## 5. Ресурсы — позже, на вашем сервере
|
|||
|
|
|
|||
|
|
Для исходной проверки сборки этот раздел можно полностью пропустить.
|
|||
|
|
|
|||
|
|
Положите рядом каталоги установленной игры, сохранив имена и регистр:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
/srv/kam-r16020/
|
|||
|
|
data/
|
|||
|
|
SpriteResource/
|
|||
|
|
Maps/
|
|||
|
|
MapsMP/
|
|||
|
|
Campaigns/
|
|||
|
|
Tutorials/
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Содержимое собираете вы из соответствующих установок. Стенд не получает игровые файлы из сети. В Docker папка монтируется read-only; в отдельные сборочные каталоги помещаются её точные копии.
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
./build-android.sh --assets /srv/kam-r16020
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Это добавляет ресурсы в упаковываемые KaM-пробы (`core_types`, `integration`, либо выбранные с `--package-all`). Независимый `platform` остаётся без игровых ресурсов. Для каждой копии на сервере проверяется SHA-256. При запуске Android получает файлы из assets и копирует в приватный каталог приложения для обычных `TFileStream`-путей, проверяя размер копии. Никакой конвертации `.map/.dat/.rxx` нет.
|
|||
|
|
|
|||
|
|
**Добавление файлов не запускает миссию автоматически.** Этот режим проверяет доставку данных и нативные файловые пути, а не полноценное декодирование/создание мира. Runtime checksum оригинальных ресурсов и штатные загрузки мира не заявлены как выполненные проверки этого стенда. Большой комплект может заметно увеличить APK, время инициализации и занятое место; для проверки сборки он не нужен.
|
|||
|
|
|
|||
|
|
Не передавайте проприетарные файлы через публичный Git. `private-assets/`, `vendor/`, `build/`, `dist/` исключены в `.gitignore`. В `evidence.zip` содержимого ресурсов нет, но имена/размеры/хеши могут присутствовать в metadata — просмотрите их перед публичной публикацией.
|
|||
|
|
|
|||
|
|
## 6. Запуск APK на Android — дополнительный этап
|
|||
|
|
|
|||
|
|
Для ответа «собирается ли выбранная архитектура?» достаточно серверного compile/link/package-отчёта. Проверка запуска — отдельное свидетельство.
|
|||
|
|
|
|||
|
|
На машине с ADB и одним авторизованным Android-устройством:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
python3 tools/device.py --profile platform --exercise-lifecycle
|
|||
|
|
python3 tools/device.py --profile core_types --exercise-lifecycle
|
|||
|
|
python3 tools/device.py --profile integration --exercise-lifecycle
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Указывать профиль имеет смысл только после получения его APK. Несколько устройств: добавьте `--serial <serial>`. Скрипт устанавливает/обновляет **только выбранное тестовое приложение**, запускает его и читает приватный отчёт через `run-as`. Старый `runtime.json` этого теста удаляется перед запуском; ресурсы, настройки игры и сохранения не очищаются. ADB не запускается внутри стандартного Docker build-контейнера.
|
|||
|
|
|
|||
|
|
В APK: процедурная клеточная картинка, drag/pinch/tap, кнопки сохранения отчёта и звука. Автоматически проверяются ABI, native-файлы/seek, FPC zlib, поток и frame callbacks. В профильных APK вызываются настоящие `KMPoint`/`KMPointRight`; в `core_streams` и `integration` — `TKMemoryStreamBinary`. Успешное достижение UI также показывает, что unit initialization импортированного набора не прервало запуск.
|
|||
|
|
|
|||
|
|
Вывод находится в `reports/device/<timestamp>/`. Видимое изображение, удобство жестов и слышимый звук требуют наблюдения: возвращение `SoundEngine.Play` не подменяет проверку звука. КаМ-terrain, здания и симуляция этим APK не изображаются.
|
|||
|
|
|
|||
|
|
## 7. Проверка самого стенда
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
./test-harness.sh
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Это Python unit/integration tests инструментария без сети, Docker и ресурсов. Они проверяют выбор исходников, пути, gate, генерацию проектов, ELF/APK parser, отказ при старом/неверном артефакте, отказ при пустом выводе компилятора, продолжение после ошибки и приватность evidence.
|
|||
|
|
|
|||
|
|
**Сквозные контрольные тесты используют явно помеченные временные test doubles компилятора/ELF/APK.** Это тестирование управления сборкой, не эмуляция настоящего KaM и не доказательство компиляции Pascal. Test doubles существуют только в `TemporaryDirectory`; в реальные targets и результаты Android они не попадают.
|
|||
|
|
|
|||
|
|
## 8. Структура
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
build-android.sh Единственная точка входа сборки
|
|||
|
|
code/ Общий Android/CGE runtime стенда
|
|||
|
|
tools/ Загрузка исходников, 15 targets, сборка, аудит, ADB
|
|||
|
|
config/profiles.json Корни проверяемых подсистем
|
|||
|
|
config/upstream.json Зафиксированная база
|
|||
|
|
config/extra-paths.json Явно добавленные зависимости (изначально пусто)
|
|||
|
|
tests/ Тесты инструментария; не игровое ядро
|
|||
|
|
reports/preparation/ Проверки, реально выполненные при подготовке ZIP
|
|||
|
|
docs/ Границы доказательств, источники, разбор ошибок
|
|||
|
|
vendor/ Источники появляются при запуске на сервере
|
|||
|
|
private-assets/ Необязательное закрытое место ваших данных
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
`CastleEngineManifest.xml`, `ProbeBuild.pas`, `ProbeImports.pas` создаются отдельно для каждого профиля в `build/<build-id>/<profile>/`. Корень ZIP сам по себе не является одним CGE-проектом; запускайте `build-android.sh`, а не `castle-engine compile` без target из корня.
|
|||
|
|
|
|||
|
|
Полноценный порт не требуется для этого теста. Следующее решение принимается по реальному серверному отчёту: устранить обнаруженный общий блокер и повторить те же Android-пробы, не переписывать работающие игровые подсистемы заранее.
|
|||
|
|
|
|||
|
|
## 0.3.1 — correction after first server report
|
|||
|
|
|
|||
|
|
- Removed global FPC `-Mdelphi`. KaM units already select Delphi mode through `KaM_Remake.inc`; forcing it globally also changed Castle Game Engine units and broke `CastleLocalizationGetText` before any KaM code was compiled.
|
|||
|
|
- Source inventory now reads Pascal files with `utf-8-sig`, so UTF-8 BOM files such as `src/game/KM_Game.pas` are recognized.
|
|||
|
|
- Added regression tests for both failures.
|