Skip to content

Commit 7593ded

Browse files
authored
Add native-image.properties files to jars (#4208)
This allows adding or removing entries from the set of classes that are initialized at native image build time without requiring changes to graalvm/native-build-tools. The new precompiled script plugin introduced in this commit defines two Gradle tasks: `nativeImageProperties` and `validateNativeImageProperties`. The former is used for writing the `native-image.properties` file to the correct resource folder based (by convention) on the `src/nativeImage/initialize-at-build-time` file in each affected subproject. The latter validates that all listed classes exist and acts as a safeguard when classes are renamed or deleted. Resolves #4207.
1 parent aa922c7 commit 7593ded

File tree

24 files changed

+187
-3
lines changed

24 files changed

+187
-3
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import junitbuild.graalvm.NativeImagePropertiesExtension
2+
import java.util.zip.ZipFile
3+
4+
plugins {
5+
`java-library`
6+
}
7+
8+
val extension = extensions.create<NativeImagePropertiesExtension>("nativeImageProperties").apply {
9+
val resourceFile: RegularFile = layout.projectDirectory.file("src/nativeImage/initialize-at-build-time")
10+
if (resourceFile.asFile.exists()) {
11+
initializeAtBuildTime.convention(providers.fileContents(resourceFile).asText.map { it.trim().lines() })
12+
} else {
13+
initializeAtBuildTime.empty()
14+
}
15+
initializeAtBuildTime.finalizeValueOnRead()
16+
}
17+
18+
val outputDir = layout.buildDirectory.dir("resources/nativeImage")
19+
20+
val propertyFileTask = tasks.register<WriteProperties>("nativeImageProperties") {
21+
destinationFile = outputDir.map { it.file("META-INF/native-image/${project.group}/${project.name}/native-image.properties") }
22+
// see https://www.graalvm.org/latest/reference-manual/native-image/overview/BuildConfiguration/#configuration-file-format
23+
property("Args", extension.initializeAtBuildTime.map {
24+
if (it.isEmpty()) {
25+
""
26+
} else {
27+
"--initialize-at-build-time=${it.joinToString(",")}"
28+
}
29+
})
30+
}
31+
32+
val validationTask = tasks.register("validateNativeImageProperties") {
33+
dependsOn(tasks.jar)
34+
doLast {
35+
val zipEntries = ZipFile(tasks.jar.get().archiveFile.get().asFile).use { zipFile ->
36+
zipFile.entries().asSequence().map { it.name }.filter { it.endsWith(".class") }.toSet()
37+
}
38+
val missingClasses = extension.initializeAtBuildTime.get().filter { className ->
39+
!zipEntries.contains("${className.replace('.', '/')}.class")
40+
}
41+
if (missingClasses.isNotEmpty()) {
42+
throw GradleException("The following classes were specified as initialize-at-build-time but do not exist (you should probably remove them from nativeImageProperties.initializeAtBuildTime):\n${missingClasses.joinToString("\n- ", "- ")}")
43+
}
44+
}
45+
}
46+
47+
tasks.check {
48+
dependsOn(validationTask)
49+
}
50+
51+
sourceSets {
52+
main {
53+
output.dir(propertyFileTask.map { outputDir })
54+
}
55+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package junitbuild.graalvm
2+
3+
import org.gradle.api.provider.SetProperty
4+
5+
abstract class NativeImagePropertiesExtension {
6+
abstract val initializeAtBuildTime: SetProperty<String>
7+
}

junit-jupiter-api/junit-jupiter-api.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
plugins {
22
id("junitbuild.kotlin-library-conventions")
33
id("junitbuild.code-generator")
4+
id("junitbuild.native-image-properties")
45
`java-test-fixtures`
56
}
67

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
org.junit.jupiter.api.DisplayNameGenerator$Standard
2+
org.junit.jupiter.api.TestInstance$Lifecycle
3+
org.junit.jupiter.api.condition.OS
4+
org.junit.jupiter.api.extension.ConditionEvaluationResult

junit-jupiter-engine/junit-jupiter-engine.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
plugins {
22
id("junitbuild.kotlin-library-conventions")
3+
id("junitbuild.native-image-properties")
34
`java-test-fixtures`
45
}
56

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
org.junit.jupiter.engine.JupiterTestEngine
2+
org.junit.jupiter.engine.config.CachingJupiterConfiguration
3+
org.junit.jupiter.engine.config.DefaultJupiterConfiguration
4+
org.junit.jupiter.engine.config.EnumConfigurationParameterConverter
5+
org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter
6+
org.junit.jupiter.engine.descriptor.ClassTestDescriptor
7+
org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor
8+
org.junit.jupiter.engine.descriptor.DynamicDescendantFilter
9+
org.junit.jupiter.engine.descriptor.ExclusiveResourceCollector$1
10+
org.junit.jupiter.engine.descriptor.JupiterEngineDescriptor
11+
org.junit.jupiter.engine.descriptor.JupiterTestDescriptor
12+
org.junit.jupiter.engine.descriptor.JupiterTestDescriptor$1
13+
org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor
14+
org.junit.jupiter.engine.descriptor.NestedClassTestDescriptor
15+
org.junit.jupiter.engine.descriptor.TestFactoryTestDescriptor
16+
org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor
17+
org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor
18+
org.junit.jupiter.engine.execution.ConditionEvaluator
19+
org.junit.jupiter.engine.execution.InterceptingExecutableInvoker
20+
org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall
21+
org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall$VoidMethodInterceptorCall
22+
org.junit.jupiter.engine.execution.InvocationInterceptorChain

junit-jupiter-params/junit-jupiter-params.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ plugins {
22
id("junitbuild.kotlin-library-conventions")
33
id("junitbuild.shadow-conventions")
44
id("junitbuild.jmh-conventions")
5+
id("junitbuild.native-image-properties")
56
}
67

78
description = "JUnit Jupiter Params"
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
org.junit.jupiter.params.provider.EnumSource$Mode
2+
org.junit.jupiter.params.provider.EnumSource$Mode$Validator

junit-platform-commons/junit-platform-commons.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import junitbuild.java.UpdateJarAction
33
plugins {
44
id("junitbuild.java-library-conventions")
55
id("junitbuild.java-multi-release-sources")
6+
id("junitbuild.native-image-properties")
67
`java-test-fixtures`
78
}
89

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
org.junit.platform.commons.util.StringUtils
2+
org.junit.platform.commons.logging.LoggerFactory$DelegatingLogger
3+
org.junit.platform.commons.logging.LoggerFactory
4+
org.junit.platform.commons.util.ReflectionUtils
5+
org.junit.platform.commons.util.LruCache

0 commit comments

Comments
 (0)