Pass arguments to kotlinc via @argfile

This commit is contained in:
Erik C. Thauvin 2025-03-23 02:30:17 -07:00
parent 125e9f7327
commit b0d6a3ac3b
Signed by: erik
GPG key ID: 776702A6A2DA330E
4 changed files with 59 additions and 33 deletions

View file

@ -26,6 +26,7 @@ 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;
@ -319,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.
*
@ -458,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.");
@ -470,60 +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());

View file

@ -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;
@ -111,7 +110,6 @@ public class CompileOptions {
return this;
}
/**
* Allow using declarations only from the specified version of Kotlin bundled libraries.
*
@ -253,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");

View file

@ -224,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

View file

@ -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",
@ -210,7 +208,6 @@ class CompileOptionsTest {
.advancedOptions("Xoption")
.apiVersion("11")
.argFile("file")
.classpath("classpath")
.expression("expression")
.includeRuntime(true)
.javaParameters(true)
@ -233,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;