FOnline Engine
Current master GitHub
Документация Docs/ru/how-to/native-extensions/project-dependencies.md

Проектные зависимости

Это руководство определяет переиспользуемый контракт для библиотек, SDK, фреймворков, инструментов и файлов среды выполнения, которые добавляет игровой репозиторий, подключающий FOnline. Оно охватывает зависимости, необходимые игре, но не принадлежащие переиспользуемому движку.

Для исходников, вендоризованных в Engine/ThirdParty/, используйте раздел Сопровождение ThirdParty. Мост C++, потребляющий проектную зависимость, описан в разделе Нативные расширения. Подключающий проект обязан хранить точный реестр зависимостей, продуктовые интеграции, учётные данные, поставщиков и релизную политику в собственном репозитории.

Решение по зависимости

Для каждой проектной зависимости используйте такую последовательность:

  1. Сначала классифицируйте владельца: Engine, встраивающий проект, версионируемый companion, проектный build tool или требование операционной системы. Регистрация через helpers Engine не передаёт проектное владение.
  2. Выберите и закрепите модель доставки, затем запишите в проекте версию, происхождение, целостность, лицензию, поддерживаемые платформы и toolchains, путь обновления и rollback pin.
  3. Создайте проектную цель после появления third-party targets Engine и до того, как BuildCoreLibraries() потребит привязанные к ревизии списки библиотек. Добавляйте её только в необходимые FO_COMMON_LIBS, FO_SERVER_LIBS, FO_CLIENT_LIBS, FO_BAKER_LIBS или FO_TESTING_LIBS.
  4. Разделяйте состояния requested, compiled и initialized at runtime. Явно сохраняйте владение allocator, exceptions, CRT/toolchain, architecture, generated headers и границы C ABI, а не считайте наличие headers доказательством runtime support.
  5. Рассматривайте development copy и release payload отдельно. Через package declarations объявите runtime files, target paths, notices, runtime file hashes и signatures или владельца signing. Затем запускайте и проверяйте упакованный artifact из изолированного каталога на каждой заявленной платформе.

Полная запись release delivery отдельно называет каждый класс evidence: package declarations, licenses и notices, runtime-file hashes, signatures или владельца signing и изолированный запуск упакованного artifact. Один из этих классов не заменяет остальные.

Не останавливайтесь на успешном include или link. Приёмка должна доказать задуманные состояния requested, compiled и initialized, ABI shared library и владение allocator, payload и целостность пакета, а также изолированное runtime-поведение.

Статус контракта

Проектный интерфейс CMake имеет статус experimental и привязан к ревизии. Текущий Engine не предоставляет объявленную helper-команду для role-scoped регистрации project libraries. Подключающие проекты добавляют targets в текущие списки библиотек, которые являются implementation state и могут меняться с ревизией Engine. Закрепляйте Engine, заново проверяйте списки и пересобирайте зависимости и extensions вместе после каждого изменения pin.

Движок отвечает за:

  • списки библиотек COMMON, SERVER, CLIENT, BAKER и TESTS;
  • core-library targets, потребляющие эти списки;
  • граф базовых библиотек, потребляющий список каждой роли;
  • объявления пакетов и общие механизмы их сборки;
  • документированные правила аллокаторов, указателей, исключений и нативных расширений.

Подключающий проект отвечает за:

  • выбор зависимости, версию, источник, целостность, лицензию и срок поддержки;
  • цель CMake, условие включения функции, назначение роли и заглушку неподдерживаемого режима;
  • сгенерированные заголовки, инструменты сборки, платформенные требования и совместимость ABI;
  • библиотеки среды выполнения, файлы данных, уведомления, подписание и приёмку пакета;
  • реакцию на уязвимости, периодичность обновлений, откат, тесты и релизные свидетельства.

Регистрация никогда не передаёт владение движку. Библиотека становится зависимостью движка только через явное изменение движка, которое переносит реализацию, тесты, запись сопровождения и обязательства по поддерживаемым платформам.

Сначала выберите владельца

Классифицируйте зависимость до добавления файлов или CMake:

Потребность Владелец и расположение Правило
Переиспользуемая среда выполнения, формат, рендерер или инструмент движка Движок, обычно Engine/ThirdParty/<name>/ Следуйте процессу вендоризации движка и проверке публичного контракта.
Нативный мост только для игры, клиент сервиса, проприетарный SDK или среда выполнения контента Подключающий проект, обычно SourceExt/<name>/ или Dependencies/<name>/ Оставляйте реализацию, политику и релизные свидетельства во владении проекта.
Переиспользуемая необязательная интеграция, не подходящая для ядра движка Версионируемый сопутствующий репозиторий Публикуйте точный диапазон совместимости с движком, собственные тесты и минимальный пример подключения.
Генератор или средство аудита времени сборки, не линкуемое с ролями движка Дерево проектных инструментов Закрепляйте его среду выполнения и пакеты отдельно и не добавляйте его в роль движка.
Фреймворк операционной системы или библиотека хоста Платформенная конфигурация проекта Укажите поддерживаемые хосты и завершайте конфигурацию ошибкой при отсутствии обязательного компонента.

Не дублируйте зависимость движка в проекте только для получения доступа к её заголовкам или цели. Если проекту намеренно нужна другая сборка или версия, документируйте изоляцию символов, границы аллокатора и ABI, область платформ и причину, по которой нельзя использовать копию движка.

Выберите модель доставки

Используйте минимальную модель, обеспечивающую детерминированную сборку и законную доставку:

  1. Вендорные исходники предпочтительны, когда проект должен собирать библиотеку на всех поддерживаемых хостах, применять небольшой проверенный патч или исключить расхождение версий на хостах. Закрепите версию upstream и хеш архива, сохраните обязательные уведомления и зафиксируйте обрезку.
  2. Импортированная цель SDK подходит для проприетарного или предварительно собранного SDK. Закрепите релиз SDK, архитектуру, совместимость с компилятором и средой выполнения, источник получения, разрешённые к распространению файлы и условия лицензии. Не коммитьте материалы, распространение которых запрещено лицензией.
  3. Системная или платформенная библиотека подходит для API ОС или намеренно поддерживаемой внешней зависимости хоста. Ограничьте использование явными платформенными проверками и подтвердите минимальный поддерживаемый хост. Успешное обнаружение на машине разработчика не является переносимым контрактом зависимости.
  4. Менеджер пакетов или загружаемые исходники допустимы только с неизменяемой версией или коммитом и фиксацией целостности. Релизные и CI-сборки не должны незаметно выбирать более новый пакет или зависеть от непроверенного сетевого ответа.
  5. Файл только для среды выполнения подходит для динамической библиотеки, вспомогательного исполняемого файла, модели или данных, которые не компилируются. Для него всё равно нужны версия, происхождение, соответствие платформе и архитектуре, лицензионное решение, правило упаковки и приёмочный тест запуска.

Не используйте незакреплённую ветку, плавающий диапазон пакетов, неявный путь включения или незарегистрированный результат find_package() как входные данные production-сборки.

Ведите запись о зависимости

Для каждой проектной зависимости должна существовать одна авторитетная запись в подключающем репозитории. Это может быть таблица, манифест или README самой зависимости, но она обязана отвечать на следующие вопросы:

Поле Обязательное содержимое
Идентичность Имя upstream, имя проектной цели, владелец и контакт поддержки.
Версия Точный релиз, тег или коммит и метаданные исходников или пакета, которыми он подтверждается.
Происхождение Официальный URL источника или идентичность закрытого артефакта, а также хеш архива или коммита.
Доставка Вендорная, импортированный SDK, системная, загружаемая, только для инструментов или только для среды выполнения.
Лицензия Идентификатор лицензии, сохранённые файлы, атрибуция, обязательства по распространению и предоставлению исходников.
Интеграция Потребляющие роли движка, нативный мост, флаг функции, сгенерированные файлы и хук аллокатора.
Поддержка Платформы, архитектуры, цепочки инструментов, конфигурации и поведение неподдерживаемого режима.
Пакет Файлы среды выполнения, целевые пути, владелец подписания и приёмочная проверка.
Безопасность Источник бюллетеней, периодичность проверки, граница секретов и путь экстренного отключения или удаления.
Обновление Локальные патчи, запись об обрезке, связанные с совместимостью ресурсы и данные, тесты и закреплённая версия отката.

Если исходный код зависимости публикует версию, он является для неё авторитетным источником. Синхронизируйте человеческие реестры с этим значением; текстовая версия в документации не должна быть источником истины для сборки.

Интегрируйте на границе проекта

Создавайте цели проектных зависимостей после того, как стадия ThirdParty движка создала переиспользуемые цели движка, и до того, как BuildCoreLibraries() потребит списки ролей. Как обычно, регистрируйте проектные исходники до RegisterEngineSources():

StartProjectGeneration()
RegisterProjectOptions()

# Register handlers needed by Engine or project third-party CMake before the
# ThirdParty stage installs its find_package() interceptor.
RegisterFindPackageHandler(OptionalBackend NotFoundFindPackage)
AddThirdPartyLibraries()

add_subdirectory(Dependencies/ProjectCodec EXCLUDE_FROM_ALL)

# A project wrapper gives one stable target for upstream target-name changes,
# include classification, compile definitions, and transitive requirements.
add_library(ProjectCodec INTERFACE)
target_link_libraries(ProjectCodec INTERFACE upstream_codec)
target_include_directories(ProjectCodec SYSTEM INTERFACE
    "${CMAKE_CURRENT_SOURCE_DIR}/Dependencies/ProjectCodec/include")

list(APPEND FO_CLIENT_LIBS ProjectCodec)
list(APPEND FO_BAKER_LIBS ProjectCodec)

AddEngineSources(CLIENT SourceExt/ProjectCodecBridge.cpp)
RegisterEngineSources()
SetupCodeGeneration()
BuildCoreLibraries()

Текущая ревизия потребляет FO_COMMON_LIBS, FO_SERVER_LIBS, FO_CLIENT_LIBS и FO_BAKER_LIBS при создании соответствующих core libraries; FO_TESTING_LIBS поступает в native test targets. Добавляйте значения до BuildCoreLibraries(), самостоятельно избегайте дубликатов и завершайте configure ошибкой для неподдерживаемых комбинаций. Отдельного mapper-only списка библиотек нет: MapperLib потребляет ClientLib, поэтому client dependency достигает Mapper вместе с более широкой client role. Для действительно mapper-only dependency нужно явное изменение интерфейса Engine, а не выдуманная переменная FO_MAPPER_LIBS.

Эти списки являются привязанным к ревизии integration state, а не helper-командами из BuildTools/cmake/ProjectInterface.json. При каждом обновлении Engine заново проверяйте State.cmake и CoreLibs.cmake. Наличие helper в BuildTools/cmake не сделало бы её публичной без объявления в interface manifest.

Направляйте в самую узкую роль

Роли зависимостей соответствуют ролям нативных исходников:

Роль Владелец линковки Обычные потребители Назначение
COMMON CommonLib Каждая включённая роль среды выполнения или инструмента Действительно общий примитив процесса или конфигурации. Не помещайте сюда клиентский или серверный SDK только для удобства.
SERVER ServerLib Сервер и нативные тесты, которые его подключают Авторитетная логика, персистентность, серверный транспорт или код серверного SDK.
CLIENT ClientLib Клиент, а также текущие пути контроллера сервера, Mapper, просмотрщиков, Baker, ASCompiler и тестов Рендеринг, ввод, клиентский транспорт или код клиентского SDK. Учитывайте более широкий текущий граф потребителей.
BAKER BakerLib Baker, Mapper, просмотрщики, ASCompiler и тесты Импорт, проверка, преобразование ресурсов или поддержка авторинга.
TESTS Native test targets Принадлежащие Engine native tests Сфокусированная test-only поддержка; не используйте её для runtime delivery.

Разделяйте обёртку зависимости, если разным ролям нужны разные заголовки, функции или файлы среды выполнения. Не направляйте библиотеку через COMMON только ради устранения неразрешённого символа.

Контролируйте обнаружение пакетов

Стадия ThirdParty перехватывает find_package(), чтобы вложенный CMake сторонней зависимости не мог незаметно использовать произвольные библиотеки хоста. Зарегистрируйте каждое ожидаемое имя пакета до AddThirdPartyLibraries():

  • сопоставьте пакет с вендорной или импортированной целью в проектном обработчике;
  • используйте NotFoundFindPackage для поддерживаемого необязательного бэкенда, который должен оставаться отключённым;
  • используйте PassThroughFindPackage только для намеренной зависимости хоста с документированными установкой и минимальной версией;
  • позволяйте незарегистрированному поиску завершить конфигурацию ошибкой, после чего явно принимайте решение о владельце.

Не отключайте перехватчик и не добавляйте широкий резервный путь. Вложенные необязательные проверки зависимости входят в её цепочку поставки и область поддержки.

Изолируйте заголовки, предупреждения и сгенерированные файлы

Публикуйте заголовки зависимости через её цель, предпочтительно с target_include_directories(... SYSTEM ...), а не через общий для репозитория путь включения. Заголовки проектного моста должны оставаться не системными, чтобы проектные предупреждения продолжали считаться ошибками.

Определения компилятора и сгенерированные заголовки должны принадлежать узкой цели-обёртке, которой они нужны. Гарантируйте запуск генераторов до потребляющих целей, вывод в дерево сборки и участие в чистых сборках. Не регистрируйте вендорное дерево исходников через AddEngineSources: каждый зарегистрированный файл проходит анализ метаданных и кодогенерации, предназначенный для объявлений проектного расширения, а не произвольного стороннего кода.

Если добиться чистого от предупреждений upstream-кода непрактично, ограничьте настройки предупреждений сторонней целью. Не снижайте уровень предупреждений глобально и не подавляйте диагностику в проектном мосте.

Определите платформенный контракт

Для каждой необязательной или платформенной зависимости:

  1. предоставьте проектную опцию функции с детерминированным значением по умолчанию;
  2. во время конфигурации проверьте платформу, архитектуру, заголовки, импортируемую или статическую библиотеку и файл среды выполнения;
  3. определите один макрос доступности по окончательному результату;
  4. компилируйте независимую от зависимости заглушку, если общий скриптовый или нативный символ должен сохраняться;
  5. явно сообщайте о неподдерживаемом использовании во время выполнения вместо ложного успеха;
  6. проверяйте как минимум по одной сборке с включённой и отключённой функцией;
  7. синхронизируйте матрицу пакетов со скомпилированной доступностью.

Различайте три состояния: запрошено, скомпилировано и инициализировано во время выполнения. Наличие заголовков не доказывает загрузку соответствующей библиотеки среды выполнения, предоставление учётных данных или доступность внешнего сервиса.

Упаковывайте файлы среды выполнения

Статические зависимости из исходников могут не добавлять файлов среды выполнения, но всё равно накладывать лицензионные обязательства. Динамические или импортированные SDK обычно требуют платформенную и архитектурную библиотеку рядом с приложением. Инструментам могут требоваться вспомогательные исполняемые файлы или пакеты данных.

Используйте объявления пакетов, описанные в разделе Упаковка и релиз, чтобы включить каждый обязательный файл и уведомление. Копирование после сборки удобно для локального запуска, но не является правилом релизного пакета. Приёмка должна запускать артефакт из изолированного каталога и проверять функцию достаточно глубоко, чтобы обнаружить отсутствующий файл или неверную архитектуру.

Записывайте хеши файлов среды выполнения в происхождение релиза. Выполняйте подписание или нотаризацию на принадлежащей релизу границе и проверяйте подписи после сборки пакета. Никогда не помещайте закрытые учётные данные SDK, токены сервисов, ключи подписания или секреты сервера лицензий в исходники, значения CMake cache по умолчанию, сгенерированные метаданные, примеры, журналы или документацию.

Соблюдайте ABI, аллокацию и время жизни

Собирайте зависимости из исходников с совместимой политикой компилятора, архитектуры, среды выполнения C/C++, исключений, RTTI и конфигурации. Для готового SDK используйте только поддерживаемую поставщиком комбинацию и завершайте конфигурацию ошибкой для неподдерживаемых вариантов.

Не передавайте владение контейнерами, строками, исключениями или владеющими указателями движка через недокументированный ABI динамической библиотеки. Преобразуйте данные в мосте, сохраняйте владение аллокатором на стороне, создавшей объект, и по возможности предоставляйте небольшой нативный для SDK или C ABI.

Проверяйте реализацию хуков аллокатора зависимости, а не только их публичное объявление. Если библиотека может использовать аллокатор движка, подключите хук с правильным жизненным циклом и проверьте симметрию выделения, перераспределения и освобождения, выровненное выделение и порядок остановки. В противном случае зафиксируйте использование отдельной кучи и не включайте её объекты в предположения о владении и статистике движка. На границе следуйте разделам Essentials и Умные указатели.

Глобальное состояние SDK должно иметь явную общепроцессную семантику. Состояние отдельного клиента, сервера или тестового экземпляра принадлежит экземпляру движка или проекта; инициализируйте и останавливайте его через владеющий путь жизненного цикла, включая неудачную частичную инициализацию.

Проверяйте лицензию и риски цепочки поставки

Перед первым использованием и каждым обновлением:

  • получайте релиз из официального upstream или одобренного закрытого источника;
  • проверяйте закреплённый коммит или архив и сохранённый хеш;
  • изучайте заметки к релизу, поддерживаемые цепочки инструментов, изменения лицензии и бюллетени безопасности;
  • сохраняйте лицензии, уведомления, атрибуцию, журнал изменений и материалы предложения исходников, обязательные для модели распространения;
  • ведите реестр локальных патчей и удалённых файлов;
  • сканируйте пакет на случайные архивы исходников, учётные данные, отладочные вспомогательные средства и неодобренные файлы среды выполнения;
  • фиксируйте путь экстренного отключения, понижения версии или удаления.

Движок не определяет совместимость лицензии зависимости с коммерческой моделью игры или способом распространения. Это проектный юридический и релизный шлюз, а не вывод из успешной сборки.

Процесс обновления

  1. Зафиксируйте старую и новую идентичность зависимости и текущие ревизии движка и проекта.
  2. Подготовьте кандидата вне авторского дерева и проверьте происхождение.
  3. До замены файлов изучите лицензию, бюллетени, изменения API и ABI, требования сборки и поддержку платформ.
  4. Повторно примените документированную обрезку и минимальные локальные патчи. Единообразно отмечайте проектные изменения согласно политике проекта.
  5. Обновите авторитетную запись версии, хеш целостности, уведомления, условия включения, правила упаковки, связанные с совместимостью ресурсы и данные и владеющую документацию.
  6. Повторно сконфигурируйте каждый затронутый платформенный путь, чтобы закэшированное обнаружение не скрывало отсутствующую зависимость или устаревшую цель.
  7. Соберите каждую потребляющую роль движка и выполните сфокусированные тесты моста.
  8. Соберите изолированный пакет, проверьте хеши и подписи файлов среды выполнения и протестируйте включённое и отключённое поведение.
  9. Зафиксируйте ошибки, свидетельства и закреплённую версию отката. Сохраняйте предыдущий одобренный артефакт до завершения приёмки.

Если движок и зависимость обновляются одновременно, проверяйте их как два диапазона совместимости. Не приписывайте успешную итоговую сборку одному из изменений без узкой проверки или свидетельства, допускающего бисекцию.

Матрица проверки

Как минимум зафиксируйте:

Граница Обязательное доказательство
Интерфейс cmake -P BuildTools/tests/validate_project_interface.cmake и актуальный сгенерированный справочник CMake.
Конфигурация Чистая конфигурация для каждой затронутой платформы и архитектуры, а также обязательных включённых и отключённых состояний функции.
Компиляция и линковка Каждый изменённый проектом core/test список; project bridge без предупреждений и target-scoped dependency policy.
Кодогенерация и скрипты Перегенерированные метаданные и запекание ресурсов при изменении нативного объявления или сгенерированного заголовка.
Среда выполнения Сфокусированные пути успеха, недоступности, ошибки инициализации и остановки.
Пакет Изолированный запуск, наличие, хеш и архитектура файла среды выполнения, уведомления и сканирование артефакта на секреты.
Обновление Сравнение старой и новой закреплённых ревизий движка, проверка совместимости зависимости и отсутствие повторно используемых нативных или сгенерированных бинарных файлов старой ревизии.

Минимальный проект Engine компилирует project dependency INTERFACE, добавляя её в FO_SERVER_LIBS; его server extension не компилируется без usage requirement. Это доказывает текущий привязанный к ревизии путь линковки, не выдавая его за стабильную helper-команду и не превращая внешний SDK в часть fixture.

Маршрутизация ошибок

Симптом Что проверить сначала
Library не достигает consumer Выбранный список FO_*_LIBS, текущий CoreLibs.cmake и порядок стадий.
Заголовок найден локально, но не в CI Область путей включения цели-обёртки и случайные неявные пути включения.
Ошибка незарегистрированного find_package() Вложенную проверку зависимости и явное решение обработчика.
Расширение компилируется, но другая роль не линкуется Узкое назначение роли, транзитивные требования цели и фактический граф потребителей базовых библиотек.
Библиотека среды выполнения отсутствует или имеет неверную архитектуру Объявление пакета, расположение импортированной цели, различие между копированием после сборки и упаковкой и матрицу артефактов.
Сбой при аллокации или остановке Соответствие аллокатора и освобождения, владение через ABI, время жизни глобального состояния и очистку после частичной инициализации.
Функция заявлена доступной, но не инициализируется Разделение состояний «запрошено/скомпилировано/во время выполнения» и предоставление учётных данных или сервиса.
После обновления компиляция проходит, но ресурсы не работают Авторские данные, связанные с версией, формат генератора и среды выполнения и реальную проверку во время выполнения.

Проверенные исходные пути

  • BuildTools/Init.cmake
  • BuildTools/cmake/ProjectInterface.json
  • BuildTools/cmake/helpers/Build.cmake
  • BuildTools/cmake/helpers/State.cmake
  • BuildTools/cmake/stages/ThirdParty.cmake
  • BuildTools/cmake/stages/CoreLibs.cmake
  • BuildTools/cmake/stages/Packages.cmake
  • Examples/MinimalProject/CMakeLists.txt
  • Examples/MinimalProject/StarterServerExtension.cpp

См. также

Введите запрос.