New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor Maven Runner build config #2911
Merged
IgnatBeresnev
merged 8 commits into
Kotlin:master
from
aSemy:feat/refactor_maven_runner_build_config
Mar 16, 2023
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
4c8cfcd
initial refactor
aSemy d3c4c7c
tidying up, tests working
aSemy baefed3
rename Maven Plugin template POM
aSemy bf195e8
document Exec.environment Provider API workaround
aSemy c7617d6
move Maven versions to gradle.properties, and refactor to remove Cros…
aSemy f7db0d3
Merge branch 'master' into feat/refactor_maven_runner_build_config
aSemy 91f0314
Move `maven-cli` convention into `build-logic`
IgnatBeresnev 835c6e5
Suppress incubating API
IgnatBeresnev File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
103 changes: 103 additions & 0 deletions
103
build-logic/src/main/kotlin/org/jetbrains/conventions/maven-cli-setup.gradle.kts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
package org.jetbrains.conventions | ||
|
||
import org.gradle.kotlin.dsl.support.serviceOf | ||
|
||
/** | ||
* Utility for downloading and installing a Maven binary. | ||
* | ||
* Provides the `setupMavenProperties` extension that contains the default versions and locations | ||
* of the Maven binary. | ||
* | ||
* The task [installMavenBinary] will download and unzip the Maven bianry. | ||
*/ | ||
|
||
plugins { | ||
base | ||
} | ||
|
||
abstract class SetupMavenProperties { | ||
abstract val mavenVersion: Property<String> | ||
abstract val mavenPluginToolsVersion: Property<String> | ||
abstract val mavenBuildDir: DirectoryProperty | ||
|
||
/** Directory that will contain the unpacked Apache Maven dependency */ | ||
abstract val mavenInstallDir: DirectoryProperty | ||
|
||
/** | ||
* Path to the Maven executable. | ||
* | ||
* This should be different per OS: | ||
* | ||
* * Windows: `$mavenInstallDir/bin/mvn.cmd` | ||
* * Unix: `$mavenInstallDir/bin/mvn` | ||
*/ | ||
abstract val mvn: RegularFileProperty | ||
} | ||
|
||
val setupMavenProperties = | ||
extensions.create("setupMavenProperties", SetupMavenProperties::class).apply { | ||
mavenVersion.convention(providers.gradleProperty("mavenVersion")) | ||
mavenPluginToolsVersion.convention(providers.gradleProperty("mavenPluginToolsVersion")) | ||
|
||
mavenBuildDir.convention(layout.buildDirectory.dir("maven")) | ||
mavenInstallDir.convention(layout.buildDirectory.dir("apache-maven")) | ||
|
||
val isWindowsProvider = | ||
providers.systemProperty("os.name").map { "win" in it.toLowerCase() } | ||
|
||
mvn.convention( | ||
providers.zip(mavenInstallDir, isWindowsProvider) { mavenInstallDir, isWindows -> | ||
mavenInstallDir.file( | ||
when { | ||
isWindows -> "bin/mvn.cmd" | ||
else -> "bin/mvn" | ||
} | ||
) | ||
} | ||
) | ||
} | ||
|
||
val mavenBinary by configurations.registering { | ||
description = "used to download the Maven binary" | ||
isCanBeResolved = true | ||
isCanBeConsumed = false | ||
isVisible = false | ||
|
||
defaultDependencies { | ||
addLater(setupMavenProperties.mavenVersion.map { mavenVersion -> | ||
project.dependencies.create( | ||
group = "org.apache.maven", | ||
name = "apache-maven", | ||
version = mavenVersion, | ||
classifier = "bin", | ||
ext = "zip" | ||
) | ||
}) | ||
} | ||
} | ||
|
||
tasks.clean { | ||
delete(setupMavenProperties.mavenBuildDir) | ||
delete(setupMavenProperties.mavenInstallDir) | ||
} | ||
|
||
val installMavenBinary by tasks.registering(Sync::class) { | ||
val archives = serviceOf<ArchiveOperations>() | ||
from( | ||
mavenBinary.flatMap { conf -> | ||
@Suppress("UnstableApiUsage") | ||
val resolvedArtifacts = conf.incoming.artifacts.resolvedArtifacts | ||
|
||
resolvedArtifacts.map { artifacts -> | ||
artifacts.map { archives.zipTree(it.file) } | ||
} | ||
} | ||
) { | ||
eachFile { | ||
// drop the first directory inside the zipped Maven bin (apache-maven-$version) | ||
relativePath = RelativePath(true, *relativePath.segments.drop(1).toTypedArray()) | ||
} | ||
includeEmptyDirs = false | ||
} | ||
into(setupMavenProperties.mavenInstallDir) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,90 +1,105 @@ | ||
import org.jetbrains.CrossPlatformExec | ||
import org.jetbrains.SetupMaven | ||
import org.gradle.kotlin.dsl.support.appendReproducibleNewLine | ||
import org.jetbrains.registerDokkaArtifactPublication | ||
|
||
plugins { | ||
id("org.jetbrains.conventions.kotlin-jvm") | ||
id("org.jetbrains.conventions.maven-publish") | ||
id("org.jetbrains.conventions.maven-cli-setup") | ||
} | ||
|
||
val setupMaven by tasks.register<SetupMaven>("setupMaven") | ||
|
||
dependencies { | ||
implementation(project(":core")) | ||
implementation("org.apache.maven:maven-core:${setupMaven.mavenVersion}") | ||
implementation("org.apache.maven:maven-plugin-api:${setupMaven.mavenVersion}") | ||
implementation("org.apache.maven.plugin-tools:maven-plugin-annotations:${setupMaven.mavenPluginToolsVersion}") | ||
implementation("org.apache.maven:maven-core:${setupMavenProperties.mavenVersion.get()}") | ||
implementation("org.apache.maven:maven-plugin-api:${setupMavenProperties.mavenVersion.get()}") | ||
implementation("org.apache.maven.plugin-tools:maven-plugin-annotations:${setupMavenProperties.mavenPluginToolsVersion.get()}") | ||
implementation("org.apache.maven:maven-archiver:2.5") | ||
implementation(kotlin("stdlib-jdk8")) | ||
} | ||
|
||
val mavenBuildDir = setupMaven.mavenBuildDir | ||
val mavenBinDir = setupMaven.mavenBinDir | ||
|
||
tasks.clean { | ||
delete(mavenBuildDir) | ||
delete(mavenBinDir) | ||
} | ||
val mavenPluginTaskGroup = "maven plugin" | ||
|
||
val generatePom by tasks.registering(Copy::class) { | ||
val generatePom by tasks.registering(Sync::class) { | ||
description = "Generate pom.xml for Maven Plugin Plugin" | ||
group = mavenPluginTaskGroup | ||
|
||
val dokka_version: String by project | ||
inputs.property("dokka_version", dokka_version) | ||
|
||
from("$projectDir/pom.tpl.xml") { | ||
rename("(.*).tpl.xml", "$1.xml") | ||
} | ||
into(setupMaven.mavenBuildDir) | ||
|
||
eachFile { | ||
filter { line -> | ||
line.replace("<maven.version></maven.version>", "<maven.version>${setupMaven.mavenVersion}</maven.version>") | ||
} | ||
filter { line -> | ||
line.replace("<version>dokka_version</version>", "<version>$dokka_version</version>") | ||
} | ||
filter { line -> | ||
line.replace( | ||
"<version>maven-plugin-plugin</version>", | ||
"<version>${setupMaven.mavenPluginToolsVersion}</version>" | ||
) | ||
} | ||
val pomTemplateFile = layout.projectDirectory.file("pom.template.xml") | ||
|
||
val mavenVersion = setupMavenProperties.mavenVersion.get() | ||
val mavenPluginToolsVersion = setupMavenProperties.mavenPluginToolsVersion.get() | ||
|
||
from(pomTemplateFile) { | ||
rename { it.replace(".template.xml", ".xml") } | ||
|
||
expand( | ||
"mavenVersion" to mavenVersion, | ||
"dokka_version" to dokka_version, | ||
"mavenPluginToolsVersion" to mavenPluginToolsVersion, | ||
) | ||
} | ||
|
||
into(temporaryDir) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of worrying about Sync/Copy tasks overwriting, and having to use |
||
} | ||
|
||
val syncClasses by tasks.registering(Sync::class) { | ||
description = "Copy compiled classes to the Maven build dir, for Maven Plugin task execution" | ||
val prepareMavenPluginBuildDir by tasks.registering(Sync::class) { | ||
description = "Prepares all files for Maven Plugin task execution" | ||
group = mavenPluginTaskGroup | ||
|
||
from(tasks.compileKotlin.flatMap { it.destinationDirectory }) { into("classes/java/main") } | ||
from(tasks.compileJava.flatMap { it.destinationDirectory }) { into("classes/java/main") } | ||
|
||
dependsOn(tasks.compileKotlin, tasks.compileJava) | ||
from("$buildDir/classes/kotlin", "$buildDir/classes/java") | ||
into("${setupMaven.mavenBuildDir}/classes/java") | ||
from(generatePom) | ||
|
||
preserve { | ||
include("**/*.class") | ||
into(setupMavenProperties.mavenBuildDir) | ||
} | ||
|
||
val helpMojo by tasks.registering(Exec::class) { | ||
group = mavenPluginTaskGroup | ||
|
||
dependsOn(tasks.installMavenBinary, prepareMavenPluginBuildDir) | ||
|
||
workingDir(setupMavenProperties.mavenBuildDir) | ||
executable(setupMavenProperties.mvn.get()) | ||
args("-e", "-B", "org.apache.maven.plugins:maven-plugin-plugin:helpmojo") | ||
|
||
outputs.dir(setupMavenProperties.mavenBuildDir) | ||
|
||
doLast("normalize maven-plugin-help.properties") { | ||
// The maven-plugin-help.properties file contains a timestamp by default. | ||
// It should be removed as it is not reproducible and impacts Gradle caching | ||
val pluginHelpProperties = workingDir.resolve("maven-plugin-help.properties") | ||
pluginHelpProperties.writeText( | ||
buildString { | ||
val lines = pluginHelpProperties.readText().lines().iterator() | ||
// the first line is a descriptive comment | ||
appendReproducibleNewLine(lines.next()) | ||
// the second line is the timestamp, which should be ignored | ||
lines.next() | ||
// the remaining lines are properties | ||
lines.forEach { appendReproducibleNewLine(it) } | ||
} | ||
) | ||
} | ||
} | ||
|
||
val helpMojo by tasks.registering(CrossPlatformExec::class) { | ||
dependsOn(setupMaven, generatePom, syncClasses) | ||
workingDir(setupMaven.mavenBuildDir) | ||
commandLine(setupMaven.mvn, "-e", "-B", "org.apache.maven.plugins:maven-plugin-plugin:helpmojo") | ||
val pluginDescriptor by tasks.registering(Exec::class) { | ||
group = mavenPluginTaskGroup | ||
|
||
outputs.dir(layout.buildDirectory.dir("maven")) | ||
} | ||
dependsOn(tasks.installMavenBinary, prepareMavenPluginBuildDir) | ||
|
||
val pluginDescriptor by tasks.registering(CrossPlatformExec::class) { | ||
dependsOn(setupMaven, generatePom, syncClasses) | ||
workingDir(setupMaven.mavenBuildDir) | ||
commandLine(setupMaven.mvn, "-e", "-B", "org.apache.maven.plugins:maven-plugin-plugin:descriptor") | ||
workingDir(setupMavenProperties.mavenBuildDir) | ||
executable(setupMavenProperties.mvn.get()) | ||
args("-e", "-B", "org.apache.maven.plugins:maven-plugin-plugin:descriptor") | ||
|
||
outputs.dir(layout.buildDirectory.dir("maven/classes/java/main/META-INF/maven")) | ||
} | ||
|
||
tasks.jar { | ||
dependsOn(pluginDescriptor, helpMojo) | ||
metaInf { | ||
from("${setupMaven.mavenBuildDir}/classes/java/main/META-INF") | ||
from(setupMavenProperties.mavenBuildDir.map { it.dir("classes/java/main/META-INF") }) | ||
} | ||
manifest { | ||
attributes("Class-Path" to configurations.runtimeClasspath.map { configuration -> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of using a cross-project dependency to re-use the Maven exec, just download it again.
Gradle will cache the downloaded dependency, so it's fine to set it up twice in different subprojects.