Compare commits
2 commits
3a012bf012
...
b0d6a3ac3b
Author | SHA1 | Date | |
---|---|---|---|
b0d6a3ac3b | |||
125e9f7327 |
6 changed files with 124 additions and 105 deletions
|
@ -60,14 +60,17 @@ 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
|
||||
new CompileKotlinOperation()
|
||||
var op = new CompileKotlinOperation()
|
||||
// .kotlinHome("path/to/kotlin")
|
||||
// .kotlinc("path/to/kotlinc")
|
||||
.compileOptions(options)
|
||||
.fromProject(this)
|
||||
.execute();
|
||||
.compileOptions(new CompileOptions().verbose(true))
|
||||
.fromProject(this);
|
||||
|
||||
if (!CompileKotlinOperation.isWindows()) {
|
||||
op.jvmOptions().enableNativeAccess(JvmOptions.ALL_UNNAMED);
|
||||
}
|
||||
|
||||
op.execute();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,12 +19,14 @@ 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;
|
||||
|
@ -43,6 +45,7 @@ public class CompileKotlinOperation extends AbstractOperation<CompileKotlinOpera
|
|||
private static final String KOTLINC_EXECUTABLE = "kotlinc" + (isWindows() ? ".bat" : "");
|
||||
private final Collection<String> compileMainClasspath_ = 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> mainSourceFiles_ = new ArrayList<>();
|
||||
private final Collection<String> plugins_ = new ArrayList<>();
|
||||
|
@ -317,6 +320,17 @@ public class CompileKotlinOperation extends AbstractOperation<CompileKotlinOpera
|
|||
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.
|
||||
*
|
||||
|
@ -456,6 +470,12 @@ public class CompileKotlinOperation extends AbstractOperation<CompileKotlinOpera
|
|||
protected void executeBuildSources(Collection<String> classpath, Collection<File> sources, File destination,
|
||||
File friendPaths)
|
||||
throws ExitStatusException {
|
||||
|
||||
var cp = new ArrayList<String>();
|
||||
if (classpath != null && !classpath.isEmpty()) {
|
||||
cp.addAll(classpath);
|
||||
}
|
||||
|
||||
if (sources.isEmpty()) {
|
||||
if (!silent() && LOGGER.isLoggable(Level.WARNING)) {
|
||||
LOGGER.warning("Nothing to compile.");
|
||||
|
@ -468,56 +488,75 @@ public class CompileKotlinOperation extends AbstractOperation<CompileKotlinOpera
|
|||
throw new ExitStatusException(ExitStatusException.EXIT_FAILURE);
|
||||
}
|
||||
|
||||
var command = new ArrayList<String>();
|
||||
var args = new ArrayList<String>();
|
||||
|
||||
// kotlinc
|
||||
if (kotlinc_ != null) {
|
||||
args.add(kotlinc_.getAbsolutePath());
|
||||
command.add(kotlinc_.getAbsolutePath());
|
||||
} else if (kotlinHome_ != null) {
|
||||
args.add(Objects.requireNonNullElseGet(findKotlincInDir(kotlinHome_.getAbsolutePath()),
|
||||
command.add(Objects.requireNonNullElseGet(findKotlincInDir(kotlinHome_.getAbsolutePath()),
|
||||
CompileKotlinOperation::findKotlincPath));
|
||||
} else {
|
||||
args.add(findKotlincPath(silent()));
|
||||
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());
|
||||
}
|
||||
|
||||
// classpath
|
||||
if (classpath != null && !classpath.isEmpty()) {
|
||||
if (!cp.isEmpty()) {
|
||||
args.add("-cp");
|
||||
args.add(FileUtils.joinPaths(classpath.stream().toList()));
|
||||
args.add('"' + FileUtils.joinPaths(cp.stream().map(this::cleanPath).toList()) + '"');
|
||||
}
|
||||
|
||||
// destination
|
||||
args.add("-d");
|
||||
args.add(destination.getAbsolutePath());
|
||||
args.add('"' + cleanPath(destination) + '"');
|
||||
|
||||
// friend-path
|
||||
if (friendPaths != null && friendPaths.exists()) {
|
||||
args.add("-Xfriend-paths=" + friendPaths.getAbsolutePath());
|
||||
}
|
||||
|
||||
// options
|
||||
if (compileOptions_ != null) {
|
||||
args.addAll(compileOptions_.args());
|
||||
args.add("-Xfriend-paths=\"" + cleanPath(friendPaths) + '"');
|
||||
}
|
||||
|
||||
// plugins
|
||||
if (!plugins_.isEmpty()) {
|
||||
plugins_.forEach(p -> args.add("-Xplugin=" + p));
|
||||
plugins_.forEach(p -> args.add("-Xplugin=\"" + cleanPath(p) + '"'));
|
||||
}
|
||||
|
||||
// sources
|
||||
sources.forEach(f -> args.add(f.getAbsolutePath()));
|
||||
sources.forEach(f -> args.add('"' + cleanPath(f) + '"'));
|
||||
|
||||
var argsLine = String.join(" ", args);
|
||||
|
||||
// log the command line
|
||||
if (LOGGER.isLoggable(Level.FINE) && !silent()) {
|
||||
LOGGER.fine(String.join(" ", args));
|
||||
LOGGER.fine(String.join(" ", command) + " " + argsLine);
|
||||
}
|
||||
|
||||
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());
|
||||
|
@ -607,6 +646,36 @@ public class CompileKotlinOperation extends AbstractOperation<CompileKotlinOpera
|
|||
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}.
|
||||
*
|
||||
|
|
|
@ -23,7 +23,6 @@ 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;
|
||||
|
||||
|
@ -37,7 +36,6 @@ public class CompileOptions {
|
|||
private final Collection<String> advancedOptions_ = new ArrayList<>();
|
||||
private final Collection<File> argFile_ = 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> options_ = new ArrayList<>();
|
||||
private final Collection<String> plugin_ = new ArrayList<>();
|
||||
|
@ -112,7 +110,6 @@ public class CompileOptions {
|
|||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Allow using declarations only from the specified version of Kotlin bundled libraries.
|
||||
*
|
||||
|
@ -254,12 +251,6 @@ 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");
|
||||
|
@ -293,11 +284,6 @@ 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");
|
||||
|
@ -704,36 +690,6 @@ 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<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.
|
||||
*
|
||||
|
|
|
@ -182,10 +182,14 @@ class CompileKotlinOperationTest {
|
|||
|
||||
op.compileOptions().verbose(true);
|
||||
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 matches = List.of("-Xjdk-release=17", "-J--enable-native-access=ALL-UNNAMED", "-no-stdlib", "-verbose");
|
||||
var matches = List.of("-Xjdk-release=17", "-no-stdlib", "-verbose");
|
||||
assertThat(args).as(args + " == " + matches).isEqualTo(matches);
|
||||
|
||||
op.execute();
|
||||
|
@ -220,8 +224,8 @@ class CompileKotlinOperationTest {
|
|||
var examples = new File("examples");
|
||||
var op = new CompileKotlinOperation().fromProject(
|
||||
new BaseProjectBlueprint(examples, "com.example", "examples", "examples"));
|
||||
assertThat(op.mainSourceDirectories()).contains(new File(examples, "src/main/kotlin"));
|
||||
assertThat(op.testSourceDirectories()).contains(new File(examples, "src/test/kotlin"));
|
||||
assertThat(op.mainSourceDirectories()).containsExactly(new File(examples, "src/main/kotlin"));
|
||||
assertThat(op.testSourceDirectories()).containsExactly(new File(examples, "src/test/kotlin"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -51,7 +51,6 @@ 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)
|
||||
|
@ -76,7 +75,6 @@ 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",
|
||||
|
@ -117,7 +115,6 @@ 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");
|
||||
|
@ -127,7 +124,6 @@ class CompileOptionsTest {
|
|||
.advancedOptions(advanceOptions)
|
||||
.argFile(argFile)
|
||||
.classpath(classpath)
|
||||
.jvmOptions(jvmOptions)
|
||||
.noStdLib(false)
|
||||
.optIn(optIn)
|
||||
.options(options)
|
||||
|
@ -145,8 +141,6 @@ 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")
|
||||
|
@ -214,9 +208,7 @@ class CompileOptionsTest {
|
|||
.advancedOptions("Xoption")
|
||||
.apiVersion("11")
|
||||
.argFile("file")
|
||||
.classpath("classpath")
|
||||
.expression("expression")
|
||||
.jvmOptions("option")
|
||||
.includeRuntime(true)
|
||||
.javaParameters(true)
|
||||
.jdkHome("jdkhome")
|
||||
|
@ -238,6 +230,10 @@ 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;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package rife.bld.extension.kotlin;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import rife.bld.extension.CompileKotlinOperation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -25,15 +26,12 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
@SuppressWarnings("PMD.AvoidDuplicateLiterals")
|
||||
class JvmOptionsTest {
|
||||
@Test
|
||||
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");
|
||||
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");
|
||||
|
||||
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");
|
||||
op = new CompileKotlinOperation().jvmOptions(new JvmOptions().enableNativeAccess("m1", "m2"));
|
||||
assertThat(op.jvmOptions()).as("m1,m2").containsExactly("--enable-native-access=m1,m2");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -62,26 +60,19 @@ class JvmOptionsTest {
|
|||
|
||||
@Test
|
||||
void testJvmOptions() {
|
||||
var compileOptions = new CompileOptions().jvmOptions("option1", "option2");
|
||||
assertThat(compileOptions.jvmOptions()).as("option1,option2").containsExactly("option1", "option2");
|
||||
assertThat(compileOptions.args()).as("args()").containsExactly("-Joption1", "-Joption2");
|
||||
var op = new CompileKotlinOperation().jvmOptions("option1", "option2");
|
||||
assertThat(op.jvmOptions()).as("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 = new CompileKotlinOperation().jvmOptions(List.of("option1", "option2"));
|
||||
assertThat(op.jvmOptions()).as("List.of(option1,option2)").containsExactly("option1", "option2");
|
||||
|
||||
compileOptions = compileOptions.jvmOptions(new JvmOptions().enableNativeAccess(JvmOptions.ALL_UNNAMED));
|
||||
assertThat(compileOptions.jvmOptions()).as("List.of(option1,option2,ALL_UNNAMED)")
|
||||
op = op.jvmOptions(new JvmOptions().enableNativeAccess(JvmOptions.ALL_UNNAMED));
|
||||
assertThat(op.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");
|
||||
|
||||
compileOptions = compileOptions.jvmOptions(new JvmOptions().illegalNativeAccess(JvmOptions.NativeAccess.ALLOW));
|
||||
assertThat(compileOptions.jvmOptions()).as("allow")
|
||||
op = op.jvmOptions(new JvmOptions().illegalNativeAccess(JvmOptions.NativeAccess.ALLOW));
|
||||
assertThat(op.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");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue