##// END OF EJS Templates
Add minimum Gradle compatibility functional test
Add minimum Gradle compatibility functional test

File last commit:

r61:9b11838beca6 default
r63:79fd940a7856 tip default
Show More
README.md
306 lines | 6.8 KiB | text/x-minidsrc | MarkdownLexer

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.

Local Build

./gradlew clean check javadoc jar sourcesJar javadocJar --rerun-tasks

Configuration cache smoke check:

./gradlew check --configuration-cache

Local Ivy Publication

The current publication target is:

${user.home}/ivy-repo

Publish both modules locally:

./gradlew :common:publishIvyPublicationToIvyRepository \
          :variants:publishIvyPublicationToIvyRepository

or:

./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:

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.

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.

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:

(variant, layer)

Selectors configure materialized compile-unit source sets:

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:

configureEach -> variant -> layer -> unit

Late selector registration is controlled by:

variantSources {
    lateConfigurationPolicy {
        failOnLateConfiguration()
    }
}

Compile-unit source set names are generated by default as:

<variant> + capitalize(<layer>)

Name collisions fail by default and may be resolved deterministically:

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.
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}"
    }
}

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.

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.