Skip to content

Commit 1257d59

Browse files
author
Aleksandar Gradinac
committed
Agent doc refactor and support for additional options
1 parent 5b104dd commit 1257d59

File tree

8 files changed

+167
-60
lines changed

8 files changed

+167
-60
lines changed

common/utils/src/main/java/org/graalvm/buildtools/agent/AgentConfiguration.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,41 @@ public class AgentConfiguration implements Serializable {
4949

5050
private final Collection<String> callerFilterFiles;
5151
private final Collection<String> accessFilterFiles;
52+
private final boolean builtinCallerFilter;
53+
private final boolean builtinHeuristicFilter;
54+
private final boolean experimentalPredefinedClasses;
55+
private final boolean experimentalUnsafeAllocationTracing;
56+
private final boolean trackReflectionMetadata;
57+
5258
private final AgentMode agentMode;
5359

54-
public AgentConfiguration(Collection<String> callerFilterFiles, Collection<String> accessFilterFiles, AgentMode agentMode) {
60+
public AgentConfiguration(Collection<String> callerFilterFiles,
61+
Collection<String> accessFilterFiles,
62+
boolean builtinCallerFilter,
63+
boolean builtinHeuristicFilter,
64+
boolean experimentalPredefinedClasses,
65+
boolean experimentalUnsafeAllocationTracing,
66+
boolean trackReflectionMetadata,
67+
AgentMode agentMode) {
5568
this.callerFilterFiles = callerFilterFiles;
5669
this.accessFilterFiles = accessFilterFiles;
70+
this.builtinCallerFilter = builtinCallerFilter;
71+
this.builtinHeuristicFilter = builtinHeuristicFilter;
72+
this.experimentalPredefinedClasses = experimentalPredefinedClasses;
73+
this.experimentalUnsafeAllocationTracing = experimentalUnsafeAllocationTracing;
74+
this.trackReflectionMetadata = trackReflectionMetadata;
5775
this.agentMode = agentMode;
5876
}
5977

6078
public List<String> getAgentCommandLine() {
6179
List<String> cmdLine = new ArrayList<>(agentMode.getAgentCommandLine());
6280
appendOptionToValues("caller-filter-file=", callerFilterFiles, cmdLine);
6381
appendOptionToValues("access-filter-file=", accessFilterFiles, cmdLine);
82+
cmdLine.add("builtin-caller-filter=" + builtinCallerFilter);
83+
cmdLine.add("builtin-heuristic-filter=" + builtinHeuristicFilter);
84+
cmdLine.add("experimental-class-define-support=" + experimentalPredefinedClasses);
85+
cmdLine.add("experimental-unsafe-allocation-support=" + experimentalUnsafeAllocationTracing);
86+
cmdLine.add("track-reflection-metadata=" + trackReflectionMetadata);
6487
return cmdLine;
6588
}
6689

docs/src/docs/asciidoc/gradle-plugin.adoc

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -285,32 +285,41 @@ The same mechanism can be used if you have multiple test tasks for a single test
285285

286286
If your project requires reflection, classpath resources, dynamic proxies or other features requiring explicit native configuration, it may prove helpful to first run your application or tests using the https://www.graalvm.org/reference-manual/native-image/Agent/[`native-image-agent`].
287287

288-
The Native Image Gradle plugin simplifies generation of the required configuration files by injecting the agent automatically for you (this includes, but is not limited to the reflection file).
288+
The Native Image Gradle plugin simplifies generation of the required metadata files by injecting the agent automatically for you (this includes, but is not limited to the reflection file).
289289

290-
This should be as easy as appending `-Pagent` to the `run` and `nativeBuild`, or `test` and `nativeTest` task invocations:
290+
Any task that extends `JavaForkOptions` (like `test`, `run` etc) can be instrumented by passing `-Pagent` to gradle when running said tasks.
291+
292+
The agent can run in multiple modes that dictate how the metadata is collected and merged.
293+
294+
Once the metadata is collected, it can be copied into the project using the `metadataCopy` task.
291295

292296
[source,bash]
293297
----
294298
./gradlew -Pagent run # Runs on JVM with native-image-agent.
295-
./gradlew -Pagent nativeCompile # Builds image using configuration acquired by agent.
299+
./gradlew metadataCopy --task run --dir src/main/resources/META-INF/native-image # Copies the metadata collected by the agent into the project sources
300+
./gradlew nativeCompile # Builds image using metadata acquired by the agent.
296301
297302
# For testing
298-
./gradlew -Pagent test # Runs on JVM with native-image-agent.
299-
./gradlew -Pagent nativeTest # Builds image using configuration acquired by agent.
303+
./gradlew -Pagent nativeTest # Runs on JVM with the native-image agent, collects the metadata and uses it for testing on native-image.
300304
----
301305

302-
The agent can also be enabled by setting the corresponding DSL flag; however, that is not recommended since this is a development mode feature only.
306+
The agent can run in multiple modes:
307+
* Standard - Collects metadata without conditions. This is recommended if you are building an executable.
308+
* Conditional - Collects metadata with conditions. This is recommended if you are creating conditional metadata for a library intended for further use.
309+
* Direct - For advanced users only. This mode allows directly controlling the command line passed to the agent.
310+
311+
The default mode is specified in the DSL but can be changed by passing the mode name to Gradle when using the agent: `-Pagent=conditional`
303312

304313
The generated configuration files will be found in the `${buildDir}/native/agent-output/${taskName}` directory, for example, `build/native/agent-output/run`.
305-
Although those files will be automatically used if you run your build with the agent enabled, you should consider reviewing them and adding them to your sources instead.
314+
The plugin will also substitute `{output_dir}` in the agent options to point to this directory during the agent run.
306315

307316
[[agent-support-configuring-options]]
308317
=== Configuring agent options
309318

310319
The native agent can be configured https://www.graalvm.org/reference-manual/native-image/Agent/[with additional options].
311320
This can be done using the `agent` configuration block:
312321

313-
.Configuring agent options for every binary
322+
.Configuring agent options
314323
[source, groovy, role="multi-language-sample"]
315324
----
316325
include::../snippets/gradle/groovy/build.gradle[tags=add-agent-options]
@@ -321,20 +330,6 @@ include::../snippets/gradle/groovy/build.gradle[tags=add-agent-options]
321330
include::../snippets/gradle/kotlin/build.gradle.kts[tags=add-agent-options]
322331
----
323332

324-
You may also define distinct agent options for different images.
325-
In the following example, the agent used for instrumentation for the main image has distinct options from the test ones:
326-
327-
.Configuring agent options specifically
328-
[source, groovy, role="multi-language-sample"]
329-
----
330-
include::../snippets/gradle/groovy/build.gradle[tags=add-agent-options-individual]
331-
----
332-
333-
[source, kotlin, role="multi-language-sample"]
334-
----
335-
include::../snippets/gradle/kotlin/build.gradle.kts[tags=add-agent-options-individual]
336-
----
337-
338333
[[metadata-support]]
339334
== JVM Reachability Metadata support
340335

docs/src/docs/asciidoc/index.adoc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@ If you are interested in contributing, please refer to our https://github.com/gr
1414

1515
[[changelog]]
1616
== Changelog
17+
=== Release 0.9.12
18+
19+
==== Gradle plugin
20+
* Completely reworked agent support - **BREAKING CHANGE**
21+
* The agent block is no longer tied to the target binary.
22+
* The agent can now instrument any task that extends `JavaForkOptions`.
23+
* Introduced the `metadataCopy` task.
24+
* Introduced the concept of agent modes.
25+
** Under the hood, the agent mode dictates what options are passed to the agent and how metadata produced by multiple runs get merged.
26+
1727
=== Release 0.9.11
1828

1929
==== Maven plugin

docs/src/docs/snippets/gradle/groovy/build.gradle

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,49 @@ if (providers.environmentVariable("DISABLE_TOOLCHAIN").isPresent()) {
6767

6868
// tag::all-config-options[]
6969
graalvmNative {
70+
// Injects the native-image-agent into supported tasks if `-Pagent` is specified
71+
agent {
72+
defaultMode = "standard" // Default agent mode if one isn't specified using `-Pagent=mode_name`
73+
74+
modes {
75+
// The standard agent mode generates metadata without conditions.
76+
standard {
77+
}
78+
// The conditional agent mode generates metadata with conditions.
79+
conditional {
80+
userCodeFilterPath = "path-to-filter.json" // Path to a filter file that determines classes which will be used in the metadata conditions.
81+
extrFilterPath = "path-to-another-filter.json" // Optional, extra filter used to further filter the collected metadata.
82+
}
83+
// The direct agent mode allows users to directly pass options to the agent.
84+
direct {
85+
// {output_dir} is a special string expanded by the plugin to where the agent files would usually be output.
86+
options.add("config-output-dir={output_dir}")
87+
options.add("experimental-configuration-with-origins")
88+
}
89+
}
90+
91+
callerFilterFiles.from("filter.json")
92+
accessFilterFiles.from("filter.json")
93+
builtinCallerFilter = true
94+
builtinHeuristicFilter = true
95+
enableExperimentalPredefinedClasses = false
96+
enableExperimentalUnsafeAllocationTracing = false
97+
trackReflectionMetadata = true
98+
99+
// Copies metadata collected from tasks into the specified directories.
100+
metadataCopy {
101+
inputTaskNames.add("test") // Tasks previously executed with the agent attached.
102+
outputDirectories.add("src/main/resources/META-INF/native-image")
103+
mergeWithExisting = true // Instead of copying, merge with existing metadata in the output directories.
104+
}
105+
106+
/*
107+
By default, if `-Pagent` is specified, all tasks that extend JavaForkOptions are instrumented.
108+
This can be limited to only specific tasks that match this predicate.
109+
*/
110+
tasksToInstrumentPredicate = t -> true
111+
}
112+
70113
binaries {
71114
main {
72115
// Main options
@@ -87,11 +130,6 @@ graalvmNative {
87130
// Runtime options
88131
runtimeArgs.add('--help') // Passes '--help' to built image, during "nativeRun" task
89132

90-
// Development options
91-
agent {
92-
enabled = true // Enables the reflection agent. Can be also set on command line using '-Pagent'
93-
}
94-
95133
useFatJar = true // Instead of passing each jar individually, builds a fat jar
96134
}
97135
}

docs/src/docs/snippets/gradle/kotlin/build.gradle.kts

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,6 @@ graalvmNative {
8888
// Runtime options
8989
runtimeArgs.add("--help") // Passes '--help' to built image, during "nativeRun" task
9090

91-
// Development options
92-
agent {
93-
enabled.set(true) // Enables the reflection agent. Can be also set on command line using '-Pagent'
94-
}
95-
9691
useFatJar.set(true) // Instead of passing each jar individually, builds a fat jar
9792
}
9893
}
@@ -138,31 +133,12 @@ graalvmNative {
138133

139134
// tag::add-agent-options[]
140135
graalvmNative {
141-
binaries.configureEach {
142-
agent {
143-
options.add("experimental-class-loader-support")
144-
}
136+
agent {
137+
enableExperimentalPredefinedClasses = true
145138
}
146139
}
147140
// end::add-agent-options[]
148141

149-
// tag::add-agent-options-individual[]
150-
graalvmNative {
151-
binaries {
152-
named("main") {
153-
agent {
154-
options.add("experimental-class-loader-support")
155-
}
156-
}
157-
named("test") {
158-
agent {
159-
options.add("access-filter-file=${projectDir}/src/test/resources/access-filter.json")
160-
}
161-
}
162-
}
163-
}
164-
// end::add-agent-options-individual[]
165-
166142
// tag::enable-metadata-repository[]
167143
graalvmNative {
168144
metadataRepository {

native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/dsl/agent/AgentOptions.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,33 +54,85 @@
5454

5555
@SuppressWarnings({"unused"})
5656
public interface AgentOptions {
57+
/**
58+
* Contains configuration of supported agent modes.
59+
*/
5760
@Nested
5861
AgentModeOptions getModes();
5962

6063
default void modes(Action<? super AgentModeOptions> spec) {
6164
spec.execute(getModes());
6265
}
6366

67+
/**
68+
* The default agent mode name when the agent is in use.
69+
*/
6470
@Input
6571
@Optional
6672
Property<String> getDefaultMode();
6773

74+
/**
75+
* Caller-filter files that will be passed to the agent.
76+
*/
6877
@InputFiles
6978
@Optional
7079
ConfigurableFileCollection getCallerFilterFiles();
7180

81+
/**
82+
* Access-filter files that will be passed to the agent.
83+
*/
7284
@InputFiles
7385
@Optional
7486
ConfigurableFileCollection getAccessFilterFiles();
7587

88+
/**
89+
* Toggles the builtin agent caller filter.
90+
*/
91+
@Optional
92+
Property<Boolean> getBuiltinCallerFilter();
93+
94+
/**
95+
* Toggles the builtin agent heuristic filter.
96+
*/
97+
@Optional
98+
Property<Boolean> getBuiltinHeuristicFilter();
99+
100+
101+
/**
102+
* Toggles the experimental support for predefined classes.
103+
*/
104+
@Optional
105+
Property<Boolean> getEnableExperimentalPredefinedClasses();
106+
107+
108+
/**
109+
* Toggles the experimental support for unsafe allocation tracing.
110+
*/
111+
@Optional
112+
Property<Boolean> getEnableExperimentalUnsafeAllocationTracing();
113+
114+
115+
/**
116+
* Toggles the distinction between queried and used metadata.
117+
*/
118+
@Optional
119+
Property<Boolean> getTrackReflectionMetadata();
120+
121+
/**
122+
* Configuration of the metadata copy task.
123+
*/
76124
@Nested
77125
MetadataCopyOptions getMetadataCopy();
78126

79127
default void metadataCopy(Action<? super MetadataCopyOptions> spec) {
80128
spec.execute(getMetadataCopy());
81129
}
82130

131+
/**
132+
* Specifies prefixes that will be used to further filter files produced by the agent.
133+
*/
83134
@Input
135+
@Optional
84136
ListProperty<String> getFilterableEntries();
85137

86138
/**

native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/internal/DefaultGraalVmExtension.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,17 @@ public DefaultGraalVmExtension(NamedDomainObjectContainer<NativeImageOptions> na
7575
getToolchainDetection().convention(true);
7676
nativeImages.configureEach(options -> options.getJavaLauncher().convention(defaultJavaLauncher));
7777
getTestSupport().convention(true);
78-
getAgent().getTasksToInstrumentPredicate().convention(t -> true);
79-
getAgent().getDefaultMode().convention("standard");
80-
getAgent().getModes().getConditional().getParallel().convention(true);
81-
getAgent().getMetadataCopy().getMergeWithExisting().convention(false);
82-
getAgent().getFilterableEntries().convention(Arrays.asList("org.gradle.", "java.", "org.junit."));
78+
AgentOptions agentOpts = getAgent();
79+
agentOpts.getTasksToInstrumentPredicate().convention(t -> true);
80+
agentOpts.getDefaultMode().convention("standard");
81+
agentOpts.getModes().getConditional().getParallel().convention(true);
82+
agentOpts.getMetadataCopy().getMergeWithExisting().convention(false);
83+
agentOpts.getFilterableEntries().convention(Arrays.asList("org.gradle.", "java.", "org.junit."));
84+
agentOpts.getBuiltinHeuristicFilter().convention(true);
85+
agentOpts.getBuiltinCallerFilter().convention(true);
86+
agentOpts.getEnableExperimentalPredefinedClasses().convention(false);
87+
agentOpts.getEnableExperimentalUnsafeAllocationTracing().convention(true);
88+
agentOpts.getTrackReflectionMetadata().convention(true);
8389
configureToolchain();
8490
}
8591

native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/internal/agent/AgentConfigurationFactory.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,14 @@ public static Provider<AgentConfiguration> getAgentConfiguration(Provider<String
8787
default:
8888
throw new GradleException("Unknown agent mode selected: " + name);
8989
}
90-
return new AgentConfiguration(getFilePaths(callerFilterFiles), getFilePaths(accessFilterFiles), agentMode);
90+
return new AgentConfiguration(getFilePaths(callerFilterFiles),
91+
getFilePaths(accessFilterFiles),
92+
options.getBuiltinCallerFilter().get(),
93+
options.getBuiltinHeuristicFilter().get(),
94+
options.getEnableExperimentalPredefinedClasses().get(),
95+
options.getEnableExperimentalUnsafeAllocationTracing().get(),
96+
options.getTrackReflectionMetadata().get(),
97+
agentMode);
9198
});
9299
}
93100

0 commit comments

Comments
 (0)