diff --git a/src/main/java/rife/bld/Project.java b/src/main/java/rife/bld/Project.java index 4d49a37..1a25289 100644 --- a/src/main/java/rife/bld/Project.java +++ b/src/main/java/rife/bld/Project.java @@ -25,6 +25,7 @@ public class Project extends BaseProject { private final JavadocOperation javadocOperation_ = new JavadocOperation(); private final PrecompileOperation precompileOperation_ = new PrecompileOperation(); + private final InstrumentOperation instrumentOperation_ = new InstrumentOperation(); private final JarOperation jarOperation_ = new JarOperation(); private final JarOperation jarSourcesOperation_ = new JarOperation(); private final JarOperation jarJavadocOperation_ = new JarOperation(); @@ -56,6 +57,16 @@ public class Project extends BaseProject { return precompileOperation_; } + /** + * Retrieves the project's default instrument operation. + * + * @return the default instrument operation instance + * @since 2.4 + */ + public InstrumentOperation instrumentOperation() { + return instrumentOperation_; + } + /** * Retrieves the project's default jar operation. * @@ -125,6 +136,19 @@ public class Project extends BaseProject { precompileOperation().executeOnce(() -> precompileOperation().fromProject(this)); } + /** + * Standard build command, instruments the compiled classes ahead of + * time, as an alternative to the java agent. + * + * @since 2.4 + */ + @BuildCommand(help = InstrumentHelp.class) + public void instrument() + throws Exception { + compile(); + instrumentOperation().executeOnce(() -> instrumentOperation().fromProject(this)); + } + /** * Standard build command, creates a jar archive for the project. * diff --git a/src/main/java/rife/bld/help/InstrumentHelp.java b/src/main/java/rife/bld/help/InstrumentHelp.java new file mode 100644 index 0000000..2d33400 --- /dev/null +++ b/src/main/java/rife/bld/help/InstrumentHelp.java @@ -0,0 +1,31 @@ +/* + * Copyright 2001-2026 Geert Bevin (gbevin[remove] at uwyn dot com) + * Licensed under the Apache License, Version 2.0 (the "License") + */ +package rife.bld.help; + +import rife.bld.CommandHelp; +import rife.tools.StringUtils; + +/** + * Provides help for the instrument command. + * + * @author Geert Bevin (gbevin[remove] at uwyn dot com) + * @since 2.4 + */ +public class InstrumentHelp implements CommandHelp { + public String getSummary() { + return "Instruments compiled classes ahead of time, as an alternative to the java agent"; + } + + public String getDescription(String topic) { + return StringUtils.replace(""" + Instruments the compiled classes ahead of time with RIFE2's bytecode + transformations, as an alternative to the java agent: web engine + continuations, workflow continuations, meta-data merging and + lazy-loading. This makes the agent unnecessary at run time and + enables these capabilities inside a GraalVM native image. + + Usage : ${topic}""", "${topic}", topic); + } +} diff --git a/src/main/java/rife/bld/operations/InstrumentOperation.java b/src/main/java/rife/bld/operations/InstrumentOperation.java new file mode 100644 index 0000000..fe4f249 --- /dev/null +++ b/src/main/java/rife/bld/operations/InstrumentOperation.java @@ -0,0 +1,140 @@ +/* + * Copyright 2001-2026 Geert Bevin (gbevin[remove] at uwyn dot com) + * Licensed under the Apache License, Version 2.0 (the "License") + */ +package rife.bld.operations; + +import rife.bld.BaseProject; +import rife.tools.FileUtils; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * Instruments compiled classes ahead of time with RIFE2's bytecode + * transformations, as an alternative to the java agent. + *
The instrumentation is performed by + * {@code rife.instrument.InstrumentationDeployer} from the RIFE2 + * dependency of the project that is being built, so the same + * transformations are applied as the ones the agent of that RIFE2 version + * performs at class loading time: web engine continuations, workflow + * continuations, meta-data merging and lazy-loading. Classes that don't + * use any of these capabilities are left untouched, and instrumenting + * already instrumented classes makes no changes. + *
Ahead-of-time instrumented classes make the agent unnecessary at run
+ * time and are the way to use these capabilities inside a GraalVM native
+ * image.
+ *
+ * @author Geert Bevin (gbevin[remove] at uwyn dot com)
+ * @since 2.4
+ */
+public class InstrumentOperation extends AbstractProcessOperation The project's main build directory is instrumented in place, with
+ * the runtime classpath providing the RIFE2 dependency that performs
+ * the instrumentation.
+ *
+ * @param project the project to configure the instrument operation from
+ * @since 2.4
+ */
+ public InstrumentOperation fromProject(BaseProject project) {
+ return classpath(project.runClasspath())
+ .sourceDirectories(project.buildMainDirectory())
+ .destinationDirectory(project.buildMainDirectory());
+ }
+
+ /**
+ * Provides source directories that will be instrumented.
+ *
+ * @param directories source directories
+ * @return this operation instance
+ * @since 2.4
+ */
+ public InstrumentOperation sourceDirectories(File... directories) {
+ sourceDirectories_.addAll(List.of(directories));
+ return this;
+ }
+
+ /**
+ * Provides a list of source directories that will be instrumented.
+ * A copy will be created to allow this list to be independently modifiable.
+ *
+ * @param directories a list of source directories
+ * @return this operation instance
+ * @since 2.4
+ */
+ public InstrumentOperation sourceDirectories(Collection This is a modifiable list that can be retrieved and changed.
+ *
+ * @return the instrumentation source directories
+ * @since 2.4
+ */
+ public List