mirror of
https://github.com/ethauvin/bld.git
synced 2025-04-25 08:17:11 -07:00
Added support for automatically setting a module main class if module-info.java is part of the compilation operation and a main class was provided by the project.
This commit is contained in:
parent
9f9e8a95db
commit
fd1429f2d3
3 changed files with 80 additions and 4 deletions
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2001-2024 Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||||
|
*/
|
||||||
|
package rife.bld.instrument;
|
||||||
|
|
||||||
|
import rife.asm.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This utility class will modify a Java module {@code module-info.class} to add
|
||||||
|
* a module main class to its attributes.
|
||||||
|
*
|
||||||
|
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
public class ModuleMainClassAdapter extends ClassVisitor implements Opcodes {
|
||||||
|
private final String mainClass_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the actual modification of the module info class's bytecode.
|
||||||
|
*
|
||||||
|
* @param origBytes the bytes of the module class that should be modified
|
||||||
|
* @param mainClass the main class of the module
|
||||||
|
* @return the modified bytes
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
public static byte[] addModuleMainClassToBytes(byte[] origBytes, String mainClass) {
|
||||||
|
var cw = new ClassWriter(0);
|
||||||
|
new ClassReader(origBytes).accept(new ModuleMainClassAdapter(mainClass, cw), 0);
|
||||||
|
return cw.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ModuleMainClassAdapter(String mainClass, ClassVisitor writer) {
|
||||||
|
super(ASM9, writer);
|
||||||
|
mainClass_ = mainClass.replace('.', '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModuleVisitor visitModule(String name, int access, String version) {
|
||||||
|
var module_visitor = super.visitModule(name, access, version);
|
||||||
|
module_visitor.visitMainClass(mainClass_);
|
||||||
|
return module_visitor;
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@
|
||||||
package rife.bld.operations;
|
package rife.bld.operations;
|
||||||
|
|
||||||
import rife.bld.BaseProject;
|
import rife.bld.BaseProject;
|
||||||
|
import rife.bld.instrument.ModuleMainClassAdapter;
|
||||||
import rife.bld.operations.exceptions.ExitStatusException;
|
import rife.bld.operations.exceptions.ExitStatusException;
|
||||||
import rife.tools.FileUtils;
|
import rife.tools.FileUtils;
|
||||||
|
|
||||||
|
@ -34,6 +35,7 @@ public class CompileOperation extends AbstractOperation<CompileOperation> {
|
||||||
private final List<File> testSourceDirectories_ = new ArrayList<>();
|
private final List<File> testSourceDirectories_ = new ArrayList<>();
|
||||||
private final JavacOptions compileOptions_ = new JavacOptions();
|
private final JavacOptions compileOptions_ = new JavacOptions();
|
||||||
private final List<Diagnostic<? extends JavaFileObject>> diagnostics_ = new ArrayList<>();
|
private final List<Diagnostic<? extends JavaFileObject>> diagnostics_ = new ArrayList<>();
|
||||||
|
private String moduleMainClass_;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs the compile operation.
|
* Performs the compile operation.
|
||||||
|
@ -135,6 +137,12 @@ public class CompileOperation extends AbstractOperation<CompileOperation> {
|
||||||
diagnostics_.addAll(diagnostics.getDiagnostics());
|
diagnostics_.addAll(diagnostics.getDiagnostics());
|
||||||
executeProcessDiagnostics(diagnostics);
|
executeProcessDiagnostics(diagnostics);
|
||||||
}
|
}
|
||||||
|
var module_info_class = new File(destination, "module-info.class");
|
||||||
|
if (module_info_class.exists() && moduleMainClass() != null) {
|
||||||
|
var orig_bytes = FileUtils.readBytes(module_info_class);
|
||||||
|
var transformed_bytes = ModuleMainClassAdapter.addModuleMainClassToBytes(orig_bytes, moduleMainClass());
|
||||||
|
FileUtils.writeBytes(transformed_bytes, module_info_class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +183,8 @@ public class CompileOperation extends AbstractOperation<CompileOperation> {
|
||||||
.compileMainModulePath(project.compileMainModulePath())
|
.compileMainModulePath(project.compileMainModulePath())
|
||||||
.compileTestModulePath(project.compileTestModulePath())
|
.compileTestModulePath(project.compileTestModulePath())
|
||||||
.mainSourceFiles(project.mainSourceFiles())
|
.mainSourceFiles(project.mainSourceFiles())
|
||||||
.testSourceFiles(project.testSourceFiles());
|
.testSourceFiles(project.testSourceFiles())
|
||||||
|
.moduleMainClass(project.mainClass());
|
||||||
if (project.javaRelease() != null && !compileOptions().containsRelease()) {
|
if (project.javaRelease() != null && !compileOptions().containsRelease()) {
|
||||||
compileOptions().release(project.javaRelease());
|
compileOptions().release(project.javaRelease());
|
||||||
}
|
}
|
||||||
|
@ -428,6 +437,18 @@ public class CompileOperation extends AbstractOperation<CompileOperation> {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the main class to use if this compilation includes @{code module-info.java}.
|
||||||
|
*
|
||||||
|
* @param name the main class of the module
|
||||||
|
* @return this operation instance
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
public CompileOperation moduleMainClass(String name) {
|
||||||
|
moduleMainClass_ = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the main build destination directory.
|
* Retrieves the main build destination directory.
|
||||||
*
|
*
|
||||||
|
@ -565,4 +586,15 @@ public class CompileOperation extends AbstractOperation<CompileOperation> {
|
||||||
public List<Diagnostic<? extends JavaFileObject>> diagnostics() {
|
public List<Diagnostic<? extends JavaFileObject>> diagnostics() {
|
||||||
return diagnostics_;
|
return diagnostics_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the main class to use if this compilation includes @{code module-info.java}.
|
||||||
|
*
|
||||||
|
* @return the main class to use for the module
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
public String moduleMainClass() {
|
||||||
|
return moduleMainClass_;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,7 +199,8 @@ public class TestRunOperation {
|
||||||
var compile_operation = new CompileOperation()
|
var compile_operation = new CompileOperation()
|
||||||
.buildMainDirectory(build_main)
|
.buildMainDirectory(build_main)
|
||||||
.compileMainClasspath(List.of(build_main.getAbsolutePath()))
|
.compileMainClasspath(List.of(build_main.getAbsolutePath()))
|
||||||
.mainSourceFiles(List.of(source_file1, source_file2));
|
.mainSourceFiles(List.of(source_file1, source_file2))
|
||||||
|
.moduleMainClass("pkg.Source1");
|
||||||
compile_operation.execute();
|
compile_operation.execute();
|
||||||
assertTrue(compile_operation.diagnostics().isEmpty());
|
assertTrue(compile_operation.diagnostics().isEmpty());
|
||||||
|
|
||||||
|
@ -209,12 +210,11 @@ public class TestRunOperation {
|
||||||
.sourceDirectories(List.of(build_main))
|
.sourceDirectories(List.of(build_main))
|
||||||
.destinationDirectory(destination_dir)
|
.destinationDirectory(destination_dir)
|
||||||
.destinationFileName(destination_name)
|
.destinationFileName(destination_name)
|
||||||
.manifestAttribute(Attributes.Name.MAIN_CLASS, "pkg.Source1")
|
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
var output = new StringBuilder();
|
var output = new StringBuilder();
|
||||||
var run_operation = new RunOperation()
|
var run_operation = new RunOperation()
|
||||||
.module("pkg/pkg.Source1")
|
.module("pkg")
|
||||||
.modulePath(new File(destination_dir, destination_name).getAbsolutePath())
|
.modulePath(new File(destination_dir, destination_name).getAbsolutePath())
|
||||||
.outputProcessor(s -> {
|
.outputProcessor(s -> {
|
||||||
output.append(s);
|
output.append(s);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue