##// END OF EJS Templates
Set the project version to 0.1.0, add publication descriptions/license metadata, and keep module-level docs as compatibility pointers to the root documentation.
cin -
r60:e376d0cab00e default
parent child
Show More
@@ -0,0 +1,24
1 BSD 2-Clause License
2
3 Copyright (c) 2026 gradle-common contributors.
4
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7
8 1. Redistributions of source code must retain the above copyright notice, this
9 list of conditions and the following disclaimer.
10
11 2. Redistributions in binary form must reproduce the above copyright notice,
12 this list of conditions and the following disclaimer in the documentation
13 and/or other materials provided with the distribution.
14
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
19 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,99
1 # Local Ivy Publishing
2
3 This project currently publishes only to a local Ivy repository. Maven Central,
4 signing, and Gradle Plugin Portal publication are intentionally out of scope for
5 the current preparation step.
6
7 Published Ivy descriptors include the BSD-2-Clause license metadata.
8
9 ## Repository
10
11 The configured Ivy repository is:
12
13 ```text
14 ${user.home}/ivy-repo
15 ```
16
17 This is defined in:
18
19 - `common/build.gradle`
20 - `variants/build.gradle`
21
22 ## Verify Before Publishing
23
24 Run a full clean verification:
25
26 ```bash
27 ./gradlew clean check javadoc jar sourcesJar javadocJar --rerun-tasks
28 ```
29
30 Optional configuration-cache smoke check:
31
32 ```bash
33 ./gradlew check --configuration-cache
34 ```
35
36 ## Publish
37
38 Publish all modules:
39
40 ```bash
41 ./gradlew publish
42 ```
43
44 Publish modules explicitly:
45
46 ```bash
47 ./gradlew :common:publishIvyPublicationToIvyRepository \
48 :variants:publishIvyPublicationToIvyRepository
49 ```
50
51 Safe smoke publish into a temporary repository:
52
53 ```bash
54 ./gradlew -Duser.home=/tmp/gradle-common-ivy-smoke \
55 :common:publishIvyPublicationToIvyRepository \
56 :variants:publishIvyPublicationToIvyRepository \
57 --rerun-tasks
58 ```
59
60 ## Consume Locally
61
62 Use `buildscript` classpath for now:
63
64 ```groovy
65 buildscript {
66 repositories {
67 ivy {
68 url "${System.properties['user.home']}/ivy-repo"
69 }
70 mavenCentral()
71 }
72 dependencies {
73 classpath 'org.implab.gradle:variants:0.1.0'
74 }
75 }
76
77 apply plugin: 'org.implab.gradle-variants'
78 apply plugin: 'org.implab.gradle-variants-sources'
79 ```
80
81 The `plugins {}` DSL needs generated plugin marker artifacts and is not part of
82 the current local Ivy contract.
83
84 ## Published Artifacts
85
86 Each module publishes:
87
88 - `<module>-<version>.jar`
89 - `<module>-<version>-sources.jar`
90 - `<module>-<version>-javadoc.jar`
91 - `ivy.xml`
92 - Gradle module metadata
93
94 ## Current Coordinates
95
96 ```text
97 org.implab.gradle:common:0.1.0
98 org.implab.gradle:variants:0.1.0
99 ```
@@ -0,0 +1,296
1 # gradle-common
2
3 Java 21 multi-project build with shared Gradle utilities and experimental
4 variant-oriented Gradle plugins.
5
6 The repository currently publishes to a local Ivy repository only. Maven Central
7 and Gradle Plugin Portal publication are intentionally not configured yet.
8
9 ## Modules
10
11 - `common` - shared Gradle utilities, JSON helpers, shell execution helpers, and
12 small core value/util classes.
13 - `variants` - Gradle plugins for variant topology, source-set materialization,
14 and outgoing artifact slots.
15
16 ## Requirements
17
18 - JDK 21.
19 - Gradle Wrapper from this repository, currently Gradle 8.10.2.
20
21 The produced bytecode targets Java 21.
22
23 ## License
24
25 This project is licensed under the BSD 2-Clause "Simplified" License
26 (`BSD-2-Clause`). See [LICENSE](LICENSE).
27
28 ## Local Build
29
30 ```bash
31 ./gradlew clean check javadoc jar sourcesJar javadocJar --rerun-tasks
32 ```
33
34 Configuration cache smoke check:
35
36 ```bash
37 ./gradlew check --configuration-cache
38 ```
39
40 ## Local Ivy Publication
41
42 The current publication target is:
43
44 ```text
45 ${user.home}/ivy-repo
46 ```
47
48 Publish both modules locally:
49
50 ```bash
51 ./gradlew :common:publishIvyPublicationToIvyRepository \
52 :variants:publishIvyPublicationToIvyRepository
53 ```
54
55 or:
56
57 ```bash
58 ./gradlew publish
59 ```
60
61 The publication includes:
62
63 - main jar
64 - sources jar
65 - javadoc jar
66 - Ivy descriptor
67 - Gradle module metadata
68
69 ## Local Consumption
70
71 Current plugin ids are packaged as classic Gradle plugin marker resources inside
72 the `variants` jar:
73
74 - `org.implab.gradle-variants`
75 - `org.implab.gradle-sources`
76 - `org.implab.gradle-variants-sources`
77 - `org.implab.gradle-variants-artifacts`
78
79 Until Gradle Plugin Portal marker artifacts are configured, consume the plugin
80 through `buildscript` classpath:
81
82 ```groovy
83 buildscript {
84 repositories {
85 ivy {
86 url "${System.properties['user.home']}/ivy-repo"
87 }
88 mavenCentral()
89 }
90 dependencies {
91 classpath 'org.implab.gradle:variants:0.1.0'
92 }
93 }
94
95 apply plugin: 'org.implab.gradle-variants'
96 apply plugin: 'org.implab.gradle-variants-sources'
97 ```
98
99 The `plugins { id(...) version(...) }` DSL is not part of the current local Ivy
100 contract.
101
102 ## Variants DSL
103
104 `variants` defines the finalized build topology. It does not create compile
105 tasks, source directories, or outgoing publications by itself.
106
107 ```groovy
108 apply plugin: 'org.implab.gradle-variants'
109
110 variants.layers.create('main')
111 variants.layers.create('test')
112 variants.roles.create('main')
113 variants.roles.create('test')
114
115 variants.variant('browser') {
116 role('main') {
117 layers('main')
118 }
119 role('test') {
120 layers('main', 'test')
121 }
122 }
123
124 variants.whenFinalized { view ->
125 println view.entries.collect {
126 "${it.variant().name}:${it.role().name}:${it.layer().name}"
127 }.sort()
128 }
129 ```
130
131 The finalized model exposes cheap identity objects: `Variant`, `Role`, `Layer`,
132 and the normalized relation `(variant, role, layer)`.
133
134 ## Sources DSL
135
136 `sources` creates standalone `GenericSourceSet` objects. This is useful for
137 fallback workflows that do not need variant topology.
138
139 ```groovy
140 apply plugin: 'org.implab.gradle-sources'
141
142 sources.create('main') {
143 declareOutputs('js')
144 registerOutput('js', layout.projectDirectory.file('inputs/main.js'))
145
146 sets.create('ts') {
147 srcDir 'src/main/ts'
148 }
149 }
150 ```
151
152 `SourcesPlugin` applies layout conventions:
153
154 - `sourceSetDir = src/<sourceSet>`
155 - `outputsDir = build/out/<sourceSet>`
156
157 The base `GenericSourceSet` model itself is convention-free.
158
159 ## Variant Sources DSL
160
161 `variantSources` derives compile units from finalized `variants`.
162
163 A compile unit is:
164
165 ```text
166 (variant, layer)
167 ```
168
169 Selectors configure materialized compile-unit source sets:
170
171 ```groovy
172 apply plugin: 'org.implab.gradle-variants-sources'
173
174 variants.layers.create('main')
175 variants.roles.create('main')
176 variants.variant('browser') {
177 role('main') {
178 layers('main')
179 }
180 }
181
182 variantSources {
183 layer('main') {
184 sourceSet {
185 declareOutputs('js')
186 registerOutput('js', layout.projectDirectory.file('inputs/browser.js'))
187 }
188 }
189
190 configureEach {
191 println "sourceSet=${sourceSet.name}, variant=${variant.name}, layer=${layer.name}"
192 }
193 }
194 ```
195
196 Selector order for future materialization is:
197
198 ```text
199 configureEach -> variant -> layer -> unit
200 ```
201
202 Late selector registration is controlled by:
203
204 ```groovy
205 variantSources {
206 lateConfigurationPolicy {
207 failOnLateConfiguration()
208 }
209 }
210 ```
211
212 Compile-unit source set names are generated by default as:
213
214 ```text
215 <variant> + capitalize(<layer>)
216 ```
217
218 Name collisions fail by default and may be resolved deterministically:
219
220 ```groovy
221 variantSources {
222 namingPolicy {
223 resolveNameCollision()
224 }
225 }
226 ```
227
228 ## Variant Artifacts DSL
229
230 `variantArtifacts` is an experimental outgoing artifact layer over `variants`
231 and `variantSources`.
232
233 The current model maps:
234
235 - `Variant` to a variant-level consumable outgoing configuration.
236 - `Slot` to a Gradle outgoing artifact variant inside that configuration.
237 - `primarySlot` to the primary artifact set of the outgoing configuration.
238
239 ```groovy
240 apply plugin: 'org.implab.gradle-variants-artifacts'
241
242 variants.layers.create('main')
243 variants.roles.create('main')
244 variants.variant('browser') {
245 role('main') {
246 layers('main')
247 }
248 }
249
250 variantSources.layer('main') {
251 sourceSet {
252 declareOutputs('types', 'js')
253 registerOutput('types', layout.projectDirectory.file('inputs/index.d.ts'))
254 registerOutput('js', layout.projectDirectory.file('inputs/index.js'))
255 }
256 }
257
258 variantArtifacts {
259 variant('browser') {
260 primarySlot('typesPackage') {
261 fromVariant {
262 output('types')
263 }
264 }
265 slot('js') {
266 fromVariant {
267 output('js')
268 }
269 }
270 }
271
272 whenOutgoingConfiguration { publication ->
273 publication.configuration {
274 description = "Outgoing contract for ${publication.variant.name}"
275 }
276 }
277
278 whenOutgoingSlot { publication ->
279 println "slot=${publication.artifactSlot.slot.name}, primary=${publication.primary}"
280 }
281 }
282 ```
283
284 The artifact API is still considered pre-1.0 and may change.
285
286 ## Publication Status
287
288 Current status:
289
290 - local Ivy publication only
291 - no Maven Central publication metadata
292 - no signing
293 - no Gradle Plugin Portal marker artifacts
294 - BSD-2-Clause license committed
295
296 Before external publication, see [RELEASE_CHECKLIST.md](RELEASE_CHECKLIST.md).
@@ -0,0 +1,63
1 # Release Checklist
2
3 This checklist tracks what should be true before publishing outside the local
4 Ivy repository.
5
6 ## Current Scope
7
8 For now the project is prepared for local Ivy publication only.
9
10 ## Required Before External Publication
11
12 - Add Maven publication (`maven-publish`) if publishing to Maven repositories.
13 - Add signing for Maven Central or any repository that requires signed
14 artifacts.
15 - Add complete POM metadata: project name, description, URL, license,
16 developers, and SCM coordinates.
17 - Keep Java 21 as the public baseline and document it for consumers.
18 - Decide whether `variants` artifact APIs are published as experimental or
19 split into a later module.
20 - Add Gradle plugin marker artifact generation if `plugins { id(...) version(...) }`
21 must work.
22 - Add a published-consumption smoke test that resolves artifacts from a
23 temporary local repository.
24
25 ## Local Ivy Release Steps
26
27 1. Ensure the Mercurial working tree is clean.
28 2. Run:
29
30 ```bash
31 ./gradlew clean check javadoc jar sourcesJar javadocJar --rerun-tasks
32 ```
33
34 3. Optionally run:
35
36 ```bash
37 ./gradlew check --configuration-cache
38 ```
39
40 4. Publish locally:
41
42 ```bash
43 ./gradlew publish
44 ```
45
46 5. Optionally smoke-publish into `/tmp` first:
47
48 ```bash
49 ./gradlew -Duser.home=/tmp/gradle-common-ivy-smoke \
50 :common:publishIvyPublicationToIvyRepository \
51 :variants:publishIvyPublicationToIvyRepository \
52 --rerun-tasks
53 ```
54
55 6. Verify `${user.home}/ivy-repo/org.implab.gradle` contains `common` and
56 `variants` for the expected version.
57
58 ## API Status
59
60 - `common` is intended to be a shared utility library.
61 - `variants` core and source APIs are pre-1.0 and should be treated as
62 evolving.
63 - `variantArtifacts` is experimental and may change more aggressively.
@@ -1,6 +1,7
1 1 syntax: glob
2 2 .gradle/
3 3 .codex/
4 build/
4 5 common/build/
5 6 common/bin/
6 7 variants/build/
@@ -3,6 +3,8 plugins {
3 3 id "ivy-publish"
4 4 }
5 5
6 description = "Shared Gradle build utilities used by Implab plugins"
7
6 8 java {
7 9 withJavadocJar()
8 10 withSourcesJar()
@@ -46,6 +48,10 publishing {
46 48 descriptor.description {
47 49 text = providers.provider({ description })
48 50 }
51 descriptor.license {
52 name = "BSD-2-Clause"
53 url = "https://spdx.org/licenses/BSD-2-Clause.html"
49 54 }
50 55 }
51 56 }
57 }
@@ -1,134 +1,18
1 # Gradle Common Sources Model
2
3 ## NAME
4
5 `gradle-common/common` — набор плагинов для моделирования вариантов сборки,
6 регистрации source sets и интеграции этой модели с toolchain-адаптерами.
7
8 ## SYNOPSIS
9
10 ```groovy
11 plugins {
12 id 'org.implab.gradle-variants-sources'
13 }
14
15 variants {
16 layer('mainBase')
17 layer('mainAmd')
18
19 variant('browser') {
20 role('main') { layers('mainBase', 'mainAmd') }
21 }
22 }
23
24 variantSources {
25 bind('mainBase') {
26 configureSourceSet {
27 declareOutputs('compiled')
28 }
29 }
30
31 bind('mainAmd').sourceSetNamePattern = '{variant}{layerCap}'
1 # Gradle Common
32 2
33 whenRegistered { sourceSetName() }
34
35 whenBound { ctx ->
36 ctx.configureSourceSet {
37 declareOutputs('typings')
38 }
39 }
40 }
41 ```
42
43 ## DESCRIPTION
44
45 Модуль состоит из трех логических частей:
3 `common` is the shared utility module used by the Gradle plugins in this
4 repository.
46 5
47 - `variants` — декларативная доменная модель сборки;
48 - `sources` — модель физически регистрируемых source sets;
49 - `variantSources` — адаптер, который связывает первые две модели.
50
51 Ниже раскрытие каждой части.
52
53 ### variants
54
55 `variants` задает структуру пространства сборки: какие есть слои, какие роли
56 используют эти слои в каждом варианте, какие есть атрибуты и artifact slots.
57 Модель не создает задачи и не привязана к TS/JS.
58
59 Практический смысл:
60
61 - формализовать архитектуру сборки;
62 - дать адаптерам единый источник правды.
63
64 ### sources
6 It contains:
65 7
66 `sources` описывает независимые source sets (`GenericSourceSet`) с именованными
67 outputs. Это уже "физический" уровень, к которому удобно привязывать задачи,
68 артефакты и task inputs/outputs.
69
70 Практический смысл:
71
72 - создать единый контракт по входам/выходам;
73 - регистрировать результаты задач как outputs source set;
74 - минимизировать ручные `dependsOn` за счет модели outputs.
75
76 ### variantSources
77
78 `variantSources` регистрирует source sets на основе `variants`, применяет
79 конфигурацию layer-bindings и отдает события (`whenRegistered`, `whenBound`) для
80 адаптеров других плагинов.
81
82 Практический смысл:
83
84 - переводить логическую модель `variants` в executable-модель `sources`;
85 - навешивать политики toolchain на зарегистрированные source sets;
86 - синхронизировать плагины через replayable callback-контракт.
87
88 ## DOMAIN MODEL
89
90 - `BuildLayer` — canonical identity-model объявленного слоя.
91 - `BuildVariant` — агрегат ролей, атрибутов, артефактных слотов.
92 - `BuildRole` — роль внутри варианта, содержит ссылки на declared layer names.
93 - `GenericSourceSet` — зарегистрированный набор исходников и outputs.
94 - `LayerBindingSpec` — публичный DSL-contract adapter policy/callbacks для слоя.
95 - `SourceSetRegistration` — payload события регистрации source set.
96 - `SourceSetUsageBinding` — payload события usage-binding.
97
98 ## EVENT CONTRACT
8 - core Gradle helper utilities
9 - small language/value helpers
10 - shell execution helpers
11 - JSON DSL and JSON-writing task support
99 12
100 - `whenRegistered`:
101 - событие нового уникального source set name;
102 - replayable.
103 - `whenBound`:
104 - событие каждой usage-связки `variant/role/layer`;
105 - replayable.
106
107 Closure callbacks работают в delegate-first режиме (`@DelegatesTo`). Для
108 вложенных closure рекомендуется явный параметр (`ctx -> ...`).
109
110 ## KEY CLASSES
13 It no longer contains the variant/source/artifact plugin model. Those plugins
14 live in the `variants` module.
111 15
112 - `SourcesPlugin` — регистрирует extension `sources`.
113 - `GenericSourceSet` — модель источников/outputs для конкретного имени.
114 - `VariantsPlugin` — регистрирует extension `variants` и lifecycle finalize.
115 - `BuildVariantsExtension` — корневой API модели вариантов.
116 - `BuildVariant` — API ролей, attributes и artifact slots варианта.
117 - `VariantsSourcesPlugin` — применяет `variants` + `sources` и запускает адаптер.
118 - `VariantSourcesExtension` — API bind/events registration.
119 - `LayerBindingSpec` — слой-конкретный DSL для policy/configuration source set.
120 - `SourceSetRegistration` — payload `whenRegistered(...)`.
121 - `SourceSetUsageBinding` — payload `whenBound(...)`.
16 See the root [README.md](../README.md) and [PUBLISHING.md](../PUBLISHING.md) for
17 current build and local Ivy publication instructions.
122 18
123 ## NOTES
124
125 - Marker ids:
126 - `org.implab.gradle-variants`
127 - `org.implab.gradle-variants-sources`
128 - `SourcesPlugin` пока class-only (без marker id).
129
130 ## SEE ALSO
131
132 - `sources-plugin.md`
133 - `variants-plugin.md`
134 - `variant-sources-plugin.md`
@@ -1,83 +1,7
1 # Sources Plugin
2
3 ## NAME
4
5 `SourcesPlugin` и extension `sources`.
6
7 ## SYNOPSIS
8
9 ```groovy
10 // Обычно подключается транзитивно через org.implab.gradle-variants-sources
11
12 sources {
13 register('main') {
14 declareOutputs('compiled', 'typings')
15
16 sets {
17 ts { srcDir 'src/main/ts' }
18 js { srcDir 'src/main/js' }
19 }
20 }
21 }
22 ```
23
24 ## DESCRIPTION
25
26 `SourcesPlugin` регистрирует extension `sources` типа
27 `NamedDomainObjectContainer<GenericSourceSet>`.
28
29 `GenericSourceSet` — это автономный source bundle с четким контрактом outputs.
30
31 ### sourceSetDir
32
33 Базовый каталог набора. Конвенция по умолчанию: `src/<name>`.
34
35 ### outputsDir
36
37 Базовый каталог результатов набора. Конвенция по умолчанию: `build/<name>`.
38
39 ### sets
1 # Moved: Sources Plugin
40 2
41 Контейнер `SourceDirectorySet` внутри `GenericSourceSet`. Используется для
42 логического разделения подпапок (например `ts`, `js`, `typings`).
43
44 ### outputs contract
45
46 Outputs именованные и должны быть объявлены заранее:
47
48 - `declareOutputs(...)` — декларация доступных output keys;
49 - `output(name)` — доступ к `ConfigurableFileCollection` для output key;
50 - `registerOutput(...)` — регистрация output из файлов или task provider.
51
52 Такой контракт упрощает wiring задач через inputs/outputs без ручного
53 `dependsOn`.
54
55 ## API
56
57 ### SourcesPlugin
58
59 - `apply(Project)` — добавляет extension `sources` в проект.
60 - `getSourcesExtension(Project)` — возвращает контейнер `GenericSourceSet`.
3 The `SourcesPlugin` implementation is now part of the `variants` module, not
4 the `common` module.
61 5
62 ### GenericSourceSet
6 Current documentation is maintained in the root [README.md](../README.md).
63 7
64 - `getSourceSetDir()` — root directory источников набора.
65 - `getOutputsDir()` — root directory результатов набора.
66 - `getSets()` — контейнер поднаборов `SourceDirectorySet`.
67 - `declareOutputs(...)` — объявляет разрешенные output names.
68 - `output(name)` — возвращает `FileCollection` для конкретного output.
69 - `registerOutput(name, files...)` — добавляет файлы в output.
70 - `registerOutput(name, task, mapper)` — связывает output с task provider.
71 - `getAllOutputs()` — агрегированный `FileCollection` всех outputs.
72 - `getAllSourceDirectories()` — агрегированный `FileCollection` всех source dirs.
73
74 ## KEY CLASSES
75
76 - `SourcesPlugin` — регистрация extension `sources`.
77 - `GenericSourceSet` — модель источников и outputs.
78
79 ## NOTES
80
81 - Обращение к `output(name)` без предварительного `declareOutputs(name)`
82 приводит к ошибке валидации.
83 - Плагин `sources` сейчас без marker id.
@@ -1,354 +1,8
1 # Variant Artifacts Plugin
2
3 ## NAME
4
5 `VariantsArtifactsPlugin` и extension `variantArtifacts`.
6
7 ## SYNOPSIS
8
9 ```groovy
10 import org.gradle.api.attributes.Attribute
11
12 plugins {
13 id 'org.implab.gradle-variants-artifacts'
14 }
15
16 def variantAttr = Attribute.of('test.variant', String)
17 def slotAttr = Attribute.of('test.slot', String)
18
19 variants {
20 layer('main')
21
22 variant('browser') {
23 role('main') { layers('main') }
24 }
25 }
26
27 variantSources {
28 bind('main') {
29 configureSourceSet {
30 declareOutputs('types', 'js', 'resources')
31 }
32 }
33 }
34
35 variantArtifacts {
36 variant('browser') {
37 primarySlot('typesPackage') {
38 fromVariant {
39 output('types')
40 }
41 }
42
43 slot('js') {
44 fromVariant {
45 output('js')
46 }
47 }
48
49 slot('resources') {
50 fromVariant {
51 output('resources')
52 }
53 }
54 }
55
56 whenOutgoingVariant { publication ->
57 publication.configureConfiguration {
58 attributes.attribute(variantAttr, publication.variantName())
59 }
60
61 publication.primarySlot().configureArtifactAttributes {
62 attribute(slotAttr, publication.primarySlot().slotName())
63 }
64
65 publication.requireSlot('js').configureArtifactAttributes {
66 attribute(slotAttr, 'js')
67 }
68
69 publication.requireSlot('resources').configureArtifactAttributes {
70 attribute(slotAttr, 'resources')
71 }
72 }
73 }
74 ```
75
76 ## DESCRIPTION
77
78 `VariantsArtifactsPlugin` применяет `VariantsSourcesPlugin`, затем строит
79 outgoing publication model поверх `variantSources`.
80
81 ### publication model
82
83 Для каждого `variantArtifacts.variant('<name>')` публикуется один outgoing
84 build variant:
85
86 - primary configuration `<variant>Elements`;
87 - primary artifact slot на самой configuration;
88 - secondary variants внутри `configuration.outgoing.variants` для остальных slots.
89
90 Пример:
91
92 - `browserElements`
93 - primary slot: `typesPackage`
94 - secondary variants: `js`, `resources`
95
96 Это разделяет:
97
98 - graph selection build variant-а;
99 - artifact selection внутри уже выбранного variant-а.
100
101 ### slot contributions и DSL
102
103 `slot('<name>')` описывает artifact representation не как один файл или одну
104 задачу, а как набор contributions, которые потом materialize-ятся в отдельный
105 `ArtifactAssembly`.
106
107 Текущий DSL поддерживает два вида contributions:
108
109 - topology-aware:
110 - `fromVariant { output(...) }`
111 - `fromRole('<role>') { output(...) }`
112 - `fromLayer('<layer>') { output(...) }`
113 - direct:
114 - `from(someFileOrProviderOrTaskOutput)`
115
116 Смысл DSL по слоям:
117
118 - `fromVariant/fromRole/fromLayer` выбирают область topology model, в которой
119 contribution активен;
120 - `output(...)` выбирает named output соответствующего `GenericSourceSet`;
121 - `from(Object)` добавляет direct contribution, не зависящий от
122 `variantSources` bindings;
123 - итоговый contribution при materialization:
124 - проверяет, подходит ли текущий `SourceSetUsageBinding`;
125 - выдает object для `files.from(...)`;
126 - при необходимости выдает `BindingKey`, если такой contribution должен
127 схлопываться по logical identity.
128
129 Связь slot-а с остальной моделью:
130
131 - `variants` задает topology variant/role/layer;
132 - `variantSources` превращает topology в concrete `SourceSetUsageBinding`;
133 - `variantArtifacts.slot(...)` описывает, какие bindings надо включить в slot;
134 - `VariantArtifactsResolver` превращает contributions slot-а в `FileCollection`;
135 - `VariantArtifactsPlugin` регистрирует для slot-а отдельный `ArtifactAssembly`;
136 - `OutgoingVariantPublication` и `OutgoingArtifactSlotPublication` публикуют
137 уже собранные slot artifacts наружу.
138
139 Каждый slot materialize-ится в отдельный `ArtifactAssembly`:
140
141 - task: `process<Variant><Slot>`;
142 - output dir: `build/variant-artifacts/<variant>/<slot>`.
143
144 ### primary slot
145
146 Primary slot задает artifact, который публикуется как основной artifact
147 configuration `<variant>Elements`.
148
149 Формы DSL:
150
151 ```groovy
152 variant('browser') {
153 primarySlot('typesPackage')
154
155 slot('typesPackage') {
156 fromVariant { output('types') }
157 }
158 }
159 ```
160
161 или sugar:
162
163 ```groovy
164 variant('browser') {
165 primarySlot('typesPackage') {
166 fromVariant { output('types') }
167 }
168 }
169 ```
170
171 Правила:
172
173 - если slot один, он считается primary неявно;
174 - если slots несколько, `primarySlot(...)` обязателен;
175 - `primarySlot` должен ссылаться на существующий slot.
1 # Moved: Variant Artifacts Plugin
176 2
177 ## LIFECYCLE
178
179 - `VariantsArtifactsPlugin` ждет `variants.whenFinalized(...)`;
180 - после этого валидирует `variantArtifacts`;
181 - регистрирует `ArtifactAssembly` по каждому slot;
182 - materialize-ит outgoing publications;
183 - вызывает `whenOutgoingVariant(...)`;
184 - callbacks replayable.
185
186 После finalize мутации `variantArtifacts` запрещены.
187
188 ## EVENTS
189
190 ### whenOutgoingVariant
191
192 Replayable callback на готовую outgoing publication variant-а.
193
194 Подходит для:
195
196 - настройки общих attributes build variant-а один раз;
197 - настройки per-slot artifact attributes;
198 - доконфигурации `ArtifactAssembly`.
199
200 ## PAYLOAD TYPES
201
202 ### OutgoingVariantPublication
203
204 Содержит:
205
206 - `variantName()`;
207 - `topologyVariant()`;
208 - `variantArtifact()`;
209 - `configuration()` — primary `<variant>Elements`;
210 - `primarySlot()`;
211 - `slots()` — все slot publications;
212 - `secondarySlots()`;
213 - `findSlot(name)`, `requireSlot(name)`.
214
215 Sugar:
216
217 - `configureConfiguration(Action|Closure)`.
218
219 ### OutgoingArtifactSlotPublication
220
221 Содержит:
222
223 - `slotName()`;
224 - `primary()`;
225 - `slot()` — модель `VariantArtifactSlot`;
226 - `assembly()`.
227
228 Sugar:
229
230 - `configureAssembly(Action|Closure)`;
231 - `configureArtifactAttributes(Action|Closure)`.
232
233 `configureArtifactAttributes(...)` пишет attributes:
234
235 - в `Configuration.attributes` для primary slot;
236 - в `ConfigurationVariant.attributes` для secondary slot.
237
238 ## CONSUMER SIDE
239
240 ### primary resolution
241
242 Обычное inter-project resolution выбирает primary artifact `<variant>Elements`.
243
244 Пример:
245
246 ```groovy
247 configurations {
248 compileView {
249 canBeResolved = true
250 canBeConsumed = false
251 canBeDeclared = true
252 attributes {
253 attribute(variantAttr, 'browser')
254 attribute(slotAttr, 'typesPackage')
255 }
256 }
257 }
258
259 dependencies {
260 compileView project(':producer')
261 }
262 ```
263
264 ### artifact selection for secondary slots
3 The `VariantArtifactsPlugin` implementation is now part of the `variants`
4 module, not the `common` module.
265 5
266 Secondary artifacts выбираются через `artifactView`.
267
268 ```groovy
269 def jsFiles = configurations.compileView.incoming.artifactView {
270 attributes {
271 attribute(slotAttr, 'js')
272 }
273 }.files
274 ```
275
276 Здесь graph variant уже выбран, а `artifactView` выбирает нужный secondary
277 artifact representation.
278
279 ## VALIDATION
280
281 Проверяется:
282
283 - variant существует в topology model;
284 - slot contributions не ссылаются на неизвестные role/layer;
285 - при нескольких slots указан `primarySlot`;
286 - `primarySlot` ссылается на существующий slot.
287
288 ## API
289
290 ### VariantArtifactsExtension
291
292 - `variant(String)` — получить/создать variant artifact model;
293 - `variant(String, Action|Closure)` — сконфигурировать variant artifact;
294 - `getVariants()` — контейнер variant artifacts;
295 - `findVariant(name)`, `requireVariant(name)`;
296 - `whenOutgoingVariant(...)`.
297
298 ### VariantArtifact
299
300 - `slot(String)` — получить/создать slot;
301 - `slot(String, Action|Closure)` — сконфигурировать slot;
302 - `primarySlot(String)` — назначить primary slot;
303 - `primarySlot(String, Action|Closure)` — sugar: configure slot + mark as primary;
304 - `getSlots()`;
305 - `findSlot(name)`, `requireSlot(name)`;
306 - `findPrimarySlotName()`, `requirePrimarySlotName()`;
307 - `findPrimarySlot()`, `requirePrimarySlot()`.
308
309 ### VariantArtifactSlot
6 Current documentation is maintained in the root [README.md](../README.md) and
7 [variant_artifacts.md](../variant_artifacts.md).
310 8
311 - `from(Object)`;
312 - `fromVariant(...)`;
313 - `fromRole(String, ...)`;
314 - `fromLayer(String, ...)`.
315
316 Внутренняя модель:
317
318 - slot хранит contributions, а не строковые rules;
319 - `fromVariant/fromRole/fromLayer` создают topology-aware contributions;
320 - `from(Object)` создает direct contribution, который materialize-ится даже
321 если у variant-а нет ни одного `SourceSetUsageBinding`;
322 - slot отдельно хранит topology references для validation:
323 `referencedRoleNames()` и `referencedLayerNames()`.
324
325 ### OutputSelectionSpec
326
327 - `output(name)`;
328 - `output(name, extra...)`.
329
330 `OutputSelectionSpec` это внутренний DSL-buffer для одного блока
331 `fromVariant/fromRole/fromLayer`. Он локально накапливает contributions и
332 передает их в slot только после успешного завершения configure-блока.
333
334 ## KEY CLASSES
335
336 - `VariantsArtifactsPlugin` — plugin adapter и materialization outgoing variants.
337 - `VariantArtifactsExtension` — root DSL и lifecycle.
338 - `VariantArtifact` — outgoing build variant model.
339 - `VariantArtifactSlot` — artifact representation slot.
340 - `VariantArtifactsResolver` — adapter между `variantSources` bindings и
341 contribution model slot-а.
342 - `OutgoingVariantPublication` — payload variant-level publication callback.
343 - `OutgoingArtifactSlotPublication` — payload per-slot publication callback.
344 - `ArtifactAssembly` — assembled files for a slot.
345
346 ## NOTES
347
348 - `common` не навязывает доменную логику выбора primary slot.
349 - `common` не фиксирует значения `usage`, `libraryelements` и прочих
350 slot-specific attributes.
351 - `common` не смешивает эту модель с отдельными publish осями вроде package
352 metadata.
353 - Closure callbacks используют delegate-first; для вложенных closure удобнее
354 явный параметр (`publication -> ...`, `slotPublication -> ...`).
@@ -1,159 +1,9
1 # Variant Sources Plugin
2
3 ## NAME
4
5 `VariantsSourcesPlugin` и extension `variantSources`.
6
7 ## SYNOPSIS
8
9 ```groovy
10 plugins {
11 id 'org.implab.gradle-variants-sources'
12 }
13
14 variants {
15 layer('main')
16
17 variant('browser') {
18 role('main') { layers('main') }
19 }
20
21 variant('node') {
22 role('main') { layers('main') }
23 }
24 }
25
26 variantSources {
27 bind('main').sourceSetNamePattern = '{layer}'
28
29 bind('main') {
30 configureSourceSet {
31 declareOutputs('compiled')
32 }
33 }
34
35 whenRegistered { sourceSetName() }
36 whenBound('browser') { roleName() }
37 }
38 ```
1 # Moved: Variant Sources Plugin
39 2
40 ## DESCRIPTION
41
42 `VariantsSourcesPlugin` применяет `VariantsPlugin` и `SourcesPlugin`, затем
43 регистрирует source sets из модели `variants`.
44
45 Точка запуска registration:
46
47 - `variants.whenFinalized(model -> registerSourceSets(...))`
48
49 ### registration
50
51 Для каждой usage-связки `variant/role/layer` вычисляется имя source set,
52 регистрируется `GenericSourceSet` (если он еще не существует), затем
53 вызываются callbacks.
54
55 ### binding
56
57 `bind('<layer>')` возвращает `LayerBindingSpec` и задает policy для этого
58 слоя:
59
60 - как именовать source set;
61 - как конфигурировать source set;
62 - какие callbacks вызвать на registration/binding.
63
64 ### sourceSetNamePattern
65
66 `sourceSetNamePattern` определяет naming policy зарегистрированного source set.
67
68 Default:
69
70 - `{variant}{layerCap}`
71
72 Tokens:
73
74 - `{variant}`, `{variantCap}`
75 - `{role}`, `{roleCap}`
76 - `{layer}`, `{layerCap}`
77
78 Имя санитизируется (`[^A-Za-z0-9_.-] -> _`).
3 The `VariantSourcesPlugin` implementation is now part of the `variants` module,
4 not the `common` module.
79 5
80 Ограничение:
81
82 - один `sourceSetName` не может быть порожден разными слоями.
83
84 ## EVENTS
85
86 ### whenRegistered
87
88 - callback на новый уникальный source set;
89 - replayable;
90 - при shared source set срабатывает один раз.
91
92 ### whenBound
93
94 - callback на каждую usage-связку `variant/role/layer`;
95 - replayable;
96 - подходит для per-usage логики.
97
98 ### variant filter
99
100 Фильтр по варианту поддерживает только usage-binding:
101
102 - `whenBound(String variantName, ...)`
103
104 ## PAYLOAD TYPES
105
106 `SourceSetRegistration` содержит:
107
108 - `layerName`, `sourceSetName`;
109 - `sourceSet` (`NamedDomainObjectProvider<GenericSourceSet>`).
110
111 Sugar:
112
113 - `configureSourceSet(Action|Closure)`.
114
115 `SourceSetUsageBinding` содержит:
116
117 - `variantName`, `roleName`, `layerName`, `sourceSetName`;
118 - `sourceSet` (`NamedDomainObjectProvider<GenericSourceSet>`).
6 Current documentation is maintained in the root [README.md](../README.md),
7 [variant_sources.md](../variant_sources.md), and
8 [variant_sources_precedence.md](../variant_sources_precedence.md).
119 9
120 Sugar:
121
122 - `configureSourceSet(Action|Closure)`.
123
124 ## API
125
126 ### VariantSourcesExtension
127
128 - `bind(BuildLayer)` — получить/создать binding для canonical layer identity.
129 - `bind(String)` — получить/создать binding по имени слоя.
130 - `bind(String, Action|Closure)` — сконфигурировать binding.
131 - `bind(BuildLayer, Action|Closure)` — сконфигурировать binding по `BuildLayer`.
132 - `getBindings()` — read-only snapshot текущих bindings.
133 - `whenRegistered(...)` — глобальные callbacks регистрации source set.
134 - `whenBound(...)` — глобальные callbacks usage-binding.
135 - `whenBound(String variantName, ...)` — usage-binding callbacks с variant-filter.
136
137 ### LayerBindingSpec
138
139 - `sourceSetNamePattern` — naming policy для source set слоя.
140 - `configureSourceSet(...)` — слойная конфигурация `GenericSourceSet`.
141 - `whenRegistered(...)` — callbacks регистрации в рамках слоя.
142 - `whenBound(...)` — callbacks usage-binding в рамках слоя.
143
144 ## KEY CLASSES
145
146 - `VariantsSourcesPlugin` — точка входа plugin adapter.
147 - `VariantSourcesExtension` — глобальный DSL bind/events.
148 - `LayerBindingSpec` — публичный DSL-contract layer-local policy/callbacks.
149 - `SourceSetRegistration` — payload регистрации source set.
150 - `SourceSetUsageBinding` — payload usage-binding.
151
152 ## NOTES
153
154 - `sourceSetNamePattern` фиксируется при первом чтении в registration
155 (`finalizeValueOnRead`).
156 - runtime state bindings скрыт внутри adapter implementation (`LayerBinding`).
157 - name-based bindings резолвятся к canonical `BuildLayer` через registry `variants`.
158 - Closure callbacks используют delegate-first.
159 - Для вложенных closure лучше явный параметр (`ctx -> ...`).
@@ -1,112 +1,8
1 # Variants Plugin
2
3 ## NAME
4
5 `VariantsPlugin` и extension `variants`.
6
7 ## SYNOPSIS
8
9 ```groovy
10 plugins {
11 id 'org.implab.gradle-variants'
12 }
13
14 variants {
15 layer('mainBase')
16 layer('mainAmd')
17
18 variant('browser') {
19 attributes {
20 string('jsRuntime', 'browser')
21 string('jsModule', 'amd')
22 }
23
24 role('main') {
25 layers('mainBase', 'mainAmd')
26 }
27
28 artifactSlot('mainCompiled')
29 }
30 }
31 ```
32
33 ## DESCRIPTION
34
35 `VariantsPlugin` задает доменную модель сборки и ее валидацию. Плагин не
36 регистрирует compile/copy/bundle задачи напрямую.
37
38 ### layers
39
40 Глобальные логические слои. Служат единым словарем имен, на которые затем
41 ссылаются роли.
42
43 ### variants
44
45 Именованные варианты исполнения/пакетирования (`browser`, `node`, и т.д.).
46 Вариант агрегирует роли, атрибуты и artifact slots.
47
48 ### roles
49
50 Роль описывает набор слоев в пределах варианта (`main`, `test`, `tools`).
51 Одна роль может ссылаться на несколько слоев.
52
53 ### attributes
1 # Moved: Variants Plugin
54 2
55 Typed-атрибуты (`Attribute<T> -> Provider<T>`) для передачи параметров в
56 адаптеры и публикацию артефактов.
57
58 ### artifact slots
59
60 Именованные слоты ожидаемых артефактов варианта. Используются как контракт
61 между моделью варианта и плагинами, создающими/публикующими результаты.
62
63 ## VALIDATION
64
65 В `finalizeModel()` выполняется проверка:
66
67 - роль не может ссылаться на неизвестный layer;
68 - пустые имена layer запрещены;
69 - имена ролей в варианте должны быть уникальны;
70 - имена artifact slots в варианте должны быть уникальны.
71
72 ## LIFECYCLE
73
74 - `VariantsPlugin` вызывает `variants.finalizeModel()` на `afterEvaluate`.
75 - после `finalizeModel()` мутации модели запрещены.
76 - `whenFinalized(...)` replayable.
77
78 ## API
79
80 ### BuildVariantsExtension
3 The `VariantsPlugin` implementation is now part of the `variants` module, not
4 the `common` module.
81 5
82 - `layer(...)` — объявление или конфигурация `BuildLayer`.
83 - `variant(...)` — объявление или конфигурация `BuildVariant`.
84 - `layers { layer(...) }`, `variants { ... }` — grouped DSL без публикации container API наружу.
85 - `all(...)` — callback для всех вариантов.
86 - `findLayer(name)`, `requireLayer(name)`, `getAllLayers()` — доступ к registry слоев.
87 - `getAll()`, `find(name)`, `require(name)` — доступ к вариантам.
88 - `validate()` — явный запуск валидации.
89 - `finalizeModel()` — валидация + финализация модели.
90 - `whenFinalized(...)` — callback по завершенной модели (replayable).
91
92 ### BuildVariant
93
94 - `attributes { ... }` — атрибуты варианта (+ sugar `string/bool/integer`).
95 - `role(...)`, `roles { ... }` — роли варианта.
96 - `artifactSlot(...)`, `artifactSlots { ... }` — артефактные слоты.
6 Current documentation is maintained in the root [README.md](../README.md) and
7 the design notes in [variant_sources.md](../variant_sources.md).
97 8
98 ## KEY CLASSES
99
100 - `VariantsPlugin` — точка входа плагина.
101 - `BuildVariantsExtension` — root extension и lifecycle.
102 - `BuildVariant` — агрегатная модель варианта.
103 - `BuildLayer` — canonical identity-model слоя.
104 - `BuildRole` — модель роли.
105 - `BuildArtifactSlot` — модель артефактного слота.
106 - `VariantAttributes` — typed wrapper для variant attributes.
107
108 ## NOTES
109
110 - Модель `variants` intentionally agnostic к toolchain.
111 - Layer registry хранится как явная identity-map, а не как публичный `NamedDomainObjectContainer`.
112 - Интеграция с задачами выполняется через `variantSources` и адаптеры.
@@ -1,2 +1,2
1 1 group=org.implab.gradle
2 version=1.0 No newline at end of file
2 version=0.1.0
@@ -1,5 +1,9
1 1 # Variants and Variant Artifacts
2 2
3 > Design note. The current user-facing DSL and local publication workflow are
4 > documented in [README.md](README.md). Some snippets below are conceptual and
5 > describe model direction rather than exact public API.
6
3 7 ## Overview
4 8
5 9 This document describes the artifact model built on top of `variants` and
@@ -592,7 +596,7 model rather than define it.
592 596
593 597 Examples:
594 598
595 - `whenOutgoingVariant(...)`
599 - `whenOutgoingConfiguration(...)`
596 600 - `whenOutgoingSlot(...)`
597 601
598 602 These hooks are adapter-facing customization points over already declared
@@ -1,5 +1,9
1 1 # Variants and Variant Sources
2 2
3 > Design note. The current user-facing DSL and local publication workflow are
4 > documented in [README.md](README.md). Some snippets below are conceptual and
5 > describe model direction rather than exact public API.
6
3 7 ## Overview
4 8
5 9 This document describes a two-layer model for build variants:
@@ -510,7 +514,8 This policy is intentionally modeled as
510 514 property:
511 515
512 516 * it must be chosen before the first selector rule is added
513 * selector rules here mean `variant(...)`, `layer(...)`, and `unit(...)`
517 * selector rules here mean `configureEach(...)`, `variant(...)`, `layer(...)`,
518 and `unit(...)`
514 519 * once chosen, it cannot be changed later
515 520 * it controls runtime behavior, not just a stored value
516 521 * the enforcement point is the first selector registration itself, not variants
@@ -519,7 +524,7 property:
519 524 For source sets configured before materialization, selector precedence remains:
520 525
521 526 ```text
522 variant < layer < unit
527 configureEach < variant < layer < unit
523 528 ```
524 529
525 530 For already materialized source sets in `warn` and `allow` modes:
@@ -16,14 +16,36 Instead, it provides configuration selec
16 16
17 17 ## Selectors
18 18
19 Three selectors are available:
19 Four selectors are available:
20 20
21 - `configureEach(...)`
21 22 - `variant(...)`
22 23 - `layer(...)`
23 24 - `unit(...)`
24 25
25 26 They all target the same set of compile units, but at different levels of specificity.
26 27
28 ### `configureEach(...)`
29
30 `configureEach(...)` applies configuration to every materialized compile-unit
31 source set.
32
33 Example:
34
35 ```groovy
36 variantSources {
37 configureEach {
38 sourceSet {
39 declareOutputs("js")
40 }
41 }
42 }
43 ```
44
45 Use this selector for global source-set conventions.
46
47 ---
48
27 49 ### `variant(...)`
28 50
29 51 `variant(...)` applies configuration to all compile units that belong to the given variant.
@@ -33,9 +55,11 Example:
33 55 ```groovy
34 56 variantSources {
35 57 variant("browser") {
58 sourceSet {
36 59 declareOutputs("js", "dts")
37 60 }
38 61 }
62 }
39 63 ```
40 64
41 65 This affects all compile units of `browser`, for example:
@@ -57,11 +81,13 Example:
57 81 ```groovy
58 82 variantSources {
59 83 layer("main") {
60 set("ts") {
84 sourceSet {
85 sets.create("ts") {
61 86 srcDir("src/main/ts")
62 87 }
63 88 }
64 89 }
90 }
65 91 ```
66 92
67 93 This affects all compile units with layer `main`, for example:
@@ -83,11 +109,13 Example:
83 109 ```groovy
84 110 variantSources {
85 111 unit("browser", "main") {
86 set("resources") {
112 sourceSet {
113 sets.create("resources") {
87 114 srcDir("src/browserMain/resources")
88 115 }
89 116 }
90 117 }
118 }
91 119 ```
92 120
93 121 This affects only:
@@ -103,14 +131,15 Use this selector for the most specific
103 131 For each compile unit, source-set configuration is applied in the following order:
104 132
105 133 ```text
106 variant < layer < unit
134 configureEach < variant < layer < unit
107 135 ```
108 136
109 137 This means:
110 138
111 1. `variant(...)` actions are applied first
112 2. `layer(...)` actions are applied next
113 3. `unit(...)` actions are applied last
139 1. `configureEach(...)` actions are applied first
140 2. `variant(...)` actions are applied next
141 3. `layer(...)` actions are applied next
142 4. `unit(...)` actions are applied last
114 143
115 144 Each next level is allowed to refine or override the previous one.
116 145
@@ -160,7 +189,8 Available modes:
160 189 Policy rules:
161 190
162 191 - the policy must be chosen before the first selector rule is added
163 - selector rules here mean `variant(...)`, `layer(...)`, and `unit(...)`
192 - selector rules here mean `configureEach(...)`, `variant(...)`, `layer(...)`,
193 and `unit(...)`
164 194 - once chosen, the policy cannot be changed later
165 195 - the policy is single-valued; it is not intended to be switched during further
166 196 configuration
@@ -173,8 +203,8 Operationally:
173 203 already materialized targets
174 204 - `warn` and `allow` keep compatibility with imperative late mutation
175 205 - in `warn` and `allow`, already materialized targets observe the late action in
176 actual registration order, not in reconstructed `variant < layer < unit`
177 order
206 actual registration order, not in reconstructed
207 `configureEach < variant < layer < unit` order
178 208
179 209 ---
180 210
@@ -234,11 +264,11 Naming policy is fixed when the finalize
234 264
235 265 Operationally this means:
236 266
237 - policy selection must happen before `variantSources.whenFinalized(...)`
267 - policy selection must happen before `variantSources.whenAvailable(...)`
238 268 becomes observable
239 269 - compile-unit names are projected and validated before queued
240 `whenFinalized(...)` callbacks are replayed
241 - changing naming policy from inside a `whenFinalized(...)` callback is too late
270 `whenAvailable(...)` callbacks are replayed
271 - changing naming policy from inside a `whenAvailable(...)` callback is too late
242 272
243 273 ---
244 274
@@ -246,22 +276,34 Operationally this means:
246 276
247 277 ```groovy
248 278 variantSources {
279 configureEach {
280 sourceSet {
281 declareOutputs("js", "dts")
282 }
283 }
284
249 285 variant("browser") {
250 declareOutputs("js", "dts")
286 sourceSet {
287 registerOutput("js", layout.projectDirectory.file("inputs/browser.js"))
288 }
251 289 }
252 290
253 291 layer("main") {
254 set("ts") {
292 sourceSet {
293 sets.create("ts") {
255 294 srcDir("src/main/ts")
256 295 }
257 296 }
297 }
258 298
259 299 unit("browser", "main") {
260 set("resources") {
300 sourceSet {
301 sets.create("resources") {
261 302 srcDir("src/browserMain/resources")
262 303 }
263 304 }
264 305 }
306 }
265 307 ```
266 308
267 309 For compile unit `(browser, main)` the effective configuration is built in this order:
@@ -270,6 +312,9 1. `variant("browser")`
270 312 2. `layer("main")`
271 313 3. `unit("browser", "main")`
272 314
315 The global `configureEach(...)` selector is applied before the listed
316 variant/layer/unit selectors for every compile unit.
317
273 318 For compile unit `(browser, rjs)` the effective configuration is built in this order:
274 319
275 320 1. `variant("browser")`
@@ -324,7 +369,7 This guarantees that:
324 369 - precedence is:
325 370
326 371 ```text
327 variant < layer < unit
372 configureEach < variant < layer < unit
328 373 ```
329 374
330 375 - registration order is preserved within the same selector level
@@ -3,6 +3,8 plugins {
3 3 id "ivy-publish"
4 4 }
5 5
6 description = "Variant, source-set, and outgoing artifact model plugins for Gradle builds"
7
6 8 java {
7 9 withJavadocJar()
8 10 withSourcesJar()
@@ -15,9 +17,7 dependencies {
15 17 compileOnly libs.jdt.annotations
16 18
17 19 api gradleApi(),
18 libs.bundles.jackson
19
20 implementation project(":common")
20 project(":common")
21 21
22 22 testImplementation gradleTestKit()
23 23 testImplementation "org.junit.jupiter:junit-jupiter-api:5.11.4"
@@ -52,6 +52,10 publishing {
52 52 descriptor.description {
53 53 text = providers.provider({ description })
54 54 }
55 descriptor.license {
56 name = "BSD-2-Clause"
57 url = "https://spdx.org/licenses/BSD-2-Clause.html"
55 58 }
56 59 }
57 60 }
61 }
General Comments 0
You need to be logged in to leave comments. Login now