##// END OF EJS Templates
Refactor variant artifact slots into contribution-based inputs
Refactor variant artifact slots into contribution-based inputs

File last commit:

r35:389e9d6c7860 default
r35:389e9d6c7860 default
Show More
variant-artifacts-plugin.md
354 lines | 10.5 KiB | text/x-minidsrc | MarkdownLexer
/ common / variant-artifacts-plugin.md
cin
Refactor variantArtifacts to variant-level publications with primary and secondary slots
r34 # Variant Artifacts Plugin
## NAME
`VariantsArtifactsPlugin` и extension `variantArtifacts`.
## SYNOPSIS
```groovy
import org.gradle.api.attributes.Attribute
plugins {
id 'org.implab.gradle-variants-artifacts'
}
def variantAttr = Attribute.of('test.variant', String)
def slotAttr = Attribute.of('test.slot', String)
variants {
layer('main')
variant('browser') {
role('main') { layers('main') }
}
}
variantSources {
bind('main') {
configureSourceSet {
declareOutputs('types', 'js', 'resources')
}
}
}
variantArtifacts {
variant('browser') {
primarySlot('typesPackage') {
fromVariant {
output('types')
}
}
slot('js') {
fromVariant {
output('js')
}
}
slot('resources') {
fromVariant {
output('resources')
}
}
}
whenOutgoingVariant { publication ->
publication.configureConfiguration {
attributes.attribute(variantAttr, publication.variantName())
}
publication.primarySlot().configureArtifactAttributes {
attribute(slotAttr, publication.primarySlot().slotName())
}
publication.requireSlot('js').configureArtifactAttributes {
attribute(slotAttr, 'js')
}
publication.requireSlot('resources').configureArtifactAttributes {
attribute(slotAttr, 'resources')
}
}
}
```
## DESCRIPTION
`VariantsArtifactsPlugin` применяет `VariantsSourcesPlugin`, затем строит
outgoing publication model поверх `variantSources`.
### publication model
Для каждого `variantArtifacts.variant('<name>')` публикуется один outgoing
build variant:
- primary configuration `<variant>Elements`;
- primary artifact slot на самой configuration;
- secondary variants внутри `configuration.outgoing.variants` для остальных slots.
Пример:
- `browserElements`
- primary slot: `typesPackage`
- secondary variants: `js`, `resources`
Это разделяет:
- graph selection build variant-а;
- artifact selection внутри уже выбранного variant-а.
cin
Refactor variant artifact slots into contribution-based inputs
r35 ### slot contributions и DSL
`slot('<name>')` описывает artifact representation не как один файл или одну
задачу, а как набор contributions, которые потом materialize-ятся в отдельный
`ArtifactAssembly`.
Текущий DSL поддерживает два вида contributions:
cin
Refactor variantArtifacts to variant-level publications with primary and secondary slots
r34
cin
Refactor variant artifact slots into contribution-based inputs
r35 - topology-aware:
- `fromVariant { output(...) }`
- `fromRole('<role>') { output(...) }`
- `fromLayer('<layer>') { output(...) }`
- direct:
- `from(someFileOrProviderOrTaskOutput)`
Смысл DSL по слоям:
cin
Refactor variantArtifacts to variant-level publications with primary and secondary slots
r34
cin
Refactor variant artifact slots into contribution-based inputs
r35 - `fromVariant/fromRole/fromLayer` выбирают область topology model, в которой
contribution активен;
- `output(...)` выбирает named output соответствующего `GenericSourceSet`;
- `from(Object)` добавляет direct contribution, не зависящий от
`variantSources` bindings;
- итоговый contribution при materialization:
- проверяет, подходит ли текущий `SourceSetUsageBinding`;
- выдает object для `files.from(...)`;
- при необходимости выдает `BindingKey`, если такой contribution должен
схлопываться по logical identity.
cin
Refactor variantArtifacts to variant-level publications with primary and secondary slots
r34
cin
Refactor variant artifact slots into contribution-based inputs
r35 Связь slot-а с остальной моделью:
- `variants` задает topology variant/role/layer;
- `variantSources` превращает topology в concrete `SourceSetUsageBinding`;
- `variantArtifacts.slot(...)` описывает, какие bindings надо включить в slot;
- `VariantArtifactsResolver` превращает contributions slot-а в `FileCollection`;
- `VariantArtifactsPlugin` регистрирует для slot-а отдельный `ArtifactAssembly`;
- `OutgoingVariantPublication` и `OutgoingArtifactSlotPublication` публикуют
уже собранные slot artifacts наружу.
cin
Refactor variantArtifacts to variant-level publications with primary and secondary slots
r34
Каждый slot materialize-ится в отдельный `ArtifactAssembly`:
- task: `process<Variant><Slot>`;
- output dir: `build/variant-artifacts/<variant>/<slot>`.
### primary slot
Primary slot задает artifact, который публикуется как основной artifact
configuration `<variant>Elements`.
Формы DSL:
```groovy
variant('browser') {
primarySlot('typesPackage')
slot('typesPackage') {
fromVariant { output('types') }
}
}
```
или sugar:
```groovy
variant('browser') {
primarySlot('typesPackage') {
fromVariant { output('types') }
}
}
```
Правила:
- если slot один, он считается primary неявно;
- если slots несколько, `primarySlot(...)` обязателен;
- `primarySlot` должен ссылаться на существующий slot.
## LIFECYCLE
- `VariantsArtifactsPlugin` ждет `variants.whenFinalized(...)`;
- после этого валидирует `variantArtifacts`;
- регистрирует `ArtifactAssembly` по каждому slot;
- materialize-ит outgoing publications;
- вызывает `whenOutgoingVariant(...)`;
- callbacks replayable.
После finalize мутации `variantArtifacts` запрещены.
## EVENTS
### whenOutgoingVariant
Replayable callback на готовую outgoing publication variant-а.
Подходит для:
- настройки общих attributes build variant-а один раз;
- настройки per-slot artifact attributes;
- доконфигурации `ArtifactAssembly`.
## PAYLOAD TYPES
### OutgoingVariantPublication
Содержит:
- `variantName()`;
- `topologyVariant()`;
- `variantArtifact()`;
- `configuration()` — primary `<variant>Elements`;
- `primarySlot()`;
- `slots()` — все slot publications;
- `secondarySlots()`;
- `findSlot(name)`, `requireSlot(name)`.
Sugar:
- `configureConfiguration(Action|Closure)`.
### OutgoingArtifactSlotPublication
Содержит:
- `slotName()`;
- `primary()`;
- `slot()` — модель `VariantArtifactSlot`;
- `assembly()`.
Sugar:
- `configureAssembly(Action|Closure)`;
- `configureArtifactAttributes(Action|Closure)`.
`configureArtifactAttributes(...)` пишет attributes:
- в `Configuration.attributes` для primary slot;
- в `ConfigurationVariant.attributes` для secondary slot.
## CONSUMER SIDE
### primary resolution
Обычное inter-project resolution выбирает primary artifact `<variant>Elements`.
Пример:
```groovy
configurations {
compileView {
canBeResolved = true
canBeConsumed = false
canBeDeclared = true
attributes {
attribute(variantAttr, 'browser')
attribute(slotAttr, 'typesPackage')
}
}
}
dependencies {
compileView project(':producer')
}
```
### artifact selection for secondary slots
Secondary artifacts выбираются через `artifactView`.
```groovy
def jsFiles = configurations.compileView.incoming.artifactView {
attributes {
attribute(slotAttr, 'js')
}
}.files
```
Здесь graph variant уже выбран, а `artifactView` выбирает нужный secondary
artifact representation.
## VALIDATION
Проверяется:
- variant существует в topology model;
cin
Refactor variant artifact slots into contribution-based inputs
r35 - slot contributions не ссылаются на неизвестные role/layer;
cin
Refactor variantArtifacts to variant-level publications with primary and secondary slots
r34 - при нескольких slots указан `primarySlot`;
- `primarySlot` ссылается на существующий slot.
## API
### VariantArtifactsExtension
- `variant(String)` — получить/создать variant artifact model;
- `variant(String, Action|Closure)` — сконфигурировать variant artifact;
- `getVariants()` — контейнер variant artifacts;
- `findVariant(name)`, `requireVariant(name)`;
- `whenOutgoingVariant(...)`.
### VariantArtifact
- `slot(String)` — получить/создать slot;
- `slot(String, Action|Closure)` — сконфигурировать slot;
- `primarySlot(String)` — назначить primary slot;
- `primarySlot(String, Action|Closure)` — sugar: configure slot + mark as primary;
- `getSlots()`;
- `findSlot(name)`, `requireSlot(name)`;
- `findPrimarySlotName()`, `requirePrimarySlotName()`;
- `findPrimarySlot()`, `requirePrimarySlot()`.
### VariantArtifactSlot
cin
Refactor variant artifact slots into contribution-based inputs
r35 - `from(Object)`;
cin
Refactor variantArtifacts to variant-level publications with primary and secondary slots
r34 - `fromVariant(...)`;
- `fromRole(String, ...)`;
- `fromLayer(String, ...)`.
cin
Refactor variant artifact slots into contribution-based inputs
r35 Внутренняя модель:
- slot хранит contributions, а не строковые rules;
- `fromVariant/fromRole/fromLayer` создают topology-aware contributions;
- `from(Object)` создает direct contribution, который materialize-ится даже
если у variant-а нет ни одного `SourceSetUsageBinding`;
- slot отдельно хранит topology references для validation:
`referencedRoleNames()` и `referencedLayerNames()`.
cin
Refactor variantArtifacts to variant-level publications with primary and secondary slots
r34 ### OutputSelectionSpec
- `output(name)`;
- `output(name, extra...)`.
cin
Refactor variant artifact slots into contribution-based inputs
r35 `OutputSelectionSpec` это внутренний DSL-buffer для одного блока
`fromVariant/fromRole/fromLayer`. Он локально накапливает contributions и
передает их в slot только после успешного завершения configure-блока.
cin
Refactor variantArtifacts to variant-level publications with primary and secondary slots
r34 ## KEY CLASSES
- `VariantsArtifactsPlugin` — plugin adapter и materialization outgoing variants.
- `VariantArtifactsExtension` — root DSL и lifecycle.
- `VariantArtifact` — outgoing build variant model.
- `VariantArtifactSlot` — artifact representation slot.
cin
Refactor variant artifact slots into contribution-based inputs
r35 - `VariantArtifactsResolver` — adapter между `variantSources` bindings и
contribution model slot-а.
cin
Refactor variantArtifacts to variant-level publications with primary and secondary slots
r34 - `OutgoingVariantPublication` — payload variant-level publication callback.
- `OutgoingArtifactSlotPublication` — payload per-slot publication callback.
- `ArtifactAssembly` — assembled files for a slot.
## NOTES
- `common` не навязывает доменную логику выбора primary slot.
- `common` не фиксирует значения `usage`, `libraryelements` и прочих
slot-specific attributes.
- `common` не смешивает эту модель с отдельными publish осями вроде package
metadata.
- Closure callbacks используют delegate-first; для вложенных closure удобнее
явный параметр (`publication -> ...`, `slotPublication -> ...`).