Compare commits

..

No commits in common. "b0d6a3ac3b63c769c4bd9be1036302056306ccaf" and "3a012bf012fc97dcfdfd28dd0e194aeb0c4db50d" have entirely different histories.

6 changed files with 105 additions and 124 deletions

View file

@ -60,17 +60,14 @@ public class ExampleBuild extends Project {
@BuildCommand(summary = "Compiles the Kotlin project") @BuildCommand(summary = "Compiles the Kotlin project")
@Override @Override
public void compile() throws Exception { 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 // 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") // .kotlinHome("path/to/kotlin")
// .kotlinc("path/to/kotlinc") // .kotlinc("path/to/kotlinc")
.compileOptions(new CompileOptions().verbose(true)) .compileOptions(options)
.fromProject(this); .fromProject(this)
.execute();
if (!CompileKotlinOperation.isWindows()) {
op.jvmOptions().enableNativeAccess(JvmOptions.ALL_UNNAMED);
}
op.execute();
} }
} }

View file

@ -19,14 +19,12 @@ package rife.bld.extension;
import rife.bld.BaseProject; import rife.bld.BaseProject;
import rife.bld.extension.kotlin.CompileOptions; import rife.bld.extension.kotlin.CompileOptions;
import rife.bld.extension.kotlin.CompilerPlugin; import rife.bld.extension.kotlin.CompilerPlugin;
import rife.bld.extension.kotlin.JvmOptions;
import rife.bld.operations.AbstractOperation; import rife.bld.operations.AbstractOperation;
import rife.bld.operations.exceptions.ExitStatusException; import rife.bld.operations.exceptions.ExitStatusException;
import rife.tools.FileUtils; import rife.tools.FileUtils;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.*; import java.util.*;
import java.util.logging.Level; import java.util.logging.Level;
@ -45,7 +43,6 @@ public class CompileKotlinOperation extends AbstractOperation<CompileKotlinOpera
private static final String KOTLINC_EXECUTABLE = "kotlinc" + (isWindows() ? ".bat" : ""); private static final String KOTLINC_EXECUTABLE = "kotlinc" + (isWindows() ? ".bat" : "");
private final Collection<String> compileMainClasspath_ = new ArrayList<>(); private final Collection<String> compileMainClasspath_ = new ArrayList<>();
private final Collection<String> compileTestClasspath_ = new ArrayList<>(); private final Collection<String> compileTestClasspath_ = new ArrayList<>();
private final JvmOptions jvmOptions_ = new JvmOptions();
private final Collection<File> mainSourceDirectories_ = new ArrayList<>(); private final Collection<File> mainSourceDirectories_ = new ArrayList<>();
private final Collection<File> mainSourceFiles_ = new ArrayList<>(); private final Collection<File> mainSourceFiles_ = new ArrayList<>();
private final Collection<String> plugins_ = new ArrayList<>(); private final Collection<String> plugins_ = new ArrayList<>();
@ -320,17 +317,6 @@ public class CompileKotlinOperation extends AbstractOperation<CompileKotlinOpera
return buildTestDirectory_; return buildTestDirectory_;
} }
private String cleanPath(File path) {
return cleanPath(path.getAbsolutePath());
}
private String cleanPath(String path) {
if (isWindows()) {
return path.replaceAll("\\\\", "\\\\\\\\");
}
return path;
}
/** /**
* Provides entries for the main compilation classpath. * Provides entries for the main compilation classpath.
* *
@ -470,12 +456,6 @@ public class CompileKotlinOperation extends AbstractOperation<CompileKotlinOpera
protected void executeBuildSources(Collection<String> classpath, Collection<File> sources, File destination, protected void executeBuildSources(Collection<String> classpath, Collection<File> sources, File destination,
File friendPaths) File friendPaths)
throws ExitStatusException { throws ExitStatusException {
var cp = new ArrayList<String>();
if (classpath != null && !classpath.isEmpty()) {
cp.addAll(classpath);
}
if (sources.isEmpty()) { if (sources.isEmpty()) {
if (!silent() && LOGGER.isLoggable(Level.WARNING)) { if (!silent() && LOGGER.isLoggable(Level.WARNING)) {
LOGGER.warning("Nothing to compile."); LOGGER.warning("Nothing to compile.");
@ -488,75 +468,56 @@ public class CompileKotlinOperation extends AbstractOperation<CompileKotlinOpera
throw new ExitStatusException(ExitStatusException.EXIT_FAILURE); throw new ExitStatusException(ExitStatusException.EXIT_FAILURE);
} }
var command = new ArrayList<String>();
var args = new ArrayList<String>(); var args = new ArrayList<String>();
// kotlinc // kotlinc
if (kotlinc_ != null) { if (kotlinc_ != null) {
command.add(kotlinc_.getAbsolutePath()); args.add(kotlinc_.getAbsolutePath());
} else if (kotlinHome_ != null) { } else if (kotlinHome_ != null) {
command.add(Objects.requireNonNullElseGet(findKotlincInDir(kotlinHome_.getAbsolutePath()), args.add(Objects.requireNonNullElseGet(findKotlincInDir(kotlinHome_.getAbsolutePath()),
CompileKotlinOperation::findKotlincPath)); CompileKotlinOperation::findKotlincPath));
} else { } else {
command.add(findKotlincPath(silent())); args.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());
} }
// classpath // classpath
if (!cp.isEmpty()) { if (classpath != null && !classpath.isEmpty()) {
args.add("-cp"); args.add("-cp");
args.add('"' + FileUtils.joinPaths(cp.stream().map(this::cleanPath).toList()) + '"'); args.add(FileUtils.joinPaths(classpath.stream().toList()));
} }
// destination // destination
args.add("-d"); args.add("-d");
args.add('"' + cleanPath(destination) + '"'); args.add(destination.getAbsolutePath());
// friend-path // friend-path
if (friendPaths != null && friendPaths.exists()) { 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 // plugins
if (!plugins_.isEmpty()) { if (!plugins_.isEmpty()) {
plugins_.forEach(p -> args.add("-Xplugin=\"" + cleanPath(p) + '"')); plugins_.forEach(p -> args.add("-Xplugin=" + p));
} }
// sources // 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()) { if (LOGGER.isLoggable(Level.FINE) && !silent()) {
LOGGER.fine(String.join(" ", command) + " " + argsLine); LOGGER.fine(String.join(" ", args));
} }
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(); var pb = new ProcessBuilder();
pb.inheritIO(); pb.inheritIO();
pb.command(command); pb.command(args);
pb.directory(workDir_); pb.directory(workDir_);
try {
var proc = pb.start(); var proc = pb.start();
proc.waitFor(); proc.waitFor();
ExitStatusException.throwOnFailure(proc.exitValue()); ExitStatusException.throwOnFailure(proc.exitValue());
@ -646,36 +607,6 @@ public class CompileKotlinOperation extends AbstractOperation<CompileKotlinOpera
return op; return op;
} }
/**
* 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 CompileKotlinOperation jvmOptions(Collection<String> 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}. * Provides the Kotlin home directory, if it differs from the default {@code KOTLIN_HOME}.
* *

View file

@ -23,6 +23,7 @@ import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import static rife.bld.extension.CompileKotlinOperation.isNotBlank; import static rife.bld.extension.CompileKotlinOperation.isNotBlank;
@ -36,6 +37,7 @@ public class CompileOptions {
private final Collection<String> advancedOptions_ = new ArrayList<>(); private final Collection<String> advancedOptions_ = new ArrayList<>();
private final Collection<File> argFile_ = new ArrayList<>(); private final Collection<File> argFile_ = new ArrayList<>();
private final Collection<File> classpath_ = new ArrayList<>(); private final Collection<File> classpath_ = new ArrayList<>();
private final JvmOptions jvmOptions_ = new JvmOptions();
private final Collection<String> optIn_ = new ArrayList<>(); private final Collection<String> optIn_ = new ArrayList<>();
private final Collection<String> options_ = new ArrayList<>(); private final Collection<String> options_ = new ArrayList<>();
private final Collection<String> plugin_ = new ArrayList<>(); private final Collection<String> plugin_ = new ArrayList<>();
@ -110,6 +112,7 @@ public class CompileOptions {
return this; return this;
} }
/** /**
* Allow using declarations only from the specified version of Kotlin bundled libraries. * 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())); 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 // expression
if (isNotBlank(expression_)) { if (isNotBlank(expression_)) {
args.add("-expression"); args.add("-expression");
@ -284,6 +293,11 @@ public class CompileOptions {
args.add("-Xjdk-release=" + jdkRelease_); args.add("-Xjdk-release=" + jdkRelease_);
} }
// JVM options
if (!jvmOptions_.isEmpty()) {
jvmOptions_.forEach(s -> args.add("-J" + s));
}
// kotlin-home // kotlin-home
if (kotlinHome_ != null) { if (kotlinHome_ != null) {
args.add("-kotlin-home"); args.add("-kotlin-home");
@ -690,6 +704,36 @@ public class CompileOptions {
return jdkRelease(String.valueOf(version)); 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<String> 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. * Specify the target version of the generated JVM bytecode.
* *

View file

@ -182,14 +182,10 @@ class CompileKotlinOperationTest {
op.compileOptions().verbose(true); op.compileOptions().verbose(true);
op.compileOptions().jdkRelease("17"); op.compileOptions().jdkRelease("17");
op.compileOptions().jvmOptions().enableNativeAccess(JvmOptions.ALL_UNNAMED);
if (!CompileKotlinOperation.isWindows()) {
op.jvmOptions().enableNativeAccess(JvmOptions.ALL_UNNAMED);
assertThat(op.jvmOptions()).containsExactly("--enable-native-access=ALL-UNNAMED");
}
var args = op.compileOptions().args(); 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); assertThat(args).as(args + " == " + matches).isEqualTo(matches);
op.execute(); op.execute();
@ -224,8 +220,8 @@ class CompileKotlinOperationTest {
var examples = new File("examples"); var examples = new File("examples");
var op = new CompileKotlinOperation().fromProject( var op = new CompileKotlinOperation().fromProject(
new BaseProjectBlueprint(examples, "com.example", "examples", "examples")); new BaseProjectBlueprint(examples, "com.example", "examples", "examples"));
assertThat(op.mainSourceDirectories()).containsExactly(new File(examples, "src/main/kotlin")); assertThat(op.mainSourceDirectories()).contains(new File(examples, "src/main/kotlin"));
assertThat(op.testSourceDirectories()).containsExactly(new File(examples, "src/test/kotlin")); assertThat(op.testSourceDirectories()).contains(new File(examples, "src/test/kotlin"));
} }
@Test @Test

View file

@ -51,6 +51,7 @@ class CompileOptionsTest {
var options = new CompileOptions() var options = new CompileOptions()
.apiVersion("11") .apiVersion("11")
.argFile(new File("file.txt"), new File("file2.txt")) .argFile(new File("file.txt"), new File("file2.txt"))
.classpath(new File("path1"), new File("path2"))
.javaParameters(true) .javaParameters(true)
.jvmTarget("11") .jvmTarget("11")
.includeRuntime(true) .includeRuntime(true)
@ -75,6 +76,7 @@ class CompileOptionsTest {
var matches = List.of( var matches = List.of(
"-api-version", "11", "-api-version", "11",
"@" + localPath("file.txt"), "@" + localPath("file2.txt"), "@" + localPath("file.txt"), "@" + localPath("file2.txt"),
"-classpath", localPath("path1", "path2"),
"-java-parameters", "-java-parameters",
"-jvm-target", "11", "-jvm-target", "11",
"-include-runtime", "-include-runtime",
@ -115,6 +117,7 @@ class CompileOptionsTest {
var advanceOptions = List.of("Xoption1", "Xoption2"); var advanceOptions = List.of("Xoption1", "Xoption2");
var argFile = List.of(new File("arg1.txt"), new File("arg2.txt")); var argFile = List.of(new File("arg1.txt"), new File("arg2.txt"));
var classpath = List.of(new File("path1"), new File("path2")); var classpath = List.of(new File("path1"), new File("path2"));
var jvmOptions = List.of("option1", "option2");
var optIn = List.of("opt1", "opt2"); var optIn = List.of("opt1", "opt2");
var options = List.of("-foo", "-bar"); var options = List.of("-foo", "-bar");
var plugin = List.of("id:name:value", "id2:name2:value2"); var plugin = List.of("id:name:value", "id2:name2:value2");
@ -124,6 +127,7 @@ class CompileOptionsTest {
.advancedOptions(advanceOptions) .advancedOptions(advanceOptions)
.argFile(argFile) .argFile(argFile)
.classpath(classpath) .classpath(classpath)
.jvmOptions(jvmOptions)
.noStdLib(false) .noStdLib(false)
.optIn(optIn) .optIn(optIn)
.options(options) .options(options)
@ -141,6 +145,8 @@ class CompileOptionsTest {
.hasSize(argFile.size()).containsAll(argFile); .hasSize(argFile.size()).containsAll(argFile);
softly.assertThat(op.classpath()).as("classpath") softly.assertThat(op.classpath()).as("classpath")
.hasSize(classpath.size()).containsAll(classpath); .hasSize(classpath.size()).containsAll(classpath);
softly.assertThat(op.jvmOptions()).as("jvmOptions")
.hasSize(jvmOptions.size()).containsAll(jvmOptions);
softly.assertThat(op.optIn()).as("optIn") softly.assertThat(op.optIn()).as("optIn")
.hasSize(optIn.size()).containsAll(optIn); .hasSize(optIn.size()).containsAll(optIn);
softly.assertThat(op.options()).as("options") softly.assertThat(op.options()).as("options")
@ -208,7 +214,9 @@ class CompileOptionsTest {
.advancedOptions("Xoption") .advancedOptions("Xoption")
.apiVersion("11") .apiVersion("11")
.argFile("file") .argFile("file")
.classpath("classpath")
.expression("expression") .expression("expression")
.jvmOptions("option")
.includeRuntime(true) .includeRuntime(true)
.javaParameters(true) .javaParameters(true)
.jdkHome("jdkhome") .jdkHome("jdkhome")
@ -230,10 +238,6 @@ class CompileOptionsTest {
.wError(true) .wError(true)
.wExtra(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()) { try (var softly = new AutoCloseableSoftAssertions()) {
for (var p : args) { for (var p : args) {
var found = false; var found = false;

View file

@ -17,7 +17,6 @@
package rife.bld.extension.kotlin; package rife.bld.extension.kotlin;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import rife.bld.extension.CompileKotlinOperation;
import java.util.List; import java.util.List;
@ -26,12 +25,15 @@ import static org.assertj.core.api.Assertions.assertThat;
@SuppressWarnings("PMD.AvoidDuplicateLiterals") @SuppressWarnings("PMD.AvoidDuplicateLiterals")
class JvmOptionsTest { class JvmOptionsTest {
@Test @Test
void testop() { void testCompileOptions() {
var op = new CompileKotlinOperation().jvmOptions(new JvmOptions().enableNativeAccess(JvmOptions.ALL_UNNAMED)); var compileOptions = new CompileOptions().jvmOptions(new JvmOptions().enableNativeAccess(JvmOptions.ALL_UNNAMED));
assertThat(op.jvmOptions()).as(JvmOptions.ALL_UNNAMED).containsExactly("--enable-native-access=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")); compileOptions = new CompileOptions().jvmOptions(new JvmOptions().enableNativeAccess("m1", "m2"));
assertThat(op.jvmOptions()).as("m1,m2").containsExactly("--enable-native-access=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 @Test
@ -60,19 +62,26 @@ class JvmOptionsTest {
@Test @Test
void testJvmOptions() { void testJvmOptions() {
var op = new CompileKotlinOperation().jvmOptions("option1", "option2"); var compileOptions = new CompileOptions().jvmOptions("option1", "option2");
assertThat(op.jvmOptions()).as("option1,option2").containsExactly("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")); compileOptions = new CompileOptions().jvmOptions(List.of("option1", "option2"));
assertThat(op.jvmOptions()).as("List.of(option1,option2)").containsExactly("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)); compileOptions = compileOptions.jvmOptions(new JvmOptions().enableNativeAccess(JvmOptions.ALL_UNNAMED));
assertThat(op.jvmOptions()).as("List.of(option1,option2,ALL_UNNAMED)") assertThat(compileOptions.jvmOptions()).as("List.of(option1,option2,ALL_UNNAMED)")
.containsExactly("option1", "option2", "--enable-native-access=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)); compileOptions = compileOptions.jvmOptions(new JvmOptions().illegalNativeAccess(JvmOptions.NativeAccess.ALLOW));
assertThat(op.jvmOptions()).as("allow") assertThat(compileOptions.jvmOptions()).as("allow")
.containsExactly("option1", "option2", "--enable-native-access=ALL-UNNAMED", .containsExactly("option1", "option2", "--enable-native-access=ALL-UNNAMED",
"--illegal-native-access=allow"); "--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");
} }
} }