README.md
306 lines
| 6.8 KiB
| text/x-minidsrc
|
MarkdownLexer
|
|
r60 | # gradle-common | ||
| Java 21 multi-project build with shared Gradle utilities and experimental | ||||
| variant-oriented Gradle plugins. | ||||
| The repository currently publishes to a local Ivy repository only. Maven Central | ||||
| and Gradle Plugin Portal publication are intentionally not configured yet. | ||||
| ## Modules | ||||
| - `common` - shared Gradle utilities, JSON helpers, shell execution helpers, and | ||||
| small core value/util classes. | ||||
| - `variants` - Gradle plugins for variant topology, source-set materialization, | ||||
| and outgoing artifact slots. | ||||
| ## Requirements | ||||
| - JDK 21. | ||||
| - Gradle Wrapper from this repository, currently Gradle 8.10.2. | ||||
| The produced bytecode targets Java 21. | ||||
| ## License | ||||
| This project is licensed under the BSD 2-Clause "Simplified" License | ||||
| (`BSD-2-Clause`). See [LICENSE](LICENSE). | ||||
| ## Local Build | ||||
| ```bash | ||||
| ./gradlew clean check javadoc jar sourcesJar javadocJar --rerun-tasks | ||||
| ``` | ||||
| Configuration cache smoke check: | ||||
| ```bash | ||||
| ./gradlew check --configuration-cache | ||||
| ``` | ||||
| ## Local Ivy Publication | ||||
| The current publication target is: | ||||
| ```text | ||||
| ${user.home}/ivy-repo | ||||
| ``` | ||||
| Publish both modules locally: | ||||
| ```bash | ||||
| ./gradlew :common:publishIvyPublicationToIvyRepository \ | ||||
| :variants:publishIvyPublicationToIvyRepository | ||||
| ``` | ||||
| or: | ||||
| ```bash | ||||
| ./gradlew publish | ||||
| ``` | ||||
| The publication includes: | ||||
| - main jar | ||||
| - sources jar | ||||
| - javadoc jar | ||||
| - Ivy descriptor | ||||
| - Gradle module metadata | ||||
| ## Local Consumption | ||||
| Current plugin ids are packaged as classic Gradle plugin marker resources inside | ||||
| the `variants` jar: | ||||
| - `org.implab.gradle-variants` | ||||
| - `org.implab.gradle-sources` | ||||
| - `org.implab.gradle-variants-sources` | ||||
| - `org.implab.gradle-variants-artifacts` | ||||
| Until Gradle Plugin Portal marker artifacts are configured, consume the plugin | ||||
| through `buildscript` classpath: | ||||
| ```groovy | ||||
| buildscript { | ||||
| repositories { | ||||
| ivy { | ||||
| url "${System.properties['user.home']}/ivy-repo" | ||||
| } | ||||
| mavenCentral() | ||||
| } | ||||
| dependencies { | ||||
| classpath 'org.implab.gradle:variants:0.1.0' | ||||
| } | ||||
| } | ||||
| apply plugin: 'org.implab.gradle-variants' | ||||
| apply plugin: 'org.implab.gradle-variants-sources' | ||||
| ``` | ||||
| The `plugins { id(...) version(...) }` DSL is not part of the current local Ivy | ||||
| contract. | ||||
| ## Variants DSL | ||||
| `variants` defines the finalized build topology. It does not create compile | ||||
| tasks, source directories, or outgoing publications by itself. | ||||
| ```groovy | ||||
| apply plugin: 'org.implab.gradle-variants' | ||||
| variants.layers.create('main') | ||||
| variants.layers.create('test') | ||||
| variants.roles.create('main') | ||||
| variants.roles.create('test') | ||||
| variants.variant('browser') { | ||||
| role('main') { | ||||
| layers('main') | ||||
| } | ||||
| role('test') { | ||||
| layers('main', 'test') | ||||
| } | ||||
| } | ||||
| variants.whenFinalized { view -> | ||||
| println view.entries.collect { | ||||
| "${it.variant().name}:${it.role().name}:${it.layer().name}" | ||||
| }.sort() | ||||
| } | ||||
| ``` | ||||
| The finalized model exposes cheap identity objects: `Variant`, `Role`, `Layer`, | ||||
| and the normalized relation `(variant, role, layer)`. | ||||
| ## Sources DSL | ||||
| `sources` creates standalone `GenericSourceSet` objects. This is useful for | ||||
| fallback workflows that do not need variant topology. | ||||
| ```groovy | ||||
| apply plugin: 'org.implab.gradle-sources' | ||||
| sources.create('main') { | ||||
| declareOutputs('js') | ||||
| registerOutput('js', layout.projectDirectory.file('inputs/main.js')) | ||||
| sets.create('ts') { | ||||
| srcDir 'src/main/ts' | ||||
| } | ||||
| } | ||||
| ``` | ||||
| `SourcesPlugin` applies layout conventions: | ||||
| - `sourceSetDir = src/<sourceSet>` | ||||
| - `outputsDir = build/out/<sourceSet>` | ||||
| The base `GenericSourceSet` model itself is convention-free. | ||||
| ## Variant Sources DSL | ||||
| `variantSources` derives compile units from finalized `variants`. | ||||
| A compile unit is: | ||||
| ```text | ||||
| (variant, layer) | ||||
| ``` | ||||
| Selectors configure materialized compile-unit source sets: | ||||
| ```groovy | ||||
| apply plugin: 'org.implab.gradle-variants-sources' | ||||
| variants.layers.create('main') | ||||
| variants.roles.create('main') | ||||
| variants.variant('browser') { | ||||
| role('main') { | ||||
| layers('main') | ||||
| } | ||||
| } | ||||
| variantSources { | ||||
| layer('main') { | ||||
| sourceSet { | ||||
| declareOutputs('js') | ||||
| registerOutput('js', layout.projectDirectory.file('inputs/browser.js')) | ||||
| } | ||||
| } | ||||
| configureEach { | ||||
| println "sourceSet=${sourceSet.name}, variant=${variant.name}, layer=${layer.name}" | ||||
| } | ||||
| } | ||||
| ``` | ||||
| Selector order for future materialization is: | ||||
| ```text | ||||
| configureEach -> variant -> layer -> unit | ||||
| ``` | ||||
| Late selector registration is controlled by: | ||||
| ```groovy | ||||
| variantSources { | ||||
| lateConfigurationPolicy { | ||||
| failOnLateConfiguration() | ||||
| } | ||||
| } | ||||
| ``` | ||||
| Compile-unit source set names are generated by default as: | ||||
| ```text | ||||
| <variant> + capitalize(<layer>) | ||||
| ``` | ||||
| Name collisions fail by default and may be resolved deterministically: | ||||
| ```groovy | ||||
| variantSources { | ||||
| namingPolicy { | ||||
| resolveNameCollision() | ||||
| } | ||||
| } | ||||
| ``` | ||||
| ## Variant Artifacts DSL | ||||
| `variantArtifacts` is an experimental outgoing artifact layer over `variants` | ||||
| and `variantSources`. | ||||
| The current model maps: | ||||
| - `Variant` to a variant-level consumable outgoing configuration. | ||||
| - `Slot` to a Gradle outgoing artifact variant inside that configuration. | ||||
| - `primarySlot` to the primary artifact set of the outgoing configuration. | ||||
| ```groovy | ||||
| apply plugin: 'org.implab.gradle-variants-artifacts' | ||||
| variants.layers.create('main') | ||||
| variants.roles.create('main') | ||||
| variants.variant('browser') { | ||||
| role('main') { | ||||
| layers('main') | ||||
| } | ||||
| } | ||||
| variantSources.layer('main') { | ||||
| sourceSet { | ||||
| declareOutputs('types', 'js') | ||||
| registerOutput('types', layout.projectDirectory.file('inputs/index.d.ts')) | ||||
| registerOutput('js', layout.projectDirectory.file('inputs/index.js')) | ||||
| } | ||||
| } | ||||
| variantArtifacts { | ||||
| variant('browser') { | ||||
| primarySlot('typesPackage') { | ||||
| fromVariant { | ||||
| output('types') | ||||
| } | ||||
| } | ||||
| slot('js') { | ||||
| fromVariant { | ||||
| output('js') | ||||
| } | ||||
| } | ||||
| } | ||||
| whenOutgoingConfiguration { publication -> | ||||
| publication.configuration { | ||||
| description = "Outgoing contract for ${publication.variant.name}" | ||||
| } | ||||
| } | ||||
| whenOutgoingSlot { publication -> | ||||
| println "slot=${publication.artifactSlot.slot.name}, primary=${publication.primary}" | ||||
| } | ||||
| } | ||||
| ``` | ||||
|
|
r61 | Slot bodies have two assembly modes: | ||
| - contribution-based assembly with `from(...)`, `fromVariant(...)`, | ||||
| `fromRole(...)`, or `fromLayer(...)`; the plugin copies selected inputs into a | ||||
| managed directory and publishes that directory; | ||||
| - task-produced assembly with `producedBy(task) { outputFile }`; the mapped task | ||||
| output file or directory is published directly. | ||||
| These modes are mutually exclusive for one slot. | ||||
|
|
r60 | The artifact API is still considered pre-1.0 and may change. | ||
| ## Publication Status | ||||
| Current status: | ||||
| - local Ivy publication only | ||||
| - no Maven Central publication metadata | ||||
| - no signing | ||||
| - no Gradle Plugin Portal marker artifacts | ||||
| - BSD-2-Clause license committed | ||||
| Before external publication, see [RELEASE_CHECKLIST.md](RELEASE_CHECKLIST.md). | ||||
