Pre compiled script plugin and compile time vars

I’m trying to dynamically set the version catalog version used in my pre compiled script settings plugin.

my problem is that it is evaluated at application compile time and not script compile time.

Is there a method to set variables for pre compiled script compile time.

What i want to happen

dependencyResolutionManagement {
    versionCatalogs {
        libs {
            from("com.mycompany:catalog:${version}")
        }
    }
}

generates at plugin compile in settings plugin
./gradlew clean build -Pversion=1.0.0

dependencyResolutionManagement {
    versionCatalogs {
        libs {
            from("com.mycompany:catalog:1.0.0")
        }
    }
}

running on application consuming plugin should only need
./gradlew clean build

What happens

dependencyResolutionManagement {
    versionCatalogs {
        libs {
            from("com.mycompany:catalog:${version}")
        }
    }
}

generates at plugin compile in settings plugin
./gradlew clean build -Pversion=1.0.0

dependencyResolutionManagement {
    versionCatalogs {
        libs {
            from("com.mycompany:catalog:${version}")
        }
    }
}

requires the application consuming the plugin to specify the version in a parameter
./gradlew clean build -Pversion=1.0.0

Read the property in the build script of your plugin, write it to some file, for example using expand on processResources to replace a placeholder in a properties file, read the version from that file in your plugin.

So reading files from resources was a bit beyond me here so decided to go with a code generation approach. even if this is possibly not the simplest method hopefully it helps someone in the future.

What this effectively does is use code generation through kotlinpoet to generate a class containing a constant with the version in it. its then added to the class path so its accessible to the settings plugin.

build.gradle.kts

import com.squareup.kotlinpoet.FileSpec
import com.squareup.kotlinpoet.TypeSpec
import com.squareup.kotlinpoet.PropertySpec
import com.squareup.kotlinpoet.KModifier

buildscript {
  dependencies {
    classpath("com.squareup:kotlinpoet:1.18.1")
  }
}

val generateVersion by tasks.register("generateVersion") {
  val outputDir = file("build/generated-sources/version")
  outputs.dir(outputDir)
  doLast {
    val version = project.getProperties().getOrDefault("version", "0.0.0") as String
    val classSpec = TypeSpec.classBuilder("Version")
      .addType(
        TypeSpec.companionObjectBuilder()
          .addProperty(
            PropertySpec.builder("VERSION", String::class)
              .addModifiers(KModifier.CONST)
              .initializer("\"${version}\"")
              .build()
          )
          .build()
      )
      .build()
    val fileSpec = FileSpec.builder("com.mycompany", "Version")
      .addType(classSpec)
      .build()
    fileSpec.writeTo(outputDir)
  }
}

kotlin {
  sourceSets {
    main {
      kotlin.srcDir(generateVersion)
    }
  }
}

settings-plugin.settings.gradle.kts

import com.mycompany.Version

dependencyResolutionManagement {
  versionCatalogs {
    create("libs") {
      from("com.mycompany:catalog:${Version.VERSION}")
    }
  }
}

So reading files from resources was a bit beyond me here so decided to go with a code generation approach.

That works too of course, but reading a resource would have been way easier actually. :smiley:
Just have a properties file with version=$version in src/main/resources, then something like

tasks.processResources {
    filteringCharset = ISO_8859_1.name()
    filesMatching("path/to/your/version.properties") {
        expand("version" to version)
    }
}

And in the plugin

val version = javaClass
    .getResourceAsStream("/path/to/your/version.properties")
    .use { inStream ->
        Properties().apply {
            load(inStream)
        }
    }
    .getProperty("version")