##// END OF EJS Templates
Upgrade Gradle to 9.4.1 and fix functional tests
Upgrade Gradle to 9.4.1 and fix functional tests

File last commit:

r60:e376d0cab00e default
r62:c7861b56e1d8 default
Show More
variant_sources_precedence.md
382 lines | 9.1 KiB | text/x-minidsrc | MarkdownLexer
/ variant_sources_precedence.md
cin
WIP almost stable variants model, working on variantSources
r41 # `variantSources`: selectors and precedence
`variantSources` configures source-set materialization over the compile-unit space.
A compile unit is defined as:
- `(variant, layer)`
This means:
- `variant` defines compilation semantics
- `layer` defines compilation partitioning
The `variantSources` DSL does not introduce a separate source model.
Instead, it provides configuration selectors over the existing compile-unit space.
## Selectors
cin
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.
r60 Four selectors are available:
cin
WIP almost stable variants model, working on variantSources
r41
cin
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.
r60 - `configureEach(...)`
cin
WIP almost stable variants model, working on variantSources
r41 - `variant(...)`
- `layer(...)`
- `unit(...)`
They all target the same set of compile units, but at different levels of specificity.
cin
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.
r60 ### `configureEach(...)`
`configureEach(...)` applies configuration to every materialized compile-unit
source set.
Example:
```groovy
variantSources {
configureEach {
sourceSet {
declareOutputs("js")
}
}
}
```
Use this selector for global source-set conventions.
---
cin
WIP almost stable variants model, working on variantSources
r41 ### `variant(...)`
`variant(...)` applies configuration to all compile units that belong to the given variant.
Example:
```groovy
variantSources {
variant("browser") {
cin
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.
r60 sourceSet {
declareOutputs("js", "dts")
}
cin
WIP almost stable variants model, working on variantSources
r41 }
}
```
This affects all compile units of `browser`, for example:
- `(browser, main)`
- `(browser, rjs)`
- `(browser, test)`
Use this selector for variant-wide conventions.
---
### `layer(...)`
`layer(...)` applies configuration to all compile units that use the given layer.
Example:
```groovy
variantSources {
layer("main") {
cin
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.
r60 sourceSet {
sets.create("ts") {
srcDir("src/main/ts")
}
cin
WIP almost stable variants model, working on variantSources
r41 }
}
}
```
This affects all compile units with layer `main`, for example:
- `(browser, main)`
- `(nodejs, main)`
- `(electron, main)`
Use this selector for cross-variant layer conventions.
---
### `unit(...)`
`unit(...)` applies configuration to one exact compile unit.
Example:
```groovy
variantSources {
unit("browser", "main") {
cin
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.
r60 sourceSet {
sets.create("resources") {
srcDir("src/browserMain/resources")
}
cin
WIP almost stable variants model, working on variantSources
r41 }
}
}
```
This affects only:
- `(browser, main)`
Use this selector for the most specific adjustments.
---
## Precedence
For each compile unit, source-set configuration is applied in the following order:
```text
cin
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.
r60 configureEach < variant < layer < unit
cin
WIP almost stable variants model, working on variantSources
r41 ```
This means:
cin
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.
r60 1. `configureEach(...)` actions are applied first
2. `variant(...)` actions are applied next
3. `layer(...)` actions are applied next
4. `unit(...)` actions are applied last
cin
WIP almost stable variants model, working on variantSources
r41
Each next level is allowed to refine or override the previous one.
### Within the same level
Within the same selector level, actions are applied in registration order.
For example, if two plugins both configure `layer("main")`, their actions are applied in the same order in which they were registered.
cin
Add compile-unit naming policy and late-configuration enforcement to VariantSourcesPlugin
r43 ### Scope of this guarantee
This precedence describes the normal materialization order used by the source-set
materializer.
It is stable for source sets that are configured before they are materialized.
If a selector rule is added after a target source set has already been
materialized, the behavior depends on the selected late-configuration policy.
- in `fail` mode, such late configuration is rejected
- in `warn` and `allow` modes, the late action is applied as an imperative
follow-up step
- in `warn` and `allow` modes, selector precedence is not reconstructed
retroactively for already materialized targets
---
## Late Configuration Policy
`variantSources` exposes a policy switch for selector rules that target already
materialized source sets:
```groovy
variantSources {
lateConfigurationPolicy {
failOnLateConfiguration()
}
}
```
Available modes:
- `failOnLateConfiguration()` rejects such rules
- `warnOnLateConfiguration()` allows them and emits a warning
- `allowLateConfiguration()` allows them silently
Policy rules:
- the policy must be chosen before the first selector rule is added
cin
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.
r60 - selector rules here mean `configureEach(...)`, `variant(...)`, `layer(...)`,
and `unit(...)`
cin
Add compile-unit naming policy and late-configuration enforcement to VariantSourcesPlugin
r43 - once chosen, the policy cannot be changed later
- the policy is single-valued; it is not intended to be switched during further
configuration
cin
more documentation
r44 - the enforcement point is the first selector registration itself; finalization
of `variants` alone does not freeze this policy
cin
Add compile-unit naming policy and late-configuration enforcement to VariantSourcesPlugin
r43
Operationally:
- `fail` preserves the strict precedence contract by rejecting late mutation of
already materialized targets
- `warn` and `allow` keep compatibility with imperative late mutation
- in `warn` and `allow`, already materialized targets observe the late action in
cin
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.
r60 actual registration order, not in reconstructed
`configureEach < variant < layer < unit` order
cin
Add compile-unit naming policy and late-configuration enforcement to VariantSourcesPlugin
r43
cin
WIP almost stable variants model, working on variantSources
r41 ---
cin
more documentation
r44 ## Compile-Unit Naming Policy
`variantSources` also exposes a policy for projecting compile units to symbolic
source-set names:
```groovy
variantSources {
namingPolicy {
failOnNameCollision()
}
}
```
Base projected name:
- `sourceSetName = variantName + capitalize(layerName)`
Example:
- `(browser, main)` -> `browserMain`
- `(browser, rjs)` -> `browserRjs`
Available modes:
- `failOnNameCollision()` rejects finalized compile-unit models that project the
same base name for different compile units
- `resolveNameCollision()` resolves such collisions deterministically
### `resolveNameCollision()` semantics
Conflicting compile units are ordered canonically by:
```text
(variant.name, layer.name)
```
Name assignment in a conflicting group is:
- the first compile unit keeps the base name
- the second gets suffix `2`
- the third gets suffix `3`
- and so on
Example:
- `(foo, variantBar)` and `(fooVariant, bar)` both project to `fooVariantBar`
- after canonical ordering:
- `(foo, variantBar)` -> `fooVariantBar`
- `(fooVariant, bar)` -> `fooVariantBar2`
### Fixation Point
Naming policy is fixed when the finalized `VariantSourcesContext` is created.
Operationally this means:
cin
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.
r60 - policy selection must happen before `variantSources.whenAvailable(...)`
cin
more documentation
r44 becomes observable
- compile-unit names are projected and validated before queued
cin
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.
r60 `whenAvailable(...)` callbacks are replayed
- changing naming policy from inside a `whenAvailable(...)` callback is too late
cin
more documentation
r44
---
cin
WIP almost stable variants model, working on variantSources
r41 ## Example
```groovy
variantSources {
cin
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.
r60 configureEach {
sourceSet {
declareOutputs("js", "dts")
}
}
cin
WIP almost stable variants model, working on variantSources
r41 variant("browser") {
cin
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.
r60 sourceSet {
registerOutput("js", layout.projectDirectory.file("inputs/browser.js"))
}
cin
WIP almost stable variants model, working on variantSources
r41 }
layer("main") {
cin
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.
r60 sourceSet {
sets.create("ts") {
srcDir("src/main/ts")
}
cin
WIP almost stable variants model, working on variantSources
r41 }
}
unit("browser", "main") {
cin
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.
r60 sourceSet {
sets.create("resources") {
srcDir("src/browserMain/resources")
}
cin
WIP almost stable variants model, working on variantSources
r41 }
}
}
```
For compile unit `(browser, main)` the effective configuration is built in this order:
1. `variant("browser")`
2. `layer("main")`
3. `unit("browser", "main")`
cin
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.
r60 The global `configureEach(...)` selector is applied before the listed
variant/layer/unit selectors for every compile unit.
cin
WIP almost stable variants model, working on variantSources
r41 For compile unit `(browser, rjs)` the effective configuration is built in this order:
1. `variant("browser")`
2. `layer("rjs")` if present
3. `unit("browser", "rjs")` if present
For compile unit `(nodejs, main)` the effective configuration is built in this order:
1. `variant("nodejs")` if present
2. `layer("main")`
3. `unit("nodejs", "main")` if present
---
## Model boundary
These selectors do not define compile units.
Compile units are derived from finalized `variants`.
`variantSources` only configures how source sets are materialized for those units.
This means:
- `variants` is the source of truth for compile-unit existence
- `variantSources` is the source of truth for compile-unit source-set configuration
---
## Operational semantics
The `variantSources` API is exposed through a finalized context.
Conceptually, configuration is registered against finalized model objects, while DSL sugar may still use names for convenience.
cin
Add compile-unit naming policy and late-configuration enforcement to VariantSourcesPlugin
r43 Internally, selector-based configuration is accumulated and later applied by the
source-set materializer when a `GenericSourceSet` is created for a compile unit.
cin
WIP almost stable variants model, working on variantSources
r41
This guarantees that:
cin
Add compile-unit naming policy and late-configuration enforcement to VariantSourcesPlugin
r43 - selector precedence is stable before materialization
cin
WIP almost stable variants model, working on variantSources
r41 - registration order is preserved
cin
Add compile-unit naming policy and late-configuration enforcement to VariantSourcesPlugin
r43 - configuration of already materialized targets is governed by the selected
late-configuration policy
cin
WIP almost stable variants model, working on variantSources
r41 - adapters do not need to depend on raw Gradle lifecycle timing
---
## Summary
- compile unit space is `(variant, layer)`
- `variant(...)`, `layer(...)`, and `unit(...)` are selectors over that space
- precedence is:
```text
cin
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.
r60 configureEach < variant < layer < unit
cin
WIP almost stable variants model, working on variantSources
r41 ```
- registration order is preserved within the same selector level
cin
Add compile-unit naming policy and late-configuration enforcement to VariantSourcesPlugin
r43 - already materialized targets are handled by `lateConfigurationPolicy(...)`
- the late-configuration policy must be selected before the first selector rule
and cannot be changed later
cin
more documentation
r44 - compile-unit naming is governed by `namingPolicy(...)`
- by default, name collisions fail fast during finalized context creation
cin
WIP almost stable variants model, working on variantSources
r41 - `variants` defines what exists
- `variantSources` defines how those compile units are materialized as source sets