Контекст
Связано с IngvarConsulting/unica#170: тестовое расширение TESTS использует API расширения YaXUnit и должно собираться/загружаться вместе с ним и основной конфигурацией.
Проверено на:
v0.5.1;
v0.5.2-pre.1 / current master (be558db1c456f2d3a828c0f4de121b980ba6ccdc).
Сейчас source-set содержит только name, type и path: SourceSetSchema.
Validator проверяет только глобальное условие «если существует EXTENSION, должна существовать хотя бы одна CONFIGURATION», но не связывает конкретное расширение с базовой конфигурацией или другим расширением: validate_source_sets.
Проблема
В реальном проекте расширения могут зависеть от API других расширений:
main CONFIGURATION
└── yaxunit EXTENSION
└── TESTS EXTENSION
Текущий canonical order группирует все конфигурации, затем все расширения, сохраняя YAML-порядок внутри группы: ordered_source_sets.
Это позволяет вручную поставить YaXUnit перед TESTS, но не фиксирует причинную связь. Порядок декларации становится скрытым operational contract.
Дополнительно build --source-set TESTS выбирает только TESTS, без основной конфигурации и YaXUnit: selected_ordered_source_sets.
test yaxunit частично маскирует проблему, поскольку перед тестом запускает build всех source-set с source_set: None: run_tests coordinator.
Это operational co-loading всех расширений, а не dependency contract. Из-за этого полный тестовый запуск может работать, а scoped build на чистой ИБ — зависеть от уже установленного состояния или завершаться ошибкой.
Минимальное воспроизведение
source-set:
- name: main
type: CONFIGURATION
path: src/cf
- name: yaxunit
type: EXTENSION
path: vendor/yaxunit
- name: TESTS
type: EXTENSION
path: src/cfe/TESTS
Условия:
TESTS вызывает экспортный API YaXUnit.
- Полный
build обрабатывает элементы только по category/YAML order.
build --source-set TESTS не включает main и yaxunit.
- В
v8project.yaml невозможно выразить, что TESTS требует YaXUnit.
Предлагаемый контракт
Добавить optional source-set[].dependsOn — список stable source-set.name непосредственных зависимостей:
source-set:
- name: main
type: CONFIGURATION
path: src/cf
- name: yaxunit
type: EXTENSION
path: vendor/yaxunit
dependsOn:
- main
- name: TESTS
type: EXTENSION
path: src/cfe/TESTS
dependsOn:
- yaxunit
Семантика A.dependsOn: [B]:
B должен быть успешно построен/загружен раньше A;
- scoped operation для
A включает B;
- транзитивные зависимости
B также включаются;
- связь направленная и не означает обратной зависимости
B → A.
Closure для примера:
Validation contract
До любого platform call необходимо проверять:
- каждое имя dependency существует;
- self-reference и повторяющиеся зависимости запрещены;
- dependency target имеет тип
CONFIGURATION или EXTENSION;
- граф ацикличен;
- closure dependency-aware расширения содержит ровно одну
CONFIGURATION;
- несколько ветвей зависимостей не приводят к разным configuration roots;
- ошибка содержит source-set и путь проблемы, например:
source-set dependency cycle: TESTS -> yaxunit -> TESTS
Base-Project EDT можно проверять на непротиворечивость объявленному configuration root, если он присутствует, но не использовать для неявного вывода CFE → CFE.
Ordering contract
Для полного build использовать stable topological order:
- dependency всегда раньше dependent;
- для несвязанных узлов сохраняется существующий canonical category order;
- внутри равноправной группы сохраняется порядок из YAML.
Добавление графа не должно случайно переставлять независимые source-set.
Scoped closure
v8-runner build --source-set TESTS
должен построить:
Каждый source-set обрабатывается не более одного раза. Change detection применяется к каждому элементу closure отдельно: неизменённая зависимость может получить Skipped, но остаётся частью вычисленного плана. Ошибка dependency не должна позволять начать dependent.
Желательно отражать в structured result как исходный selector, так и раскрытый план, например:
{
"requestedSourceSets": ["TESTS"],
"expandedSourceSets": ["main", "yaxunit", "TESTS"]
}
Один resolver closure следует использовать во всех scoped runtime-командах, которые собирают или загружают source-set.
Backward compatibility
dependsOn остаётся optional.
Для существующего проекта с одной CONFIGURATION и расширениями без dependsOn сохраняется текущее поведение full build. Для scoped extension build единственная конфигурация может считаться implicit base.
Если конфигураций несколько, dependency-aware extension должен явно приводить closure к одной из них; неоднозначность не следует разрешать порядком YAML.
Критерии готовности
Не входит в задачу
- автоматический вывод зависимостей из вызовов BSL;
- трактовка YAML-порядка как декларации зависимости;
- смешивание runtime build/load graph со static-analysis visibility graph;
- неявный вывод CFE → CFE из EDT layout или имени каталога.
Runtime graph нужен как источник истины, который затем смогут использовать Unica и статические анализаторы, но собственно semantic visibility анализатора должна решаться отдельно.
Контекст
Связано с IngvarConsulting/unica#170: тестовое расширение
TESTSиспользует API расширения YaXUnit и должно собираться/загружаться вместе с ним и основной конфигурацией.Проверено на:
v0.5.1;v0.5.2-pre.1/ currentmaster(be558db1c456f2d3a828c0f4de121b980ba6ccdc).Сейчас source-set содержит только
name,typeиpath: SourceSetSchema.Validator проверяет только глобальное условие «если существует
EXTENSION, должна существовать хотя бы однаCONFIGURATION», но не связывает конкретное расширение с базовой конфигурацией или другим расширением: validate_source_sets.Проблема
В реальном проекте расширения могут зависеть от API других расширений:
Текущий canonical order группирует все конфигурации, затем все расширения, сохраняя YAML-порядок внутри группы: ordered_source_sets.
Это позволяет вручную поставить YaXUnit перед
TESTS, но не фиксирует причинную связь. Порядок декларации становится скрытым operational contract.Дополнительно
build --source-set TESTSвыбирает толькоTESTS, без основной конфигурации и YaXUnit: selected_ordered_source_sets.test yaxunitчастично маскирует проблему, поскольку перед тестом запускает build всех source-set сsource_set: None: run_tests coordinator.Это operational co-loading всех расширений, а не dependency contract. Из-за этого полный тестовый запуск может работать, а scoped build на чистой ИБ — зависеть от уже установленного состояния или завершаться ошибкой.
Минимальное воспроизведение
Условия:
TESTSвызывает экспортный API YaXUnit.buildобрабатывает элементы только по category/YAML order.build --source-set TESTSне включаетmainиyaxunit.v8project.yamlневозможно выразить, чтоTESTSтребует YaXUnit.Предлагаемый контракт
Добавить optional
source-set[].dependsOn— список stablesource-set.nameнепосредственных зависимостей:Семантика
A.dependsOn: [B]:Bдолжен быть успешно построен/загружен раньшеA;AвключаетB;Bтакже включаются;B → A.Closure для примера:
Validation contract
До любого platform call необходимо проверять:
CONFIGURATIONилиEXTENSION;CONFIGURATION;Base-ProjectEDT можно проверять на непротиворечивость объявленному configuration root, если он присутствует, но не использовать для неявного вывода CFE → CFE.Ordering contract
Для полного
buildиспользовать stable topological order:Добавление графа не должно случайно переставлять независимые source-set.
Scoped closure
должен построить:
Каждый source-set обрабатывается не более одного раза. Change detection применяется к каждому элементу closure отдельно: неизменённая зависимость может получить
Skipped, но остаётся частью вычисленного плана. Ошибка dependency не должна позволять начать dependent.Желательно отражать в structured result как исходный selector, так и раскрытый план, например:
{ "requestedSourceSets": ["TESTS"], "expandedSourceSets": ["main", "yaxunit", "TESTS"] }Один resolver closure следует использовать во всех scoped runtime-командах, которые собирают или загружают source-set.
Backward compatibility
dependsOnостаётся optional.Для существующего проекта с одной
CONFIGURATIONи расширениями безdependsOnсохраняется текущее поведение full build. Для scoped extension build единственная конфигурация может считаться implicit base.Если конфигураций несколько, dependency-aware extension должен явно приводить closure к одной из них; неоднозначность не следует разрешать порядком YAML.
Критерии готовности
dependsOn: [<source-set-name>...].build --source-set TESTSвыполняетmain → yaxunit → TESTS.--full-rebuildработают отдельно для каждого узла closure.test yaxunitсохраняет текущее поведение.dependsOnпродолжает загружаться.Не входит в задачу
Runtime graph нужен как источник истины, который затем смогут использовать Unica и статические анализаторы, но собственно semantic visibility анализатора должна решаться отдельно.