diff --git a/examples/src/bld/java/com/example/ExampleBuild.java b/examples/src/bld/java/com/example/ExampleBuild.java index 87cc83a..cd44399 100644 --- a/examples/src/bld/java/com/example/ExampleBuild.java +++ b/examples/src/bld/java/com/example/ExampleBuild.java @@ -60,17 +60,14 @@ public class ExampleBuild extends Project { @BuildCommand(summary = "Compiles the Kotlin project") @Override public void compile() throws Exception { + var options = new CompileOptions().verbose(true); + options.jvmOptions().enableNativeAccess(JvmOptions.ALL_UNNAMED); // The source code located in src/main/kotlin and src/test/kotlin will be compiled - var op = new CompileKotlinOperation() + new CompileKotlinOperation() // .kotlinHome("path/to/kotlin") // .kotlinc("path/to/kotlinc") - .compileOptions(new CompileOptions().verbose(true)) - .fromProject(this); - - if (!CompileKotlinOperation.isWindows()) { - op.jvmOptions().enableNativeAccess(JvmOptions.ALL_UNNAMED); - } - - op.execute(); + .compileOptions(options) + .fromProject(this) + .execute(); } } diff --git a/src/main/java/rife/bld/extension/CompileKotlinOperation.java b/src/main/java/rife/bld/extension/CompileKotlinOperation.java index 8f7372e..64aabff 100644 --- a/src/main/java/rife/bld/extension/CompileKotlinOperation.java +++ b/src/main/java/rife/bld/extension/CompileKotlinOperation.java @@ -19,14 +19,12 @@ package rife.bld.extension; import rife.bld.BaseProject; import rife.bld.extension.kotlin.CompileOptions; import rife.bld.extension.kotlin.CompilerPlugin; -import rife.bld.extension.kotlin.JvmOptions; import rife.bld.operations.AbstractOperation; import rife.bld.operations.exceptions.ExitStatusException; import rife.tools.FileUtils; import java.io.File; import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; import java.util.*; import java.util.logging.Level; @@ -45,7 +43,6 @@ public class CompileKotlinOperation extends AbstractOperation compileMainClasspath_ = new ArrayList<>(); private final Collection compileTestClasspath_ = new ArrayList<>(); - private final JvmOptions jvmOptions_ = new JvmOptions(); private final Collection mainSourceDirectories_ = new ArrayList<>(); private final Collection mainSourceFiles_ = new ArrayList<>(); private final Collection plugins_ = new ArrayList<>(); @@ -320,17 +317,6 @@ public class CompileKotlinOperation extends AbstractOperation classpath, Collection sources, File destination, File friendPaths) throws ExitStatusException { - - var cp = new ArrayList(); - if (classpath != null && !classpath.isEmpty()) { - cp.addAll(classpath); - } - if (sources.isEmpty()) { if (!silent() && LOGGER.isLoggable(Level.WARNING)) { LOGGER.warning("Nothing to compile."); @@ -488,75 +468,56 @@ public class CompileKotlinOperation extends AbstractOperation(); var args = new ArrayList(); // kotlinc if (kotlinc_ != null) { - command.add(kotlinc_.getAbsolutePath()); + args.add(kotlinc_.getAbsolutePath()); } else if (kotlinHome_ != null) { - command.add(Objects.requireNonNullElseGet(findKotlincInDir(kotlinHome_.getAbsolutePath()), + args.add(Objects.requireNonNullElseGet(findKotlincInDir(kotlinHome_.getAbsolutePath()), CompileKotlinOperation::findKotlincPath)); } else { - command.add(findKotlincPath(silent())); - } - - // JVM options - if (!jvmOptions_.isEmpty()) { - jvmOptions_.forEach(s -> command.add("-J" + s)); - } - - // compiler options - if (compileOptions_ != null) { - args.addAll(compileOptions_.args()); - cp.addAll(compileOptions_.classpath().stream().map(this::cleanPath).toList()); + args.add(findKotlincPath(silent())); } // classpath - if (!cp.isEmpty()) { + if (classpath != null && !classpath.isEmpty()) { args.add("-cp"); - args.add('"' + FileUtils.joinPaths(cp.stream().map(this::cleanPath).toList()) + '"'); + args.add(FileUtils.joinPaths(classpath.stream().toList())); } // destination args.add("-d"); - args.add('"' + cleanPath(destination) + '"'); + args.add(destination.getAbsolutePath()); // friend-path if (friendPaths != null && friendPaths.exists()) { - args.add("-Xfriend-paths=\"" + cleanPath(friendPaths) + '"'); + args.add("-Xfriend-paths=" + friendPaths.getAbsolutePath()); + } + + // options + if (compileOptions_ != null) { + args.addAll(compileOptions_.args()); } // plugins if (!plugins_.isEmpty()) { - plugins_.forEach(p -> args.add("-Xplugin=\"" + cleanPath(p) + '"')); + plugins_.forEach(p -> args.add("-Xplugin=" + p)); } // sources - sources.forEach(f -> args.add('"' + cleanPath(f) + '"')); + sources.forEach(f -> args.add(f.getAbsolutePath())); - var argsLine = String.join(" ", args); - - // log the command line if (LOGGER.isLoggable(Level.FINE) && !silent()) { - LOGGER.fine(String.join(" ", command) + " " + argsLine); + LOGGER.fine(String.join(" ", args)); } + var pb = new ProcessBuilder(); + pb.inheritIO(); + pb.command(args); + pb.directory(workDir_); + try { - // create and write the @argfile - var argsFile = File.createTempFile("bld-kotlinc-", ".args"); - argsFile.deleteOnExit(); - - Files.write(argsFile.toPath(), argsLine.getBytes()); - - command.add("@" + argsFile.getAbsolutePath()); - - // run the command - var pb = new ProcessBuilder(); - pb.inheritIO(); - pb.command(command); - pb.directory(workDir_); - var proc = pb.start(); proc.waitFor(); ExitStatusException.throwOnFailure(proc.exitValue()); @@ -646,36 +607,6 @@ public class CompileKotlinOperation extends AbstractOperation jvmOptions) { - jvmOptions_.addAll(jvmOptions); - return this; - } - - /** - * Pass an option directly to the Java Virtual Machine - * - * @param jvmOptions one or more JVM option - * @return this operation instance - */ - public CompileKotlinOperation jvmOptions(String... jvmOptions) { - return jvmOptions(List.of(jvmOptions)); - } - /** * Provides the Kotlin home directory, if it differs from the default {@code KOTLIN_HOME}. * diff --git a/src/main/java/rife/bld/extension/kotlin/CompileOptions.java b/src/main/java/rife/bld/extension/kotlin/CompileOptions.java index 3e0e8bf..30f0a4e 100644 --- a/src/main/java/rife/bld/extension/kotlin/CompileOptions.java +++ b/src/main/java/rife/bld/extension/kotlin/CompileOptions.java @@ -23,6 +23,7 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.stream.Collectors; import static rife.bld.extension.CompileKotlinOperation.isNotBlank; @@ -36,6 +37,7 @@ public class CompileOptions { private final Collection advancedOptions_ = new ArrayList<>(); private final Collection argFile_ = new ArrayList<>(); private final Collection classpath_ = new ArrayList<>(); + private final JvmOptions jvmOptions_ = new JvmOptions(); private final Collection optIn_ = new ArrayList<>(); private final Collection options_ = new ArrayList<>(); private final Collection plugin_ = new ArrayList<>(); @@ -110,6 +112,7 @@ public class CompileOptions { return this; } + /** * Allow using declarations only from the specified version of Kotlin bundled libraries. * @@ -251,6 +254,12 @@ public class CompileOptions { argFile_.forEach(f -> args.add("@" + f.getAbsolutePath())); } + // classpath + if (!classpath_.isEmpty()) { + args.add("-classpath"); + args.add(classpath_.stream().map(File::getAbsolutePath).collect(Collectors.joining(File.pathSeparator))); + } + // expression if (isNotBlank(expression_)) { args.add("-expression"); @@ -284,6 +293,11 @@ public class CompileOptions { args.add("-Xjdk-release=" + jdkRelease_); } + // JVM options + if (!jvmOptions_.isEmpty()) { + jvmOptions_.forEach(s -> args.add("-J" + s)); + } + // kotlin-home if (kotlinHome_ != null) { args.add("-kotlin-home"); @@ -690,6 +704,36 @@ public class CompileOptions { return jdkRelease(String.valueOf(version)); } + /** + * Retrieves the Java Virtual Machine options. + * + * @return the JVM options + */ + public JvmOptions jvmOptions() { + return jvmOptions_; + } + + /** + * Pass an option directly to the Java Virtual Machine + * + * @param jvmOptions the JVM options + * @return this operation instance + */ + public CompileOptions jvmOptions(Collection jvmOptions) { + jvmOptions_.addAll(jvmOptions); + return this; + } + + /** + * Pass an option directly to the Java Virtual Machine + * + * @param jvmOptions one or more JVM option + * @return this operation instance + */ + public CompileOptions jvmOptions(String... jvmOptions) { + return jvmOptions(List.of(jvmOptions)); + } + /** * Specify the target version of the generated JVM bytecode. * diff --git a/src/test/java/rife/bld/extension/CompileKotlinOperationTest.java b/src/test/java/rife/bld/extension/CompileKotlinOperationTest.java index fc8aab2..0c33df0 100644 --- a/src/test/java/rife/bld/extension/CompileKotlinOperationTest.java +++ b/src/test/java/rife/bld/extension/CompileKotlinOperationTest.java @@ -182,14 +182,10 @@ class CompileKotlinOperationTest { op.compileOptions().verbose(true); op.compileOptions().jdkRelease("17"); - - if (!CompileKotlinOperation.isWindows()) { - op.jvmOptions().enableNativeAccess(JvmOptions.ALL_UNNAMED); - assertThat(op.jvmOptions()).containsExactly("--enable-native-access=ALL-UNNAMED"); - } + op.compileOptions().jvmOptions().enableNativeAccess(JvmOptions.ALL_UNNAMED); var args = op.compileOptions().args(); - var matches = List.of("-Xjdk-release=17", "-no-stdlib", "-verbose"); + var matches = List.of("-Xjdk-release=17", "-J--enable-native-access=ALL-UNNAMED", "-no-stdlib", "-verbose"); assertThat(args).as(args + " == " + matches).isEqualTo(matches); op.execute(); @@ -224,8 +220,8 @@ class CompileKotlinOperationTest { var examples = new File("examples"); var op = new CompileKotlinOperation().fromProject( new BaseProjectBlueprint(examples, "com.example", "examples", "examples")); - assertThat(op.mainSourceDirectories()).containsExactly(new File(examples, "src/main/kotlin")); - assertThat(op.testSourceDirectories()).containsExactly(new File(examples, "src/test/kotlin")); + assertThat(op.mainSourceDirectories()).contains(new File(examples, "src/main/kotlin")); + assertThat(op.testSourceDirectories()).contains(new File(examples, "src/test/kotlin")); } @Test diff --git a/src/test/java/rife/bld/extension/kotlin/CompileOptionsTest.java b/src/test/java/rife/bld/extension/kotlin/CompileOptionsTest.java index 02f9a59..cdabf36 100644 --- a/src/test/java/rife/bld/extension/kotlin/CompileOptionsTest.java +++ b/src/test/java/rife/bld/extension/kotlin/CompileOptionsTest.java @@ -51,6 +51,7 @@ class CompileOptionsTest { var options = new CompileOptions() .apiVersion("11") .argFile(new File("file.txt"), new File("file2.txt")) + .classpath(new File("path1"), new File("path2")) .javaParameters(true) .jvmTarget("11") .includeRuntime(true) @@ -75,6 +76,7 @@ class CompileOptionsTest { var matches = List.of( "-api-version", "11", "@" + localPath("file.txt"), "@" + localPath("file2.txt"), + "-classpath", localPath("path1", "path2"), "-java-parameters", "-jvm-target", "11", "-include-runtime", @@ -115,6 +117,7 @@ class CompileOptionsTest { var advanceOptions = List.of("Xoption1", "Xoption2"); var argFile = List.of(new File("arg1.txt"), new File("arg2.txt")); var classpath = List.of(new File("path1"), new File("path2")); + var jvmOptions = List.of("option1", "option2"); var optIn = List.of("opt1", "opt2"); var options = List.of("-foo", "-bar"); var plugin = List.of("id:name:value", "id2:name2:value2"); @@ -124,6 +127,7 @@ class CompileOptionsTest { .advancedOptions(advanceOptions) .argFile(argFile) .classpath(classpath) + .jvmOptions(jvmOptions) .noStdLib(false) .optIn(optIn) .options(options) @@ -141,6 +145,8 @@ class CompileOptionsTest { .hasSize(argFile.size()).containsAll(argFile); softly.assertThat(op.classpath()).as("classpath") .hasSize(classpath.size()).containsAll(classpath); + softly.assertThat(op.jvmOptions()).as("jvmOptions") + .hasSize(jvmOptions.size()).containsAll(jvmOptions); softly.assertThat(op.optIn()).as("optIn") .hasSize(optIn.size()).containsAll(optIn); softly.assertThat(op.options()).as("options") @@ -208,7 +214,9 @@ class CompileOptionsTest { .advancedOptions("Xoption") .apiVersion("11") .argFile("file") + .classpath("classpath") .expression("expression") + .jvmOptions("option") .includeRuntime(true) .javaParameters(true) .jdkHome("jdkhome") @@ -230,10 +238,6 @@ class CompileOptionsTest { .wError(true) .wExtra(true); - var skipArgs = List.of("-J", "-classpath"); - assertThat(args).as(skipArgs + " not found.").containsAll(skipArgs); - args.removeAll(skipArgs); - try (var softly = new AutoCloseableSoftAssertions()) { for (var p : args) { var found = false; diff --git a/src/test/java/rife/bld/extension/kotlin/JvmOptionsTest.java b/src/test/java/rife/bld/extension/kotlin/JvmOptionsTest.java index 6f8474f..0dcfbef 100644 --- a/src/test/java/rife/bld/extension/kotlin/JvmOptionsTest.java +++ b/src/test/java/rife/bld/extension/kotlin/JvmOptionsTest.java @@ -17,7 +17,6 @@ package rife.bld.extension.kotlin; import org.junit.jupiter.api.Test; -import rife.bld.extension.CompileKotlinOperation; import java.util.List; @@ -26,12 +25,15 @@ import static org.assertj.core.api.Assertions.assertThat; @SuppressWarnings("PMD.AvoidDuplicateLiterals") class JvmOptionsTest { @Test - void testop() { - var op = new CompileKotlinOperation().jvmOptions(new JvmOptions().enableNativeAccess(JvmOptions.ALL_UNNAMED)); - assertThat(op.jvmOptions()).as(JvmOptions.ALL_UNNAMED).containsExactly("--enable-native-access=ALL-UNNAMED"); + void testCompileOptions() { + var compileOptions = new CompileOptions().jvmOptions(new JvmOptions().enableNativeAccess(JvmOptions.ALL_UNNAMED)); + assertThat(compileOptions.jvmOptions()).as(JvmOptions.ALL_UNNAMED) + .containsExactly("--enable-native-access=ALL-UNNAMED"); + assertThat(compileOptions.args()).as("args()").containsExactly("-J--enable-native-access=ALL-UNNAMED"); - op = new CompileKotlinOperation().jvmOptions(new JvmOptions().enableNativeAccess("m1", "m2")); - assertThat(op.jvmOptions()).as("m1,m2").containsExactly("--enable-native-access=m1,m2"); + compileOptions = new CompileOptions().jvmOptions(new JvmOptions().enableNativeAccess("m1", "m2")); + assertThat(compileOptions.jvmOptions()).as("m1,m2").containsExactly("--enable-native-access=m1,m2"); + assertThat(compileOptions.args()).as("args(m1,m2)").containsExactly("-J--enable-native-access=m1,m2"); } @Test @@ -60,19 +62,26 @@ class JvmOptionsTest { @Test void testJvmOptions() { - var op = new CompileKotlinOperation().jvmOptions("option1", "option2"); - assertThat(op.jvmOptions()).as("option1,option2").containsExactly("option1", "option2"); + var compileOptions = new CompileOptions().jvmOptions("option1", "option2"); + assertThat(compileOptions.jvmOptions()).as("option1,option2").containsExactly("option1", "option2"); + assertThat(compileOptions.args()).as("args()").containsExactly("-Joption1", "-Joption2"); - op = new CompileKotlinOperation().jvmOptions(List.of("option1", "option2")); - assertThat(op.jvmOptions()).as("List.of(option1,option2)").containsExactly("option1", "option2"); + compileOptions = new CompileOptions().jvmOptions(List.of("option1", "option2")); + assertThat(compileOptions.jvmOptions()).as("List.of(option1,option2)").containsExactly("option1", "option2"); + assertThat(compileOptions.args()).as("args(list)").containsExactly("-Joption1", "-Joption2"); - op = op.jvmOptions(new JvmOptions().enableNativeAccess(JvmOptions.ALL_UNNAMED)); - assertThat(op.jvmOptions()).as("List.of(option1,option2,ALL_UNNAMED)") + compileOptions = compileOptions.jvmOptions(new JvmOptions().enableNativeAccess(JvmOptions.ALL_UNNAMED)); + assertThat(compileOptions.jvmOptions()).as("List.of(option1,option2,ALL_UNNAMED)") .containsExactly("option1", "option2", "--enable-native-access=ALL-UNNAMED"); + assertThat(compileOptions.args()).as("args(option1,option2,ALL_UNNAMED)") + .containsExactly("-Joption1", "-Joption2", "-J--enable-native-access=ALL-UNNAMED"); - op = op.jvmOptions(new JvmOptions().illegalNativeAccess(JvmOptions.NativeAccess.ALLOW)); - assertThat(op.jvmOptions()).as("allow") + compileOptions = compileOptions.jvmOptions(new JvmOptions().illegalNativeAccess(JvmOptions.NativeAccess.ALLOW)); + assertThat(compileOptions.jvmOptions()).as("allow") .containsExactly("option1", "option2", "--enable-native-access=ALL-UNNAMED", "--illegal-native-access=allow"); + assertThat(compileOptions.args()).as("args(option1,option2,ALL_UNNAMED,allow)") + .containsExactly("-Joption1", "-Joption2", "-J--enable-native-access=ALL-UNNAMED", + "-J--illegal-native-access=allow"); } }