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 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.
|
||||
*
|
||||
|
|
|
|||
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