variant_sources_precedence.md
210 lines
| 4.5 KiB
| text/x-minidsrc
|
MarkdownLexer
|
|
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 | ||||
| Three selectors are available: | ||||
| - `variant(...)` | ||||
| - `layer(...)` | ||||
| - `unit(...)` | ||||
| They all target the same set of compile units, but at different levels of specificity. | ||||
| ### `variant(...)` | ||||
| `variant(...)` applies configuration to all compile units that belong to the given variant. | ||||
| Example: | ||||
| ```groovy | ||||
| variantSources { | ||||
| variant("browser") { | ||||
| declareOutputs("js", "dts") | ||||
| } | ||||
| } | ||||
| ``` | ||||
| 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") { | ||||
| set("ts") { | ||||
| srcDir("src/main/ts") | ||||
| } | ||||
| } | ||||
| } | ||||
| ``` | ||||
| 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") { | ||||
| set("resources") { | ||||
| srcDir("src/browserMain/resources") | ||||
| } | ||||
| } | ||||
| } | ||||
| ``` | ||||
| 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 | ||||
| variant < layer < unit | ||||
| ``` | ||||
| This means: | ||||
| 1. `variant(...)` actions are applied first | ||||
| 2. `layer(...)` actions are applied next | ||||
| 3. `unit(...)` actions are applied last | ||||
| 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. | ||||
| --- | ||||
| ## Example | ||||
| ```groovy | ||||
| variantSources { | ||||
| variant("browser") { | ||||
| declareOutputs("js", "dts") | ||||
| } | ||||
| layer("main") { | ||||
| set("ts") { | ||||
| srcDir("src/main/ts") | ||||
| } | ||||
| } | ||||
| unit("browser", "main") { | ||||
| set("resources") { | ||||
| srcDir("src/browserMain/resources") | ||||
| } | ||||
| } | ||||
| } | ||||
| ``` | ||||
| For compile unit `(browser, main)` the effective configuration is built in this order: | ||||
| 1. `variant("browser")` | ||||
| 2. `layer("main")` | ||||
| 3. `unit("browser", "main")` | ||||
| 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. | ||||
| Internally, selector-based configuration is accumulated and later applied by the source-set materializer when a `GenericSourceSet` is created for a compile unit. | ||||
| This guarantees that: | ||||
| - selector precedence is stable | ||||
| - registration order is preserved | ||||
| - configuration does not depend on the materialization moment | ||||
| - 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 | ||||
| variant < layer < unit | ||||
| ``` | ||||
| - registration order is preserved within the same selector level | ||||
| - `variants` defines what exists | ||||
| - `variantSources` defines how those compile units are materialized as source sets | ||||
