Skip to content

Commit d43ac8f

Browse files
committed
chore: porting over graal and picocli configuration
1 parent 93d57d3 commit d43ac8f

11 files changed

+187
-26
lines changed

app/build.gradle

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
*/
66

77
plugins {
8-
id 'buildlogic.java-application-conventions'
8+
id 'buildlogic.picocli-conventions'
99
id 'buildlogic.java-special-tests-conventions'
10+
id 'buildlogic.java-graalvm-conventions'
1011
}
1112

1213
dependencies {
@@ -15,11 +16,37 @@ dependencies {
1516
testImplementation project(':testlib')
1617
implementation libs.bundles.spotless.libs
1718

18-
implementation libs.picocli
19-
annotationProcessor libs.picocli.codegen
19+
implementation libs.bundles.native.includes
2020
}
2121

2222
application {
23-
// Define the main class for the application.
24-
mainClass = 'org.example.app.App'
23+
mainClass = 'com.diffplug.spotless.cli.SpotlessCLI'
24+
applicationName = 'spotless'
25+
archivesBaseName = 'spotless-cli'
26+
}
27+
28+
gradle.taskGraph.whenReady { TaskExecutionGraph graph ->
29+
// println "Graph: " + graph.allTasks*.name
30+
if (graph.hasTask(':app:nativeCompile') || graph.hasTask(':app:metadataCopy') || graph.hasTask(':app:shadowJar')) {
31+
// enable graalvm agent using property here instead of command line `-Pagent=standard`
32+
// this collects information about reflective access and resources used by the application (e.g. GJF)
33+
project.ext.agent = 'standard'
34+
}
35+
}
36+
37+
tasks.withType(Test).configureEach {
38+
if (it.name == 'test' || it.name == 'testNpm') {
39+
it.outputs.dir(nativeCompileMetaDir)
40+
if (project.hasProperty('agent')) {
41+
it.inputs.property('agent', project.property('agent')) // make sure to re-run tests if agent changes
42+
}
43+
}
44+
if (it.name == 'testCliProcess' || it.name == 'testCliProcessNpm') {
45+
it.dependsOn('shadowJar')
46+
it.systemProperty 'spotless.cli.shadowJar', tasks.shadowJar.archiveFile.get().asFile
47+
}
48+
if (it.name == 'testCliNative' || it.name == 'testCliNativeNpm') {
49+
it.dependsOn('nativeCompile')
50+
it.systemProperty 'spotless.cli.nativeImage', tasks.nativeCompile.outputFile.get().asFile
51+
}
2552
}

build-logic/build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ repositories {
1616
mavenCentral()
1717
}
1818

19+
dependencies {
20+
implementation 'com.gradleup.shadow:shadow-gradle-plugin:8.3.6'
21+
}
22+
1923
spotless {
2024
encoding 'UTF-8'
2125

build-logic/settings.gradle

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
plugins {
88
// https://github.com/diffplug/spotless/blob/main/plugin-gradle/CHANGES.md
99
id 'com.diffplug.spotless' version '7.0.2' apply false
10-
}
1110

11+
// https://github.com/GradleUp/shadow/releases
12+
id 'com.gradleup.shadow' version '8.3.6' apply false
13+
}
1214

1315
dependencyResolutionManagement {
1416
// Reuse version catalog from the main build.

build-logic/src/main/groovy/buildlogic.changelog-conventions.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ plugins {
22
id 'com.diffplug.spotless-changelog'
33
}
44

5-
65
spotlessChangelog {
76
appendDashSnapshotUnless_dashPrelease=true
87
}
8+
9+
version = spotlessChangelog.versionNext
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
plugins {
2+
id 'com.gradleup.shadow'
3+
}

build-logic/src/main/groovy/buildlogic.java-common-conventions.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ testing {
3535
// Configure the built-in test suite
3636
test {
3737
// Use JUnit Jupiter test framework
38-
useJUnitJupiter('5.11.1')
38+
useJUnitJupiter(libs.versions.junit)
3939
}
4040
}
4141
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
plugins {
2+
id 'java'
3+
id 'org.graalvm.buildtools.native'
4+
id 'buildlogic.jar-shadow-conventions'
5+
}
6+
7+
8+
def nativeCompileMetaDir = project.layout.buildDirectory.dir('nativeCompile/src/main/resources/native-image/' + project.group + '/' + project.name)
9+
10+
// use tasks 'nativeCompile' and 'nativeRun' to compile and run the native image
11+
graalvmNative {
12+
agent {
13+
enabled = !project.hasProperty('skipGraalAgent') // we would love to make this dynamic, but it's not possible
14+
defaultMode = "standard"
15+
metadataCopy {
16+
inputTaskNames.add('test')
17+
inputTaskNames.add('testNpm')
18+
mergeWithExisting = false
19+
outputDirectories.add(nativeCompileMetaDir.get().asFile.path)
20+
}
21+
tasksToInstrumentPredicate = new java.util.function.Predicate<Task>() {
22+
@Override
23+
boolean test(Task task) {
24+
// if (project.hasProperty('agent')) {
25+
println ("Instrumenting task: " + task.name + " " + task.name == 'test' + "proj: " + task.project.hasProperty('agent'))
26+
return task.name == 'test' || task.name == 'testNpm'
27+
// }
28+
// return false
29+
}
30+
}
31+
}
32+
binaries {
33+
main {
34+
imageName = 'spotless'
35+
mainClass = 'com.diffplug.spotless.cli.SpotlessCLI'
36+
sharedLibrary = false
37+
useFatJar = true // use shadowJar as input to have same classpath
38+
39+
// optimizations, see https://www.graalvm.org/latest/reference-manual/native-image/optimizations-and-performance/
40+
//buildArgs.add('-O3') // on production builds
41+
42+
// the following options are required for GJF
43+
// see: <https://github.com/google/google-java-format/issues/894#issuecomment-1430408909>
44+
buildArgs.add('-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED')
45+
buildArgs.add('-J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED')
46+
buildArgs.add('-J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED')
47+
buildArgs.add('-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED')
48+
buildArgs.add('-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED')
49+
50+
buildArgs.add('--initialize-at-build-time=com.sun.tools.javac.file.Locations')
51+
52+
buildArgs.add('-H:IncludeResourceBundles=com.sun.tools.javac.resources.compiler')
53+
buildArgs.add('-H:IncludeResourceBundles=com.sun.tools.javac.resources.javac')
54+
}
55+
}
56+
}
57+
58+
tasks.named('metadataCopy') {
59+
dependsOn('test', 'testNpm')
60+
}
61+
62+
tasks.named('nativeCompile') {
63+
dependsOn('shadowJar')
64+
classpathJar = tasks.shadowJar.archiveFile.get().asFile
65+
}
66+
67+
tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
68+
dependsOn('metadataCopy') // produces graalvm agent info
69+
from(nativeCompileMetaDir.get().asFile.path) {
70+
into('META-INF/native-image/' + project.group + '/' + project.name)
71+
}
72+
}
Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,33 @@
11
plugins {
2-
id 'java'
3-
id 'com.adarshr.test-logger'
2+
id 'java'
3+
id 'com.adarshr.test-logger'
44
}
55

66
// See com.diffplug.spotless.tag package for available JUnit 5 @Tag annotations
77
def special = [
8-
'cliProcess',
9-
'cliProcessNpm',
10-
'cliNative',
11-
'cliNativeNpm'
8+
'npm',
9+
'cliProcess',
10+
'cliProcessNpm',
11+
'cliNative',
12+
'cliNativeNpm'
1213
]
1314

1415
tasks.named('test').configure {
15-
useJUnitPlatform {
16-
excludeTags special as String[]
17-
}
16+
useJUnitPlatform {
17+
excludeTags special as String[]
18+
}
1819
}
1920

2021
special.forEach { tag ->
21-
tasks.register("test${tag.capitalize()}", Test) {
22-
useJUnitPlatform { includeTags tag }
23-
}
22+
tasks.register("test${tag.capitalize()}", Test) {
23+
useJUnitPlatform { includeTags tag }
24+
}
2425
}
2526

2627
tasks.register('testAll') {
27-
dependsOn tasks.matching { it.name.startsWith('test') && it.name != 'testAll' }
28+
dependsOn tasks.matching { it.name.startsWith('test') && it.name != 'testAll' }
2829
}
2930

3031
tasks.withType(Test).configureEach {
31-
testLogging.showStandardStreams = true
32-
}
32+
testLogging.showStandardStreams = true
33+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
plugins {
2+
id 'buildlogic.java-application-conventions'
3+
}
4+
5+
dependencies {
6+
implementation libs.picocli
7+
annotationProcessor libs.picocli.codegen
8+
}
9+
10+
compileJava {
11+
// options for picocli codegen
12+
// https://github.com/remkop/picocli/tree/main/picocli-codegen#222-other-options
13+
options.compilerArgs += [
14+
"-Aproject=${project.group}/${project.name}",
15+
"-Aother.resource.bundles=application",
16+
// patterns require double-escaping (one escape is removed by groovy, the other one is needed in the resulting json file)
17+
"-Aother.resource.patterns=.*\\\\.properties,.*\\\\.json,.*\\\\.js"
18+
]
19+
}
20+
21+
tasks.withType(ProcessResources).configureEach(new ApplicationPropertiesProcessResourcesAction(project.version))
22+
23+
class ApplicationPropertiesProcessResourcesAction implements Action<ProcessResources> {
24+
25+
private final String cliVersion
26+
27+
ApplicationPropertiesProcessResourcesAction(String cliVersion) {
28+
this.cliVersion = cliVersion
29+
}
30+
31+
@Override
32+
void execute(ProcessResources processResources) {
33+
def localCliVersion = cliVersion // prevent issues with decorated closure
34+
processResources.filesMatching("application.properties") {
35+
filter(
36+
org.apache.tools.ant.filters.ReplaceTokens,
37+
tokens: [
38+
'cli.version': localCliVersion
39+
]
40+
)
41+
}
42+
}
43+
}

gradle/libs.versions.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ annotations = "26.0.2"
66
assertj-core = "3.27.3"
77
durian = "1.2.0"
88
junit = "5.8.1"
9+
native-include-googleJavaFormat = "1.24.0"
910
picocli = "4.7.6"
1011
spotless-lib = "3.0.2-SNAPSHOT"
1112

@@ -17,6 +18,7 @@ durian-io = { module = "com.diffplug.durian:durian-io", version.ref = "durian" }
1718
durian-collect = { module = "com.diffplug.durian:durian-collect", version.ref = "durian" }
1819
junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit" }
1920
junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit" }
21+
native-include-googleJavaFormat = { module = "com.google.googlejavaformat:google-java-format", version.ref = "native-include-googleJavaFormat" }
2022
picocli = { module = "info.picocli:picocli", version.ref = "picocli" }
2123
picocli-codegen = { module = "info.picocli:picocli-codegen", version.ref = "picocli" }
2224
spotless-lib = { module = "com.diffplug.spotless:spotless-lib", version.ref = "spotless-lib" }
@@ -25,3 +27,6 @@ spotless-lib-extra = { module = "com.diffplug.spotless:spotless-lib-extra", vers
2527
[bundles]
2628
spotless-libs = ["spotless-lib", "spotless-lib-extra"]
2729
durian-libs = ["durian-core", "durian-io", "durian-collect"]
30+
native-includes = [
31+
"native-include-googleJavaFormat"
32+
]

0 commit comments

Comments
 (0)