diff --git a/build-logic/common-plugins/src/main/kotlin/GitHubPackages.kt b/build-logic/common-plugins/src/main/kotlin/GitHubPackages.kt index f3e78c4325..bb2e27b721 100644 --- a/build-logic/common-plugins/src/main/kotlin/GitHubPackages.kt +++ b/build-logic/common-plugins/src/main/kotlin/GitHubPackages.kt @@ -1,4 +1,4 @@ -import XdkProperties.Companion.REDACTED +import XdkPropertiesImpl.Companion.REDACTED import com.fasterxml.jackson.databind.JsonNode import io.github.rybalkinsd.kohttp.dsl.context.Method import io.github.rybalkinsd.kohttp.dsl.context.Method.DELETE diff --git a/build-logic/common-plugins/src/main/kotlin/XdkBuildLogic.kt b/build-logic/common-plugins/src/main/kotlin/XdkBuildLogic.kt index 64ead13392..897cb18d7a 100644 --- a/build-logic/common-plugins/src/main/kotlin/XdkBuildLogic.kt +++ b/build-logic/common-plugins/src/main/kotlin/XdkBuildLogic.kt @@ -1,16 +1,13 @@ import org.gradle.api.GradleException import org.gradle.api.Project import org.gradle.api.Task -import org.gradle.api.artifacts.Configuration -import org.gradle.api.attributes.Category.CATEGORY_ATTRIBUTE -import org.gradle.api.attributes.LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE import org.gradle.api.file.Directory +import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.ProjectLayout import org.gradle.api.invocation.Gradle import org.gradle.api.logging.LogLevel import org.gradle.api.logging.LogLevel.LIFECYCLE import org.gradle.api.provider.Provider -import org.gradle.kotlin.dsl.named import java.io.ByteArrayOutputStream import java.io.File import java.nio.file.Path @@ -27,13 +24,47 @@ abstract class XdkProjectBuildLogic(protected val project: Project) { } } -class XdkBuildLogic(project: Project) : XdkProjectBuildLogic(project) { +class XdkBuildLogic private constructor(project: Project) : XdkProjectBuildLogic(project) { + private val xdkGitHub: GitHubPackages by lazy { + GitHubPackages(project) + } + + private val xdkVersions: XdkVersionHandler by lazy { + XdkVersionHandler(project) + } + + private val xdkDistributions: XdkDistribution by lazy { + XdkDistribution(project) + } + + private val xdkProperties: XdkProperties by lazy { + logger.info("$prefix Created lazy XDK Properties for project ${project.name}") + XdkPropertiesImpl(project) + } + + fun props(): XdkProperties { + return xdkProperties + } + + fun versions(): XdkVersionHandler { + return xdkVersions + } + + fun distro(): XdkDistribution { + return xdkDistributions + } + + fun github(): GitHubPackages { + return xdkGitHub + } + + fun resolveLocalXdkInstallation(): File { + return findLocalXdkInstallation() ?: throw project.buildException("Could not find local installation of XVM.") + } + companion object { const val DEFAULT_JAVA_BYTECODE_VERSION = 20 const val XDK_TASK_GROUP_DEBUG = "debug" - - // Artifact names for configuration artifacts. Gradle uses these during the build to identify various - // non-default style artifacts, that we use as part of resolvable and consumable configurations. const val XDK_ARTIFACT_NAME_DISTRIBUTION_ARCHIVE = "xdk-distribution-archive" const val XDK_ARTIFACT_NAME_JAVATOOLS_FATJAR = "javatools-fatjar" const val XDK_ARTIFACT_NAME_MACK_DIR = "mack-dir" @@ -42,32 +73,22 @@ class XdkBuildLogic(project: Project) : XdkProjectBuildLogic(project) { private const val XTC_LAUNCHER = "xec" private const val DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS" - private val cache: MutableMap = mutableMapOf() - - fun resolve(project: Project): XdkBuildLogic { - // Companion objects are guaranteed to be singletons by Kotlin, so this cache works as build global cache. - return cache[project] ?: XdkBuildLogic(project).also { - cache[project] = it - val logger = project.logger - val size = cache.size - val uniqueSize = cache.values.distinct().size - logger.info("${it.prefix} XDK build logic initialized (instances: ${size})") - assert(size == uniqueSize) - } - } + private val singletonCache: MutableMap = mutableMapOf() - fun executeCommand(project: Project, vararg args: String): String = project.run { - val output = ByteArrayOutputStream() - val result = project.exec { - commandLine(*args) - standardOutput = output - isIgnoreExitValue = false + fun instanceFor(project: Project): XdkBuildLogic { + if (singletonCache.contains(project)) { + return singletonCache[project]!! } - if (result.exitValue != 0) { - logger.error("$prefix ERROR: Command '${args.joinToString(" ")}' failed with exit code ${result.exitValue}") - return "" - } - return output.toString().trim() + + val instance = XdkBuildLogic(project) + singletonCache[project] = instance + project.logger.info( + """ + ${project.prefix} Creating new XdkBuildLogic for project '${project.name}' + (singletonCache) ${System.identityHashCode(singletonCache)} + (project -> instance) ${System.identityHashCode(project)} -> ${System.identityHashCode(instance)} + """.trimIndent()) + return instance } fun getDateTimeStampWithTz(ms: Long = System.currentTimeMillis()): String { @@ -102,56 +123,6 @@ class XdkBuildLogic(project: Project) : XdkProjectBuildLogic(project) { }.trim() } } - - private val xdkProperties = XdkProperties(project) - - private val xdkGitHub: GitHubPackages by lazy { - GitHubPackages(project) - } - - private val xdkVersions: XdkVersionHandler by lazy { - XdkVersionHandler(project) - } - - private val xdkDistributions: XdkDistribution by lazy { - XdkDistribution(project) - } - - fun versions(): XdkVersionHandler { - return xdkVersions - } - - fun distro(): XdkDistribution { - return xdkDistributions - } - - fun github(): GitHubPackages { - return xdkGitHub - } - - fun resolveLocalXdkInstallation(): File { - return findLocalXdkInstallation() ?: throw project.buildException("Could not find local installation of XVM.") - } - - fun rebuildUnicode(): Boolean { - return xdkPropBool("org.xtclang.unicode.rebuild", false) - } - - internal fun xdkPropIsSet(key: String): Boolean { - return xdkProperties.has(key) - } - - internal fun xdkPropBool(key: String, defaultValue: Boolean? = null): Boolean { - return xdkProperties.get(key, defaultValue?.toString() ?: "false").toBoolean() - } - - internal fun xdkPropInt(key: String, defaultValue: Int? = null): Int { - return xdkProperties.get(key, defaultValue?.toString() ?: "0").toInt() - } - - internal fun xdkProp(key: String, defaultValue: String? = null): String { - return xdkProperties.get(key, defaultValue) - } } // TODO: Can we move these guys to the versions handler? @@ -164,57 +135,65 @@ val Gradle.rootGradle: Gradle return dir } -val Gradle.rootLayout: ProjectLayout - get() = rootGradle.rootProject.layout +val Gradle.rootLayout: ProjectLayout get() = rootGradle.rootProject.layout -val Project.compositeRootProjectDirectory - get() = gradle.rootLayout.projectDirectory +val Project.compositeRootProjectDirectory: Directory get() = gradle.rootLayout.projectDirectory -val Project.compositeRootBuildDirectory - get() = gradle.rootLayout.buildDirectory +val Project.compositeRootBuildDirectory: DirectoryProperty get() = gradle.rootLayout.buildDirectory -val Project.userInitScriptDirectory - get() = File(gradle.gradleUserHomeDir, "init.d") +val Project.userInitScriptDirectory: File get() = File(gradle.gradleUserHomeDir, "init.d") -val Project.buildRepoDirectory: Provider - get() = compositeRootBuildDirectory.dir("repo") +val Project.buildRepoDirectory get() = compositeRootBuildDirectory.dir("repo") -val Project.xdkBuild: XdkBuildLogic - get() = XdkBuildLogic.resolve(this) +val Project.xdkBuildLogicProvider: Provider get() = provider { + XdkBuildLogic.instanceFor(this) +} -val Project.prefix - get() = "[$name]" +val Project.xdkBuildLogic: XdkBuildLogic get() = xdkBuildLogicProvider.get() -val Task.prefix - get() = "[${project.name}:$name]" +val Project.prefix: String get() = "[$name]" + +val Task.prefix: String get() = "[${project.name}:$name]" // TODO: A little bit hacky: use a config, but there is a mutual dependency between the lib_xtc and javatools. // Better to add the resource directory as a source set? -val Project.xdkIconFile: String - get() = "$compositeRootProjectDirectory/javatools_launcher/src/main/c/x.ico" +val Project.xdkIconFile: String get() = "$compositeRootProjectDirectory/javatools_launcher/src/main/c/x.ico" -// TODO: A little bit hacky, for same reason as above. -// Better to add the resource directory as a source set? -val Project.xdkImplicitsPath: String - get() = "$compositeRootProjectDirectory/lib_ecstasy/src/main/resources/implicit.x" +// TODO: A little bit hacky, for same reason as above; Better to add the resource directory as a source set? +val Project.xdkImplicitsPath: String get() = "$compositeRootProjectDirectory/lib_ecstasy/src/main/resources/implicit.x" + +val Project.xdkImplicitsFile: File get() = File(xdkImplicitsPath) + +fun Project.executeCommand(vararg args: String): String = project.run { + val output = ByteArrayOutputStream() + val result = project.exec { + commandLine(*args) + standardOutput = output + isIgnoreExitValue = false + } + if (result.exitValue != 0) { + logger.error("$prefix ERROR: Command '${args.joinToString(" ")}' failed with exit code ${result.exitValue}") + return "" + } + return output.toString().trim() +} -val Project.xdkImplicitsFile: File - get() = File(xdkImplicitsPath) +// TODO these should probably be lazy for input purposes fun Project.isXdkPropertySet(key: String): Boolean { - return xdkBuild.xdkPropIsSet(key) + return xdkBuildLogic.props().has(key) } fun Project.getXdkPropertyBoolean(key: String, defaultValue: Boolean? = null): Boolean { - return xdkBuild.xdkPropBool(key, defaultValue) + return xdkBuildLogic.props().get(key, defaultValue) } fun Project.getXdkPropertyInt(key: String, defaultValue: Int? = null): Int { - return xdkBuild.xdkPropInt(key, defaultValue) + return xdkBuildLogic.props().get(key, defaultValue) } fun Project.getXdkProperty(key: String, defaultValue: String? = null): String { - return xdkBuild.xdkProp(key, defaultValue) + return xdkBuildLogic.props().get(key, defaultValue) } fun Task.getXdkPropertyBoolean(key: String, defaultValue: Boolean? = null): Boolean { diff --git a/build-logic/common-plugins/src/main/kotlin/XdkDistribution.kt b/build-logic/common-plugins/src/main/kotlin/XdkDistribution.kt index 812d439681..0a366bb6d2 100644 --- a/build-logic/common-plugins/src/main/kotlin/XdkDistribution.kt +++ b/build-logic/common-plugins/src/main/kotlin/XdkDistribution.kt @@ -37,7 +37,7 @@ class XdkDistribution(project: Project): XdkProjectBuildLogic(project) { append(project.version) if (CI_ENABLED) { val buildNumber = System.getenv(BUILD_NUMBER) ?: "" - val gitCommitHash = XdkBuildLogic.executeCommand(project, "git", "rev-parse", "HEAD") + val gitCommitHash = project.executeCommand("git", "rev-parse", "HEAD") if (buildNumber.isNotEmpty() || gitCommitHash.isNotEmpty()) { logger.warn("This is a CI run, BUILD_NUMBER and git hash must both be available: (BUILD_NUMBER='$buildNumber', commit='$gitCommitHash')") return@buildString @@ -51,10 +51,6 @@ class XdkDistribution(project: Project): XdkProjectBuildLogic(project) { return project.layout.buildDirectory.dir(path) } - fun shouldPublishPluginToLocalDist(): Boolean { - return project.getXdkPropertyBoolean("org.xtclang.publish.localDist", false) - } - fun shouldCreateWindowsDistribution(): Boolean { val runDistExe = project.getXdkPropertyBoolean("org.xtclang.install.distExe", false) if (runDistExe) { diff --git a/build-logic/common-plugins/src/main/kotlin/XdkProperties.kt b/build-logic/common-plugins/src/main/kotlin/XdkProperties.kt index 3e48b7dfd1..344ca3b468 100644 --- a/build-logic/common-plugins/src/main/kotlin/XdkProperties.kt +++ b/build-logic/common-plugins/src/main/kotlin/XdkProperties.kt @@ -20,10 +20,16 @@ import java.util.Properties * The property helper tries to ensure that no standard or inherited task that derives from, ore * uses "./gradlew properties" will inadvertently dump secrets to the console. */ -class XdkProperties(project: Project): XdkProjectBuildLogic(project) { +interface XdkProperties { + fun get(key: String, defaultValue: String? = null): String + fun get(key: String, defaultValue: Int? = 0): Int + fun get(key: String, defaultValue: Boolean? = false): Boolean + fun has(key: String): Boolean +} + +class XdkPropertiesImpl(project: Project): XdkProjectBuildLogic(project), XdkProperties { companion object { const val REDACTED = "[REDACTED]" - private const val PROPERTIES_EXT = "properties" /** @@ -63,7 +69,7 @@ class XdkProperties(project: Project): XdkProjectBuildLogic(project) { * in a build run, that isn't declared in a property file. Examples could be testing out * a new GitHub token, or adding an environment variable that the plugin needs at start * time (for example, because the project logger outputs aren't inherited by default in - * a plugin, even if it has access to the actual project.logger instance), for the + * a plugin, even if it has access to the actual project logger instance), for the * project to which the plugin is applied. * * If the method fails to find the value of a property, both in its resolved property @@ -71,7 +77,18 @@ class XdkProperties(project: Project): XdkProjectBuildLogic(project) { * parameter. If no default value was supplied, an exception will be thrown, and the * build breaks. */ - fun get(key: String, defaultValue: String? = null): String { + override fun get(key: String, defaultValue: String?): String { + logger.lifecycle("$prefix get($key) invoked (props: ${System.identityHashCode(this)})") + if (!key.startsWith("org.xtclang")) { + // TODO: Remove this artificial limitation. + throw project.buildException("ERROR: XdkProperties are currently expected to start with org.xtclang. Remove this artificial limitation.") + } + if (!has(key)) { + return defaultValue?.also { + logger.info("$prefix XdkProperties; resolved property '$key' to its default value.") + } ?: throw project.buildException("ERROR: XdkProperty '$key' has no value, and no default was given.") + } + // First check a system env override val envKey = toSystemEnvKey(key) val envValue = System.getenv(envKey) @@ -86,18 +103,20 @@ class XdkProperties(project: Project): XdkProjectBuildLogic(project) { return sysPropValue.toString() } - // Finally, look up in table or fallback to default value. - val value = properties[key] ?: System.getenv(toSystemEnvKey(key)) ?: defaultValue - if (value == null && defaultValue == null) { - throw project.buildException("ERROR: XdkProperty '$key' has no value, and no default was given.") - } - logger.info("$prefix XdkProperties; resolved property '$key' from properties table (defaultValue: '$defaultValue')") - return value.toString() + return properties[key]!!.toString() + } + + override fun get(key: String, defaultValue: Int?): Int { + return get(key, defaultValue?.toString()).toInt() + } + + override fun get(key: String, defaultValue: Boolean?): Boolean { + return get(key, defaultValue.toString()).toBoolean() } - fun has(key: String): Boolean { - return properties[key] != null + override fun has(key: String): Boolean { + return properties[key] != null || System.getenv(toSystemEnvKey(key)) != null || System.getProperty(key) != null } override fun toString(): String { diff --git a/build-logic/common-plugins/src/main/kotlin/org.xtclang.build.publish.gradle.kts b/build-logic/common-plugins/src/main/kotlin/org.xtclang.build.publish.gradle.kts index a1e39a18f5..4ae2d226d5 100644 --- a/build-logic/common-plugins/src/main/kotlin/org.xtclang.build.publish.gradle.kts +++ b/build-logic/common-plugins/src/main/kotlin/org.xtclang.build.publish.gradle.kts @@ -5,9 +5,12 @@ plugins { id("maven-publish") // TODO: Adding the maven publish plugin here, will always bring with it the PluginMaven publication. We don't always want to use that e.g. for the plugin build. Either reuse the publication there, or find a better way to add the default maven publication. } -private val xtcGitHubClient = xdkBuild.github() -private val publishLocalDist = xdkBuild.distro().shouldPublishPluginToLocalDist() -private val localPublishTasks = provider { tasks.withType().filter{ it.name.contains("Local") }.toList() } +/* + * Should we publish the plugin to a common build repository and copy it to any localDist? + */ +private fun shouldPublishPluginToLocalDist(): Boolean { + return project.getXdkPropertyBoolean("org.xtclang.publish.localDist", false) +} /** * Configure repositories for XDK artifact publication. Currently, we publish the XDK zip "xdkArchive", and @@ -18,7 +21,7 @@ publishing { logger.info("$prefix Configuring publications for repository mavenLocal().") mavenLocal() - if (publishLocalDist) { + if (shouldPublishPluginToLocalDist()) { logger.info("$prefix Configuring publications for repository local flat dir: '$buildRepoDirectory'") maven { name = "build" @@ -28,7 +31,7 @@ publishing { } logger.info("$prefix Configuring publications for xtclang.org GitHub repository.") - with (xtcGitHubClient) { + with (xdkBuildLogicProvider.get().github()) { if (verifyGitHubConfig()) { logger.info("$prefix Found GitHub package credentials for XTC (url: $uri, user: $user, org: $organization, read-only: $isReadOnly)") maven { @@ -76,19 +79,17 @@ val publishLocal by tasks.registering { val pruneBuildRepo by tasks.registering { group = PUBLISH_TASK_GROUP description = "Helper task called internally to make sure the build repo is wiped out before republishing. Used by installLocalDist and remote publishing only." - if (publishLocalDist) { + if (shouldPublishPluginToLocalDist()) { logger.lifecycle("$prefix Installing copy of the plugin to local distribution when it exists.") delete(buildRepoDirectory) } } -if (publishLocalDist) { +if (shouldPublishPluginToLocalDist()) { logger.warn("$prefix Configuring local distribution plugin publication.") val publishAllPublicationsToBuildRepository by tasks.existing { - if (publishLocalDist) { - dependsOn(pruneBuildRepo) - mustRunAfter(pruneBuildRepo) - } + dependsOn(pruneBuildRepo) + mustRunAfter(pruneBuildRepo) } publishLocal { dependsOn(publishAllPublicationsToBuildRepository) @@ -108,7 +109,8 @@ val listAllLocalPublications by tasks.registering { description = "Task that lists local Maven publications for this project from the mavenLocal() repository." doLast { logger.lifecycle("$prefix '$name' Listing local publications (and their artifacts) for project '${project.group}:${project.name}':") - localPublishTasks.get().forEach { + //private val localPublishTasks = provider { tasks.withType().filter{ it.name.contains("Local") }.toList() } + tasks.withType().filter { it.name.contains("Local") }.forEach { with(it.publication) { logger.lifecycle("$prefix '${it.name}' (${artifacts.count()} artifacts):") val baseUrl = "${it.repository.url}${groupId.replace('.', '/')}/$artifactId/$version/$artifactId" @@ -132,15 +134,16 @@ val listAllRemotePublications by tasks.registering { group = PUBLISH_TASK_GROUP description = "Task that lists publications for this project on the 'xtclang' org GitHub package repo." doLast { + val github = xdkBuildLogicProvider.get().github() logger.lifecycle("$prefix '$name' Listing remote publications for project '${project.group}:${project.name}':") - val packageNames = xtcGitHubClient.queryXtcLangPackageNames() + val packageNames = github.queryXtcLangPackageNames() if (packageNames.isEmpty()) { logger.lifecycle("$prefix No Maven packages found.") return@doLast } packageNames.forEach { pkg -> logger.lifecycle("$prefix Maven package: '$pkg':") - val versions = xtcGitHubClient.queryXtcLangPackageVersions(pkg) + val versions = github.queryXtcLangPackageVersions(pkg) if (versions.isEmpty()) { logger.warn("$prefix WARNING: No versions found for this package. Corrupted package repo?") return@forEach @@ -154,7 +157,8 @@ val deleteAllRemotePublications by tasks.registering { group = PUBLISH_TASK_GROUP description = "Delete all versions of all packages on the 'xtclang' org GitHub package repo. WARNING: ALL VERSIONS ARE PURGED." doLast { - xtcGitHubClient.deleteXtcLangPackages() // TODO: Add a pattern that can be set thorugh a property to get finer granularity here than "kill everything!". + val github = xdkBuildLogicProvider.get().github() + github.deleteXtcLangPackages() // TODO: Add a pattern that can be set thorugh a property to get finer granularity here than "kill everything!". logger.lifecycle("$prefix Finished '$name' deleting publications for project: '${project.group}:${project.name}'.") } } diff --git a/build-logic/common-plugins/src/main/kotlin/org.xtclang.build.xdk.versioning.gradle.kts b/build-logic/common-plugins/src/main/kotlin/org.xtclang.build.xdk.versioning.gradle.kts index 8c19018edc..c8c24b5756 100644 --- a/build-logic/common-plugins/src/main/kotlin/org.xtclang.build.xdk.versioning.gradle.kts +++ b/build-logic/common-plugins/src/main/kotlin/org.xtclang.build.xdk.versioning.gradle.kts @@ -11,5 +11,5 @@ plugins { } val semanticVersion by extra { - xdkBuild.versions().assignSemanticVersionFromCatalog() + xdkBuildLogic.versions().assignSemanticVersionFromCatalog() } diff --git a/javatools_unicode/build.gradle.kts b/javatools_unicode/build.gradle.kts index 971e5d5caf..7d54e8fa63 100644 --- a/javatools_unicode/build.gradle.kts +++ b/javatools_unicode/build.gradle.kts @@ -33,7 +33,9 @@ val jar by tasks.existing(Jar::class) */ val downloadUcdFlatZip by tasks.registering(Download::class) { onlyIf { - xdkBuild.rebuildUnicode() + System.err.println("Check rebuildunicode spec: should be executing: ${state.executing}") + assert(state.executing) + getXdkPropertyBoolean("org.xtclang.unicode.rebuild", false) // TODO inputproperty } src(unicodeUcdUrl) overwrite(false) @@ -63,7 +65,7 @@ val rebuildUnicodeTables by tasks.registering { group = BUILD_GROUP description = "If the unicode files should be regenerated, generate them from the build tool, and place them under the build resources." - val rebuildUnicode = xdkBuild.rebuildUnicode() + val rebuildUnicode = getXdkPropertyBoolean("org.xtclang.unicode.rebuild", false) logger.info("$prefix Should rebuild unicode: $rebuildUnicode") dependsOn(jar) diff --git a/lib_ecstasy/build.gradle.kts b/lib_ecstasy/build.gradle.kts index da9a98f16d..dfc4130251 100644 --- a/lib_ecstasy/build.gradle.kts +++ b/lib_ecstasy/build.gradle.kts @@ -47,23 +47,21 @@ sourceSets { // mack.x is in a different project, and does not build on its own, hence we add it to the lib_ecstasy source set instead. srcDir(xdkTurtle) } - resources { + //resources { // Skip the local unicode files if we are in "rebuild unicode" mode. - if (xdkBuild.rebuildUnicode()) { - exclude("**/ecstasy/text**") - } - } + //if (xdkBuild.rebuildUnicode()) { + // exclude("**/ecstasy/text**") + //} + //} } } // We need extra resources. val processResources by tasks.existing(ProcessResources::class) { - val rebuildUnicode = xdkBuild.rebuildUnicode() - -// We can't use onlyIf here, since we need processResources to copy the src/main/resources files to the build, from where -// they are picked up by the compileXtc tasks. CompileXtc respects Gradle semantics and allows for a processResources -// (default is a plain lifecycle intra-project copy) to modify the resources, if needed. - if (rebuildUnicode) { + // We can't use onlyIf here, since we need processResources to copy the src/main/resources files to the build, from where + // they are picked up by the compileXtc tasks. CompileXtc respects Gradle semantics and allows for a processResources + // (default is a plain lifecycle intra-project copy) to modify the resources, if needed. + if (getXdkPropertyBoolean("org.xtclang.unicode.rebuild", false)) { val javaToolsUnicode = gradle.includedBuild("javatools_unicode") val rebuildUnicodeOutput = File( javaToolsUnicode.projectDir, diff --git a/xdk/build.gradle.kts b/xdk/build.gradle.kts index cd466b64c2..f65c9e08a2 100644 --- a/xdk/build.gradle.kts +++ b/xdk/build.gradle.kts @@ -75,7 +75,7 @@ dependencies { private val semanticVersion: SemanticVersion by extra logger.lifecycle("$prefix *** Building XDK; semantic version: '$semanticVersion' ***") -private val xdkDist = xdkBuild.distro() +private val xdkDist = xdkBuildLogicProvider.get().distro() /** * Propagate the "version" part of the semanticVersion to all XTC compilers in all subprojects (the XDK modules @@ -165,10 +165,14 @@ val installInitScripts by tasks.registering(Copy::class) { } } +private fun shouldPublishPluginToLocalDist(): Boolean { + return project.getXdkPropertyBoolean("org.xtclang.publish.localDist", false) +} + val publishPluginToLocalDist by tasks.registering { group = BUILD_GROUP // TODO: includeBuild dependency; Slightly hacky - use a configuration from the plugin project instead. - if (xdkDist.shouldPublishPluginToLocalDist()) { + if (shouldPublishPluginToLocalDist()) { dependsOn(gradle.includedBuild("plugin").task(":publishAllPublicationsToBuildRepository")) outputs.dir(buildRepoDirectory) doLast { @@ -188,8 +192,9 @@ distributions { assert(distributionBaseName.get() == "xdk") // TODO: Should really rename the distribution to "xdk" explicitly per convention. contents { // TODO: Why do we need the indirect - likely change these to lazy properties through map format. + // TODO WE should really not do get() here. val resources = tasks.processResources.get().outputs.files.asFileTree - + logger.warn("$prefix Distribution contents need to use lazy resources.") /* * 1) copy build plugin repository publication of the XTC plugin to install/xdk/repo * 2) copy xdk resources/main/xdk to install/xdk/libexec @@ -225,7 +230,7 @@ distributions { } into("libexec/javatools") // should just be one file with corrected dependencies, assert? } - if (xdkDist.shouldPublishPluginToLocalDist()) { + if (shouldPublishPluginToLocalDist()) { val published = publishPluginToLocalDist.get().outputs.files from(published) { into("repo") @@ -236,22 +241,20 @@ distributions { } } -val clean by tasks.existing { - doFirst { - logger.warn("$prefix Task '$name' is often unnecessary. Are you sure you don't just need to call './gradlew build' again?") +val cleanXdk by tasks.registering(Delete::class) { + subprojects.forEach { + delete(it.layout.buildDirectory) } + delete(compositeRootBuildDirectory) doLast { - subprojects.forEach { - // Hack to handle subprojects clean, not includedBuilds, where dependencies are auto-resolved by the aggregator. - val subProjectBuildDir = it.layout.buildDirectory.get().asFile - delete(it.layout.buildDirectory) - logger.info("$prefix Task '$name' cleaned subproject ${it.name} build directory (buildDir: '$subProjectBuildDir')") - } - delete(compositeRootBuildDirectory) - logger.info("$prefix Task '$name' cleaned composite build common build directory: ${compositeRootBuildDirectory.get()}") + logger.warn("$prefix Task '$name' is often unnecessary. Are you sure you don't just need to call './gradlew build' again?") } } +val clean by tasks.existing { + dependsOn(cleanXdk) +} + val distTar by tasks.existing(Tar::class) { compression = Compression.GZIP archiveExtension = "tar.gz" @@ -365,9 +368,12 @@ val findLocalDist by tasks.registering { val backupLocalDist by tasks.registering(Copy::class) { group = DISTRIBUTION_TASK_GROUP description = "Backs up a local installation to build dir before starting to overwrite." - val localDist = xdkBuild.resolveLocalXdkInstallation() + // This is file, so it can be resolved at the top level. + val localDist = xdkBuildLogicProvider.get().resolveLocalXdkInstallation() val dest = xdkDist.getLocalDistBackupDir(localDist.name) - from(localDist).into(dest) + from(localDist) { + into(dest) + } doLast { logger.lifecycle("$prefix Backed up local installation at $localDist to ${dest.get()}") } @@ -421,7 +427,7 @@ val installLocalDist by tasks.registering { mustRunAfter(purgeLocalDist) doLast { - val localDistDir = xdkBuild.resolveLocalXdkInstallation() // throws exception if file not found. + val localDistDir = xdkBuildLogicProvider.get().resolveLocalXdkInstallation() // throws exception if file not found. val localDistVersion = localDistDir.name logger.lifecycle("$prefix '$name' Overwriting local installation: $localDistVersion (path: '${localDistDir.absolutePath}')...") copy {