mirror of
https://github.com/rife2/bld
synced 2026-07-25 00:47:47 +02:00
Add an instrument operation for ahead-of-time RIFE2 instrumentation
Some checks are pending
bld-ci / build (./bld, 17, macos-latest, false) (push) Waiting to run
bld-ci / build (./bld, 21, macos-latest, false) (push) Waiting to run
bld-ci / build (./bld, 25, macos-latest, false) (push) Waiting to run
bld-ci / build (./bld, 26, macos-latest, false) (push) Waiting to run
bld-ci / build (.\bld.bat, 17, windows-latest, false) (push) Waiting to run
bld-ci / build (.\bld.bat, 21, windows-latest, false) (push) Waiting to run
bld-ci / build (.\bld.bat, 25, windows-latest, false) (push) Waiting to run
bld-ci / build (.\bld.bat, 26, windows-latest, false) (push) Waiting to run
bld-ci / build (unittests, password, unittests, mariadb:10.9, mysql:8, gvenzl/oracle-free:latest, gvenzl/oracle-xe:18-slim, postgres:15, ./bld, 17, ubuntu-latest, true) (push) Waiting to run
bld-ci / build (unittests, password, unittests, mariadb:10.9, mysql:8, gvenzl/oracle-free:latest, gvenzl/oracle-xe:18-slim, postgres:15, ./bld, 21, ubuntu-latest, true) (push) Waiting to run
bld-ci / build (unittests, password, unittests, mariadb:10.9, mysql:8, gvenzl/oracle-free:latest, gvenzl/oracle-xe:18-slim, postgres:15, ./bld, 25, ubuntu-latest, true) (push) Waiting to run
bld-ci / build (unittests, password, unittests, mariadb:10.9, mysql:8, gvenzl/oracle-free:latest, gvenzl/oracle-xe:18-slim, postgres:15, ./bld, 26, ubuntu-latest, true) (push) Waiting to run
javadocs-pages / deploy (push) Waiting to run
Some checks are pending
bld-ci / build (./bld, 17, macos-latest, false) (push) Waiting to run
bld-ci / build (./bld, 21, macos-latest, false) (push) Waiting to run
bld-ci / build (./bld, 25, macos-latest, false) (push) Waiting to run
bld-ci / build (./bld, 26, macos-latest, false) (push) Waiting to run
bld-ci / build (.\bld.bat, 17, windows-latest, false) (push) Waiting to run
bld-ci / build (.\bld.bat, 21, windows-latest, false) (push) Waiting to run
bld-ci / build (.\bld.bat, 25, windows-latest, false) (push) Waiting to run
bld-ci / build (.\bld.bat, 26, windows-latest, false) (push) Waiting to run
bld-ci / build (unittests, password, unittests, mariadb:10.9, mysql:8, gvenzl/oracle-free:latest, gvenzl/oracle-xe:18-slim, postgres:15, ./bld, 17, ubuntu-latest, true) (push) Waiting to run
bld-ci / build (unittests, password, unittests, mariadb:10.9, mysql:8, gvenzl/oracle-free:latest, gvenzl/oracle-xe:18-slim, postgres:15, ./bld, 21, ubuntu-latest, true) (push) Waiting to run
bld-ci / build (unittests, password, unittests, mariadb:10.9, mysql:8, gvenzl/oracle-free:latest, gvenzl/oracle-xe:18-slim, postgres:15, ./bld, 25, ubuntu-latest, true) (push) Waiting to run
bld-ci / build (unittests, password, unittests, mariadb:10.9, mysql:8, gvenzl/oracle-free:latest, gvenzl/oracle-xe:18-slim, postgres:15, ./bld, 26, ubuntu-latest, true) (push) Waiting to run
javadocs-pages / deploy (push) Waiting to run
This commit is contained in:
parent
682fb05d15
commit
30937a4d96
|
|
@ -25,6 +25,7 @@ public class Project extends BaseProject {
|
||||||
|
|
||||||
private final JavadocOperation javadocOperation_ = new JavadocOperation();
|
private final JavadocOperation javadocOperation_ = new JavadocOperation();
|
||||||
private final PrecompileOperation precompileOperation_ = new PrecompileOperation();
|
private final PrecompileOperation precompileOperation_ = new PrecompileOperation();
|
||||||
|
private final InstrumentOperation instrumentOperation_ = new InstrumentOperation();
|
||||||
private final JarOperation jarOperation_ = new JarOperation();
|
private final JarOperation jarOperation_ = new JarOperation();
|
||||||
private final JarOperation jarSourcesOperation_ = new JarOperation();
|
private final JarOperation jarSourcesOperation_ = new JarOperation();
|
||||||
private final JarOperation jarJavadocOperation_ = new JarOperation();
|
private final JarOperation jarJavadocOperation_ = new JarOperation();
|
||||||
|
|
@ -56,6 +57,16 @@ public class Project extends BaseProject {
|
||||||
return precompileOperation_;
|
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.
|
* Retrieves the project's default jar operation.
|
||||||
*
|
*
|
||||||
|
|
@ -125,6 +136,19 @@ public class Project extends BaseProject {
|
||||||
precompileOperation().executeOnce(() -> precompileOperation().fromProject(this));
|
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.
|
* Standard build command, creates a jar archive for the project.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
31
src/main/java/rife/bld/help/InstrumentHelp.java
Normal file
31
src/main/java/rife/bld/help/InstrumentHelp.java
Normal file
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
140
src/main/java/rife/bld/operations/InstrumentOperation.java
Normal file
140
src/main/java/rife/bld/operations/InstrumentOperation.java
Normal file
|
|
@ -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.
|
||||||
|
* <p>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.
|
||||||
|
* <p>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<InstrumentOperation> {
|
||||||
|
public static final String DEPLOYER_CLASS = "rife.instrument.InstrumentationDeployer";
|
||||||
|
|
||||||
|
private final List<File> sourceDirectories_ = new ArrayList<>();
|
||||||
|
private File destinationDirectory_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Part of the {@link #execute} operation, constructs the command list
|
||||||
|
* to use for building the process.
|
||||||
|
*
|
||||||
|
* @since 2.4
|
||||||
|
*/
|
||||||
|
protected List<String> executeConstructProcessCommandList() {
|
||||||
|
var args = new ArrayList<String>();
|
||||||
|
args.add(javaTool());
|
||||||
|
args.addAll(javaOptions());
|
||||||
|
|
||||||
|
if (!classpath().isEmpty()) {
|
||||||
|
args.add("-cp");
|
||||||
|
args.add(FileUtils.joinPaths(classpath()));
|
||||||
|
}
|
||||||
|
|
||||||
|
args.add(DEPLOYER_CLASS);
|
||||||
|
args.add("-verbose");
|
||||||
|
args.add("-d");
|
||||||
|
args.add(destinationDirectory().getAbsolutePath());
|
||||||
|
for (var directory : sourceDirectories()) {
|
||||||
|
args.add(directory.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures an instrument operation from a {@link BaseProject}.
|
||||||
|
* <p>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.
|
||||||
|
* <p>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<File> directories) {
|
||||||
|
sourceDirectories_.addAll(directories);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the destination directory in which the instrumented classes
|
||||||
|
* will be stored.
|
||||||
|
*
|
||||||
|
* @param directory the instrumentation destination directory
|
||||||
|
* @return this operation instance
|
||||||
|
* @since 2.4
|
||||||
|
*/
|
||||||
|
public InstrumentOperation destinationDirectory(File directory) {
|
||||||
|
destinationDirectory_ = directory;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the source directories that will be instrumented.
|
||||||
|
* <p>This is a modifiable list that can be retrieved and changed.
|
||||||
|
*
|
||||||
|
* @return the instrumentation source directories
|
||||||
|
* @since 2.4
|
||||||
|
*/
|
||||||
|
public List<File> sourceDirectories() {
|
||||||
|
return sourceDirectories_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the destination directory in which the instrumented classes
|
||||||
|
* will be stored.
|
||||||
|
*
|
||||||
|
* @return the instrumentation destination directory
|
||||||
|
* @since 2.4
|
||||||
|
*/
|
||||||
|
public File destinationDirectory() {
|
||||||
|
return destinationDirectory_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* 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 org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
public class TestInstrumentOperation {
|
||||||
|
@Test
|
||||||
|
void testInstantiation() {
|
||||||
|
var operation = new InstrumentOperation();
|
||||||
|
assertEquals("java", operation.javaTool());
|
||||||
|
assertTrue(operation.javaOptions().isEmpty());
|
||||||
|
assertTrue(operation.classpath().isEmpty());
|
||||||
|
assertTrue(operation.sourceDirectories().isEmpty());
|
||||||
|
assertNull(operation.destinationDirectory());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPopulation() {
|
||||||
|
var source1 = new File("source1");
|
||||||
|
var source2 = new File("source2");
|
||||||
|
var destination = new File("destination");
|
||||||
|
|
||||||
|
var operation = new InstrumentOperation()
|
||||||
|
.classpath("classpath1", "classpath2")
|
||||||
|
.sourceDirectories(source1, source2)
|
||||||
|
.destinationDirectory(destination);
|
||||||
|
assertEquals(2, operation.classpath().size());
|
||||||
|
assertEquals(2, operation.sourceDirectories().size());
|
||||||
|
assertEquals(destination, operation.destinationDirectory());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testProcessCommandList() {
|
||||||
|
var operation = new InstrumentOperation()
|
||||||
|
.classpath("cp1", "cp2")
|
||||||
|
.sourceDirectories(new File("classes"), new File("more-classes"))
|
||||||
|
.destinationDirectory(new File("instrumented"));
|
||||||
|
|
||||||
|
var command = operation.executeConstructProcessCommandList();
|
||||||
|
assertEquals("java", command.get(0));
|
||||||
|
assertTrue(command.contains("-cp"));
|
||||||
|
assertTrue(command.contains("cp1" + File.pathSeparator + "cp2"));
|
||||||
|
assertTrue(command.contains(InstrumentOperation.DEPLOYER_CLASS));
|
||||||
|
assertTrue(command.contains("-verbose"));
|
||||||
|
var d_index = command.indexOf("-d");
|
||||||
|
assertTrue(d_index > 0);
|
||||||
|
assertEquals(new File("instrumented").getAbsolutePath(), command.get(d_index + 1));
|
||||||
|
assertEquals(new File("classes").getAbsolutePath(), command.get(command.size() - 2));
|
||||||
|
assertEquals(new File("more-classes").getAbsolutePath(), command.get(command.size() - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue