| @@ -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" | |
|
|
54 | } | |
|
|
49 | 55 | } |
|
|
50 | 56 | } |
|
|
51 | 57 | } |
| @@ -1,134 +1,18 | |||
|
|
1 |
# Gradle Common |
|
|
|
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,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 |
- `whenOutgoing |
|
|
|
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(...)`, |
|
|
|
517 | * selector rules here mean `configureEach(...)`, `variant(...)`, `layer(...)`, | |
|
|
518 | and `unit(...)` | |
|
|
514 | 519 | * once chosen, it cannot be changed later |
|
|
515 | 520 |
|
|
|
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 |
|
|
|
|
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,7 +55,9 Example: | |||
|
|
33 | 55 | ```groovy |
|
|
34 | 56 | variantSources { |
|
|
35 | 57 | variant("browser") { |
|
|
36 | declareOutputs("js", "dts") | |
|
|
58 | sourceSet { | |
|
|
59 | declareOutputs("js", "dts") | |
|
|
60 | } | |
|
|
37 | 61 | } |
|
|
38 | 62 | } |
|
|
39 | 63 | ``` |
| @@ -57,8 +81,10 Example: | |||
|
|
57 | 81 | ```groovy |
|
|
58 | 82 | variantSources { |
|
|
59 | 83 | layer("main") { |
|
|
60 |
s |
|
|
|
61 |
s |
|
|
|
84 | sourceSet { | |
|
|
85 | sets.create("ts") { | |
|
|
86 | srcDir("src/main/ts") | |
|
|
87 | } | |
|
|
62 | 88 | } |
|
|
63 | 89 | } |
|
|
64 | 90 | } |
| @@ -83,8 +109,10 Example: | |||
|
|
83 | 109 | ```groovy |
|
|
84 | 110 | variantSources { |
|
|
85 | 111 | unit("browser", "main") { |
|
|
86 |
|
|
|
|
87 |
s |
|
|
|
112 | sourceSet { | |
|
|
113 | sets.create("resources") { | |
|
|
114 | srcDir("src/browserMain/resources") | |
|
|
115 | } | |
|
|
88 | 116 | } |
|
|
89 | 117 | } |
|
|
90 | 118 | } |
| @@ -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. ` |
|
|
|
112 |
2. ` |
|
|
|
113 |
3. ` |
|
|
|
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(...)`, |
|
|
|
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 |
|
|
|
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.when |
|
|
|
267 | - policy selection must happen before `variantSources.whenAvailable(...)` | |
|
|
238 | 268 | becomes observable |
|
|
239 | 269 | - compile-unit names are projected and validated before queued |
|
|
240 |
`when |
|
|
|
241 |
- changing naming policy from inside a `when |
|
|
|
270 | `whenAvailable(...)` callbacks are replayed | |
|
|
271 | - changing naming policy from inside a `whenAvailable(...)` callback is too late | |
|
|
242 | 272 | |
|
|
243 | 273 | --- |
|
|
244 | 274 | |
| @@ -246,19 +276,31 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 |
s |
|
|
|
255 |
s |
|
|
|
292 | sourceSet { | |
|
|
293 | sets.create("ts") { | |
|
|
294 | srcDir("src/main/ts") | |
|
|
295 | } | |
|
|
256 | 296 | } |
|
|
257 | 297 | } |
|
|
258 | 298 | |
|
|
259 | 299 | unit("browser", "main") { |
|
|
260 |
|
|
|
|
261 |
s |
|
|
|
300 | sourceSet { | |
|
|
301 | sets.create("resources") { | |
|
|
302 | srcDir("src/browserMain/resources") | |
|
|
303 | } | |
|
|
262 | 304 | } |
|
|
263 | 305 | } |
|
|
264 | 306 | } |
| @@ -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" | |
|
|
58 | } | |
|
|
55 | 59 | } |
|
|
56 | 60 | } |
|
|
57 | 61 | } |
General Comments 0
You need to be logged in to leave comments.
Login now
