BREAKING CHANGE: Kotlin must be installed. Location is deducted from KOTLIN_HOME, if set.
This commit is contained in:
parent
c84019de2c
commit
6fa3bdefdb
8 changed files with 190 additions and 96 deletions
|
@ -42,23 +42,7 @@ public class CompileKotlinOperationBuild extends Project {
|
|||
|
||||
repositories = List.of(MAVEN_LOCAL, MAVEN_CENTRAL, RIFE2_RELEASES, RIFE2_SNAPSHOTS);
|
||||
|
||||
var kotlin = version(2, 0, 0);
|
||||
scope(compile)
|
||||
.include(dependency("org.jetbrains.kotlin", "kotlin-compiler", kotlin))
|
||||
.include(dependency("org.jetbrains.kotlin", "kotlin-annotation-processing", kotlin))
|
||||
.include(dependency("org.jetbrains.kotlin", "kotlin-scripting-compiler", kotlin))
|
||||
.include(dependency("org.jetbrains.kotlin", "kotlin-reflect", kotlin))
|
||||
.include(dependency("org.jetbrains.kotlin", "kotlin-stdlib-common", kotlin))
|
||||
.include(dependency("org.jetbrains.kotlinx", "kotlinx-coroutines-core-jvm", version(1, 9, 0, "RC")))
|
||||
// Compiler Plugins
|
||||
.include(dependency("org.jetbrains.kotlin", "kotlin-allopen-compiler-plugin", kotlin))
|
||||
.include(dependency("org.jetbrains.kotlin", "kotlin-assignment-compiler-plugin", kotlin))
|
||||
.include(dependency("org.jetbrains.kotlin", "kotlin-serialization-compiler-plugin", kotlin))
|
||||
.include(dependency("org.jetbrains.kotlin", "kotlin-lombok-compiler-plugin", kotlin))
|
||||
.include(dependency("org.jetbrains.kotlin", "kotlin-allopen-compiler-plugin", kotlin))
|
||||
.include(dependency("org.jetbrains.kotlin", "kotlin-noarg-compiler-plugin", kotlin))
|
||||
.include(dependency("org.jetbrains.kotlin", "kotlin-power-assert-compiler-plugin", kotlin))
|
||||
.include(dependency("org.jetbrains.kotlin", "kotlin-sam-with-receiver-compiler-plugin", kotlin))
|
||||
.include(dependency("com.uwyn.rife2", "bld", version(2, 0, 0, "SNAPSHOT")));
|
||||
scope(test)
|
||||
.include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 10, 3)))
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package rife.bld.extension;
|
||||
|
||||
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler;
|
||||
import rife.bld.BaseProject;
|
||||
import rife.bld.extension.kotlin.CompileOptions;
|
||||
import rife.bld.extension.kotlin.CompilerPlugin;
|
||||
|
@ -26,7 +25,7 @@ import rife.tools.FileUtils;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
@ -52,32 +51,9 @@ public class CompileKotlinOperation extends AbstractOperation<CompileKotlinOpera
|
|||
private File buildMainDirectory_;
|
||||
private File buildTestDirectory_;
|
||||
private CompileOptions compileOptions_ = new CompileOptions();
|
||||
private File kotlinHome_;
|
||||
private BaseProject project_;
|
||||
|
||||
/**
|
||||
* Returns the list of Java archives contained in a given directory.
|
||||
*
|
||||
* @param directory the directory
|
||||
* @param regex the regular expression to match
|
||||
* @return the list of JARs
|
||||
*/
|
||||
public static List<String> getJarList(File directory, String regex) {
|
||||
var jars = new ArrayList<String>();
|
||||
|
||||
if (directory.isDirectory()) {
|
||||
var files = directory.listFiles();
|
||||
if (files != null) {
|
||||
for (var f : files) {
|
||||
if (!f.getName().endsWith("-sources.jar") && (!f.getName().endsWith("-javadoc.jar")) &&
|
||||
f.getName().matches(regex)) {
|
||||
jars.add(f.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return jars;
|
||||
}
|
||||
private File workDir_;
|
||||
|
||||
/**
|
||||
* Determines if the given string is not blank.
|
||||
|
@ -222,6 +198,18 @@ public class CompileKotlinOperation extends AbstractOperation<CompileKotlinOpera
|
|||
LOGGER.severe("A project must be specified.");
|
||||
}
|
||||
throw new ExitStatusException(ExitStatusException.EXIT_FAILURE);
|
||||
} else if (!workDir_.isDirectory()) {
|
||||
if (LOGGER.isLoggable(Level.SEVERE) && !silent()) {
|
||||
LOGGER.severe("Invalid working directory: " + workDir_.getAbsolutePath());
|
||||
}
|
||||
throw new ExitStatusException(ExitStatusException.EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (kotlinHome_ == null) {
|
||||
if (LOGGER.isLoggable(Level.SEVERE) && !silent()) {
|
||||
LOGGER.severe("The KOTLIN_HOME environment variable is not set.");
|
||||
}
|
||||
throw new ExitStatusException(ExitStatusException.EXIT_FAILURE);
|
||||
}
|
||||
|
||||
executeCreateBuildDirectories();
|
||||
|
@ -239,7 +227,7 @@ public class CompileKotlinOperation extends AbstractOperation<CompileKotlinOpera
|
|||
* @throws ExitStatusException if an error occurs
|
||||
*/
|
||||
@SuppressWarnings("PMD.SystemPrintln")
|
||||
protected void executeBuildMainSources() throws ExitStatusException {
|
||||
protected void executeBuildMainSources() throws ExitStatusException, IOException, InterruptedException {
|
||||
if (!silent()) {
|
||||
System.out.println("Compiling Kotlin main sources.");
|
||||
}
|
||||
|
@ -262,47 +250,62 @@ public class CompileKotlinOperation extends AbstractOperation<CompileKotlinOpera
|
|||
*/
|
||||
protected void executeBuildSources(Collection<String> classpath, Collection<File> sources, File destination,
|
||||
File friendPaths)
|
||||
throws ExitStatusException {
|
||||
throws ExitStatusException, InterruptedException, IOException {
|
||||
if (sources.isEmpty() || destination == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var k2 = new K2JVMCompiler();
|
||||
var args = new ArrayList<String>();
|
||||
var kotlinc = Path.of(kotlinHome_.getAbsolutePath(), "bin", "kotlinc").toFile();
|
||||
|
||||
// classpath
|
||||
args.add("-cp");
|
||||
args.add(FileUtils.joinPaths(classpath.stream().toList()));
|
||||
if (kotlinc.exists() && kotlinc.canExecute()) {
|
||||
var args = new ArrayList<String>();
|
||||
|
||||
// destination
|
||||
args.add("-d");
|
||||
args.add(destination.getAbsolutePath());
|
||||
// kotlinc
|
||||
args.add(kotlinc.getAbsolutePath());
|
||||
|
||||
// friend-path
|
||||
if (friendPaths != null && friendPaths.exists()) {
|
||||
args.add("-Xfriend-paths=" + friendPaths.getAbsolutePath());
|
||||
}
|
||||
// classpath
|
||||
args.add("-cp");
|
||||
args.add(FileUtils.joinPaths(classpath.stream().toList()));
|
||||
|
||||
// options
|
||||
if (compileOptions_ != null) {
|
||||
args.addAll(compileOptions_.args());
|
||||
}
|
||||
// destination
|
||||
args.add("-d");
|
||||
args.add(destination.getAbsolutePath());
|
||||
|
||||
// plugins
|
||||
if (!plugins_.isEmpty()) {
|
||||
plugins_.forEach(p -> args.add("-Xplugin=" + p));
|
||||
}
|
||||
// friend-path
|
||||
if (friendPaths != null && friendPaths.exists()) {
|
||||
args.add("-Xfriend-paths=" + friendPaths.getAbsolutePath());
|
||||
}
|
||||
|
||||
// sources
|
||||
sources.forEach(f -> args.add(f.getAbsolutePath()));
|
||||
// options
|
||||
if (compileOptions_ != null) {
|
||||
args.addAll(compileOptions_.args());
|
||||
}
|
||||
|
||||
if (LOGGER.isLoggable(Level.FINE) && !silent()) {
|
||||
LOGGER.fine("kotlinc " + String.join(" ", args));
|
||||
}
|
||||
// plugins
|
||||
if (!plugins_.isEmpty()) {
|
||||
plugins_.forEach(p -> args.add("-Xplugin=" + p));
|
||||
}
|
||||
|
||||
var exitCode = k2.exec(System.err, args.toArray(String[]::new));
|
||||
if (exitCode.getCode() != 0) {
|
||||
throw new ExitStatusException(exitCode.getCode());
|
||||
// sources
|
||||
sources.forEach(f -> args.add(f.getAbsolutePath()));
|
||||
|
||||
if (LOGGER.isLoggable(Level.FINE) && !silent()) {
|
||||
LOGGER.fine(String.join(" ", args));
|
||||
}
|
||||
|
||||
var pb = new ProcessBuilder();
|
||||
pb.inheritIO();
|
||||
pb.command(args);
|
||||
pb.directory(workDir_);
|
||||
|
||||
var proc = pb.start();
|
||||
proc.waitFor();
|
||||
ExitStatusException.throwOnFailure(proc.exitValue());
|
||||
} else {
|
||||
if (LOGGER.isLoggable(Level.SEVERE) && !silent()) {
|
||||
LOGGER.severe("The Kotlin compiler could not be found or executed: " + kotlinc.getAbsolutePath());
|
||||
}
|
||||
throw new ExitStatusException(ExitStatusException.EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -312,7 +315,7 @@ public class CompileKotlinOperation extends AbstractOperation<CompileKotlinOpera
|
|||
* @throws ExitStatusException if an error occurs
|
||||
*/
|
||||
@SuppressWarnings("PMD.SystemPrintln")
|
||||
protected void executeBuildTestSources() throws ExitStatusException {
|
||||
protected void executeBuildTestSources() throws ExitStatusException, IOException, InterruptedException {
|
||||
if (!silent()) {
|
||||
System.out.println("Compiling Kotlin test sources.");
|
||||
}
|
||||
|
@ -342,6 +345,8 @@ public class CompileKotlinOperation extends AbstractOperation<CompileKotlinOpera
|
|||
* <p>
|
||||
* Sets the following from the project:
|
||||
* <ul>
|
||||
* <li>{@link #kotlinHome()} to the {@code KOTLIN_HOME} environment variable, if set.</li>
|
||||
* <li>{@link #workDir()} to the project's directory.</li>
|
||||
* <li>{@link #buildMainDirectory() buildMainDirectory}</li>
|
||||
* <li>{@link #buildTestDirectory() buildTestDirectory}</li>
|
||||
* <li>{@link #compileMainClasspath() compileMainClassPath}</li>
|
||||
|
@ -359,6 +364,14 @@ public class CompileKotlinOperation extends AbstractOperation<CompileKotlinOpera
|
|||
*/
|
||||
public CompileKotlinOperation fromProject(BaseProject project) {
|
||||
project_ = project;
|
||||
|
||||
var env = System.getenv("KOTLIN_HOME");
|
||||
if (env != null) {
|
||||
kotlinHome_ = new File(env);
|
||||
}
|
||||
|
||||
workDir_ = new File(project.workDirectory().getAbsolutePath());
|
||||
|
||||
var op = buildMainDirectory(project.buildMainDirectory())
|
||||
.buildTestDirectory(project.buildTestDirectory())
|
||||
.compileMainClasspath(project.compileMainClasspath())
|
||||
|
@ -373,6 +386,36 @@ public class CompileKotlinOperation extends AbstractOperation<CompileKotlinOpera
|
|||
return op;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the Kotlin home directory, if it differs from the default {@code KOTLIN_HOME}.
|
||||
*
|
||||
* @param dir the directory
|
||||
* @return this operation instance
|
||||
*/
|
||||
public CompileKotlinOperation kotlinHome(File dir) {
|
||||
kotlinHome_ = dir;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the Kotlin home directory, if it differs from the default {@code KOTLIN_HOME}.
|
||||
*
|
||||
* @param dir the directory path
|
||||
* @return this operation instance
|
||||
*/
|
||||
public CompileKotlinOperation kotlinHome(String dir) {
|
||||
return kotlinHome(new File(dir));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Kotlin home directory.
|
||||
*
|
||||
* @return the directory
|
||||
*/
|
||||
public File kotlinHome() {
|
||||
return kotlinHome_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides main source directories that should be compiled.
|
||||
*
|
||||
|
@ -497,20 +540,29 @@ public class CompileKotlinOperation extends AbstractOperation<CompileKotlinOpera
|
|||
*/
|
||||
public CompileKotlinOperation plugins(File directory, CompilerPlugin... plugins) {
|
||||
for (var plugin : plugins) {
|
||||
plugins_.addAll(getJarList(directory, plugin.regex));
|
||||
plugins_.add(new File(directory, plugin.jar).getAbsolutePath());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides compiler plugins.
|
||||
* <p>
|
||||
* The {@link #kotlinHome()} should be set first.
|
||||
*
|
||||
* @param plugins one or more plugins
|
||||
* @return this class instance
|
||||
*/
|
||||
public CompileKotlinOperation plugins(CompilerPlugin... plugins) {
|
||||
for (var plugin : plugins) {
|
||||
plugins_.addAll(getJarList(project_.libBldDirectory(), plugin.regex));
|
||||
if (kotlinHome_ != null) {
|
||||
var kotlinLib = new File(kotlinHome_, "lib");
|
||||
for (var plugin : plugins) {
|
||||
plugins(kotlinLib, plugin);
|
||||
}
|
||||
} else {
|
||||
if (LOGGER.isLoggable(Level.WARNING) && !silent()) {
|
||||
LOGGER.warning("The Kotlin home must be set to specify compiler plugins directly.");
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -525,7 +577,7 @@ public class CompileKotlinOperation extends AbstractOperation<CompileKotlinOpera
|
|||
public CompileKotlinOperation plugins(Collection<File> jars, CompilerPlugin... plugins) {
|
||||
jars.forEach(jar -> {
|
||||
for (var plugin : plugins) {
|
||||
if (jar.getName().matches(plugin.regex)) {
|
||||
if (jar.getName().matches(plugin.jar)) {
|
||||
plugins_.add(jar.getAbsolutePath());
|
||||
break;
|
||||
}
|
||||
|
@ -625,4 +677,34 @@ public class CompileKotlinOperation extends AbstractOperation<CompileKotlinOpera
|
|||
public Collection<File> testSourceFiles() {
|
||||
return testSourceFiles_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the working directory.
|
||||
*
|
||||
* @return the directory
|
||||
*/
|
||||
public File workDir() {
|
||||
return workDir_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the working directory, if it differs from the project's directory.
|
||||
*
|
||||
* @param dir the directory
|
||||
* @return this operation instance
|
||||
*/
|
||||
public CompileKotlinOperation workDir(File dir) {
|
||||
workDir_ = dir;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the working directory, if it differs from the project's directory.
|
||||
*
|
||||
* @param dir the directory path
|
||||
* @return this operation instance
|
||||
*/
|
||||
public CompileKotlinOperation workDir(String dir) {
|
||||
return workDir(new File(dir));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,23 +17,24 @@
|
|||
package rife.bld.extension.kotlin;
|
||||
|
||||
/**
|
||||
* Defines the known Kotlin compiler plugins match (regex) strings.
|
||||
* Defines the known Kotlin compiler plugin JARs.
|
||||
*
|
||||
* @author <a href="https://erik.thauvin.net/">Erik C. Thauvin</a>
|
||||
* @since 1.0
|
||||
*/
|
||||
public enum CompilerPlugin {
|
||||
ALL_OPEN("^kotlin-allopen-compiler-plugin-.*$"),
|
||||
ASSIGNMENT("^kotlin-assignment-compiler-plugin-.*$"),
|
||||
KOTLIN_SERIALIZATION("^kotlin-serialization-compiler-plugin-.*$"),
|
||||
LOMBOK("^kotlin-lombok-compiler-plugin-.*$"),
|
||||
NOARG("^kotlin-noarg-compiler-plugin-.*$"),
|
||||
POWER_ASSERT("^kotlin-power-assert-compiler-plugin-.*$"),
|
||||
SAM_WITH_RECEIVER("^kotlin-sam-with-receiver-compiler-plugin-.*$");
|
||||
ALL_OPEN("kotlin-allopen-compiler-plugin.jar"),
|
||||
ASSIGNMENT("kotlin-assignment-compiler-plugin.jar"),
|
||||
KOTLINX_SERIALIZATION("kotlinx-serialization-compiler-plugin.jar"),
|
||||
KOTLIN_SERIALIZATION("kotlin-serialization-compiler-plugin.jar"),
|
||||
LOMBOK("kotlin-lombok-compiler-plugin.jar"),
|
||||
NOARG("kotlin-noarg-compiler-plugin.jar"),
|
||||
POWER_ASSERT("kotlin-power-assert-compiler-plugin.jar"),
|
||||
SAM_WITH_RECEIVER("kotlin-sam-with-receiver-compiler-plugin.jar");
|
||||
|
||||
public final String regex;
|
||||
public final String jar;
|
||||
|
||||
CompilerPlugin(String regex) {
|
||||
this.regex = regex;
|
||||
CompilerPlugin(String jar) {
|
||||
this.jar = jar;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,6 +53,8 @@ class CompileKotlinOperationTest {
|
|||
void testCollections() {
|
||||
var op = new CompileKotlinOperation()
|
||||
.fromProject(new Project())
|
||||
.kotlinHome("/kotlin_home")
|
||||
.workDir("work_dir")
|
||||
.compileMainClasspath("path1", "path2")
|
||||
.compileOptions(new CompileOptions().jdkRelease("17").verbose(true))
|
||||
.mainSourceDirectories("dir1", "dir2")
|
||||
|
@ -72,6 +74,9 @@ class CompileKotlinOperationTest {
|
|||
.plugins(Arrays.stream(Objects.requireNonNull(new File("lib/compile").listFiles())).toList(),
|
||||
CompilerPlugin.ALL_OPEN, CompilerPlugin.SAM_WITH_RECEIVER);
|
||||
|
||||
assertThat(op.kotlinHome().getName()).as("kotlin_home").isEqualTo("kotlin_home");
|
||||
assertThat(op.workDir().getName()).as("work_dir").isEqualTo("work_dir");
|
||||
|
||||
assertThat(op.compileMainClasspath()).as("compileMainClassPath")
|
||||
.containsAll(List.of("path1", "path2"));
|
||||
assertThat(op.compileOptions().hasRelease()).as("hasRelease").isTrue();
|
||||
|
@ -88,7 +93,9 @@ class CompileKotlinOperationTest {
|
|||
assertThat(op.testSourceFiles()).as("testSourceFiles").containsOnly(
|
||||
new File("tfile1"), new File("tfile2"), new File("tfile3"),
|
||||
new File("tfile4"), new File("tfile5"), new File("tfile6"));
|
||||
assertThat(op.plugins()).hasSize(10);
|
||||
assertThat(op.plugins()).as("plugins").contains("/kotlin_home/lib/kotlin-serialization-compiler-plugin.jar",
|
||||
"/kotlin_home/lib/kotlin-assignment-compiler-plugin.jar", "plugin2", "plugin3", "plugin4");
|
||||
assertThat(op.plugins()).as("plugins size").hasSize(8);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue