diff --git a/.github/workflows/bld.yml b/.github/workflows/bld.yml index 436605a..cfed82f 100644 --- a/.github/workflows/bld.yml +++ b/.github/workflows/bld.yml @@ -1,18 +1,16 @@ name: bld-ci -on: [push, pull_request, workflow_dispatch] - -env: - KOTLIN_HOME: /usr/share/kotlinc +on: [ push, pull_request, workflow_dispatch ] jobs: build-bld-project: - runs-on: ubuntu-latest - strategy: matrix: - java-version: [17, 21, 23] - kotlin-version: [1.9.24, 2.0.21, 2.1.0] + java-version: [ 17, 21, 24 ] + kotlin-version: [ 1.9.25, 2.0.21, 2.1.20 ] + os: [ ubuntu-latest, windows-latest, macos-latest ] + + runs-on: ${{ matrix.os }} steps: - name: Checkout source repository @@ -38,4 +36,4 @@ jobs: run: ./bld download - name: Run tests - run: ./bld compile test + run: ./bld compile test \ No newline at end of file diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 1e9f25d..e864e62 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -47,11 +47,11 @@ jobs: uses: actions/configure-pages@v3 - name: Upload artifact - uses: actions/upload-pages-artifact@v1 + uses: actions/upload-pages-artifact@v3 with: # Upload generated Javadocs repository path: "build/javadoc/" - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v1 + uses: actions/deploy-pages@v4 diff --git a/.idea/libraries/bld.xml b/.idea/libraries/bld.xml index defcfad..f9b1d1d 100644 --- a/.idea/libraries/bld.xml +++ b/.idea/libraries/bld.xml @@ -2,12 +2,12 @@ - + - + diff --git a/.idea/misc.xml b/.idea/misc.xml index ea8d1e3..593e427 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -9,6 +9,8 @@ + + diff --git a/.idea/runConfigurations/Run Tests.xml b/.idea/runConfigurations/Run Tests.xml deleted file mode 100644 index 057a90e..0000000 --- a/.idea/runConfigurations/Run Tests.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index a3f4fd0..ba429d0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,7 +9,7 @@ ], "java.configuration.updateBuildConfiguration": "automatic", "java.project.referencedLibraries": [ - "${HOME}/.bld/dist/bld-2.2.0.jar", + "${HOME}/.bld/dist/bld-2.2.1.jar", "lib/**/*.jar" ] } diff --git a/README.md b/README.md index 72c9d31..0c15334 100644 --- a/README.md +++ b/README.md @@ -2,19 +2,23 @@ [![License](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![Java](https://img.shields.io/badge/java-17%2B-blue)](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html) -[![Kotlin](https://img.shields.io/badge/kotlin-1.9.24%2B-7f52ff.svg)](https://kotlinlang.org) -[![bld](https://img.shields.io/badge/2.2.0-FA9052?label=bld&labelColor=2392FF)](https://rife2.com/bld) +[![Kotlin](https://img.shields.io/badge/kotlin-1.9.25%2B-7f52ff.svg)](https://kotlinlang.org) +[![bld](https://img.shields.io/badge/2.2.1-FA9052?label=bld&labelColor=2392FF)](https://rife2.com/bld) [![Release](https://flat.badgen.net/maven/v/metadata-url/repo.rife2.com/releases/com/uwyn/rife2/bld-kotlin/maven-metadata.xml?color=blue)](https://repo.rife2.com/#/releases/com/uwyn/rife2/bld-kotlin) [![Snapshot](https://flat.badgen.net/maven/v/metadata-url/repo.rife2.com/snapshots/com/uwyn/rife2/bld-kotlin/maven-metadata.xml?label=snapshot)](https://repo.rife2.com/#/snapshots/com/uwyn/rife2/bld-kotlin) [![GitHub CI](https://github.com/rife2/bld-kotlin/actions/workflows/bld.yml/badge.svg)](https://github.com/rife2/bld-kotlin/actions/workflows/bld.yml) -To install, please refer to the [extensions](https://github.com/rife2/bld/wiki/Extensions) -and [support](https://github.com/rife2/bld/wiki/Kotlin-Support) -documentation. +To install the latest version, add the following to the `lib/bld/bld-wrapper.properties` file: + +```properties +bld.extension-kotlin=com.uwyn.rife2:bld-kotlin +``` + +For more information, please refer to the [extensions](https://github.com/rife2/bld/wiki/Extensions) and [support](https://github.com/rife2/bld/wiki/Kotlin-Support) documentation. ## Compile Kotlin Source Code -To compile the source code located in `src/main/kotlin` and `src/test/kotlin` from the current project: +To compile the source code located in `src/main/kotlin` and `src/test/kotlin` from the current project add the following to the build file: ```java @@ -40,6 +44,15 @@ for all available configuration options. Please make sure the Kotlin compiler is [installed](https://kotlinlang.org/docs/command-line.html#install-the-compiler). +The extension will look in common locations such as: + + - `KOTLIN_HOME` + - `PATH` + - [SDKMAN!](https://sdkman.io/) + - [Homebrew](https://brew.sh/) + - [JetBrains Toolbox](https://www.jetbrains.com/toolbox-app/) (IntelliJ IDEA, Android Studio) + - etc. + You can also manually configure the Kotlin home location as follows: ```java @@ -66,7 +79,7 @@ public void compile() throws Exception { } ``` -While older version of Kotlin are likely working with the extension, only version 1.9.24 or higher are officially +While older version of Kotlin are likely working with the extension, only version 1.9.25 or higher are officially supported. ## Template Project diff --git a/examples/.idea/libraries/bld.xml b/examples/.idea/libraries/bld.xml index 553c281..153a060 100644 --- a/examples/.idea/libraries/bld.xml +++ b/examples/.idea/libraries/bld.xml @@ -2,12 +2,12 @@ - + - + diff --git a/examples/.vscode/settings.json b/examples/.vscode/settings.json index a3f4fd0..ba429d0 100644 --- a/examples/.vscode/settings.json +++ b/examples/.vscode/settings.json @@ -9,7 +9,7 @@ ], "java.configuration.updateBuildConfiguration": "automatic", "java.project.referencedLibraries": [ - "${HOME}/.bld/dist/bld-2.2.0.jar", + "${HOME}/.bld/dist/bld-2.2.1.jar", "lib/**/*.jar" ] } diff --git a/examples/lib/bld/bld-wrapper.jar b/examples/lib/bld/bld-wrapper.jar index dc7bcbd..06cf59e 100644 Binary files a/examples/lib/bld/bld-wrapper.jar and b/examples/lib/bld/bld-wrapper.jar differ diff --git a/examples/lib/bld/bld-wrapper.properties b/examples/lib/bld/bld-wrapper.properties index f24155c..1f1009d 100644 --- a/examples/lib/bld/bld-wrapper.properties +++ b/examples/lib/bld/bld-wrapper.properties @@ -1,7 +1,7 @@ bld.downloadExtensionJavadoc=false bld.downloadExtensionSources=true bld.downloadLocation= -bld.extension-kotlin=com.uwyn.rife2:bld-kotlin:1.0.4 +bld.extension-kotlin=com.uwyn.rife2:bld-kotlin:1.1.0-SNAPSHOT bld.repositories=MAVEN_LOCAL,MAVEN_CENTRAL,RIFE2_SNAPSHOTS,RIFE2_RELEASES bld.sourceDirectories= -bld.version=2.2.0 +bld.version=2.2.1 diff --git a/examples/src/bld/java/com/example/ExampleBuild.java b/examples/src/bld/java/com/example/ExampleBuild.java index ab3fd8f..170c5b5 100644 --- a/examples/src/bld/java/com/example/ExampleBuild.java +++ b/examples/src/bld/java/com/example/ExampleBuild.java @@ -3,6 +3,8 @@ package com.example; import rife.bld.BuildCommand; import rife.bld.Project; import rife.bld.extension.CompileKotlinOperation; +import rife.bld.extension.kotlin.CompileOptions; +import rife.bld.extension.kotlin.JvmOptions; import java.io.File; import java.util.List; @@ -28,13 +30,14 @@ public class ExampleBuild extends Project { repositories = List.of(MAVEN_LOCAL, MAVEN_CENTRAL, RIFE2_RELEASES); - final var kotlin = version(2, 1, 0); + final var kotlin = version(2, 1, 20); scope(compile) .include(dependency("org.jetbrains.kotlin", "kotlin-stdlib", kotlin)); scope(test) .include(dependency("org.jetbrains.kotlin", "kotlin-test-junit5", kotlin)) - .include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 11, 4))) - .include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 11, 4))); + .include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 12, 2))) + .include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 12, 2))) + .include(dependency("org.junit.platform", "junit-platform-launcher", version(1, 12, 2))); // Include the Kotlin source directory when creating or publishing sources Java Archives jarSourcesOperation().sourceDirectories(new File(srcMainDirectory(), "kotlin")); @@ -58,11 +61,11 @@ public class ExampleBuild extends Project { @Override public void compile() throws Exception { // 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") - .fromProject(this); - op.compileOptions().verbose(true); - op.execute(); + .compileOptions(new CompileOptions().verbose(true)) + .fromProject(this) + .execute(); } } diff --git a/lib/bld/bld-wrapper.jar b/lib/bld/bld-wrapper.jar index 21f7c76..d7879eb 100644 Binary files a/lib/bld/bld-wrapper.jar and b/lib/bld/bld-wrapper.jar differ diff --git a/lib/bld/bld-wrapper.properties b/lib/bld/bld-wrapper.properties index a6d0455..d29a55f 100644 --- a/lib/bld/bld-wrapper.properties +++ b/lib/bld/bld-wrapper.properties @@ -3,8 +3,8 @@ bld.downloadExtensionSources=true bld.downloadLocation= bld.javaOptions= bld.javacOptions= -bld.extension-exec=com.uwyn.rife2:bld-exec:1.0.4 -bld.extension-pmd=com.uwyn.rife2:bld-pmd:1.1.10 +bld.extension-exec=com.uwyn.rife2:bld-exec:1.0.5 +bld.extension-pmd=com.uwyn.rife2:bld-pmd:1.2.2 bld.repositories=MAVEN_CENTRAL,MAVEN_LOCAL,RIFE2_SNAPSHOTS,RIFE2_RELEASES bld.sourceDirectories= -bld.version=2.2.0 +bld.version=2.2.1 diff --git a/scripts/checkcliargs.sh b/scripts/checkcliargs.sh index 30c8537..94313ab 100755 --- a/scripts/checkcliargs.sh +++ b/scripts/checkcliargs.sh @@ -4,7 +4,7 @@ new=/tmp/checkcliargs-new old=/tmp/checkcliargs-old kotlinc -h 2>$new -~/.sdkman/candidates/kotlin/2.1.0/bin/kotlinc -h 2>$old +~/.sdkman/candidates/kotlin/2.1.10/bin/kotlinc -h 2>$old code --diff --wait $old $new diff --git a/src/bld/java/rife/bld/extension/CompileKotlinOperationBuild.java b/src/bld/java/rife/bld/extension/CompileKotlinOperationBuild.java index e12baeb..53e84c7 100644 --- a/src/bld/java/rife/bld/extension/CompileKotlinOperationBuild.java +++ b/src/bld/java/rife/bld/extension/CompileKotlinOperationBuild.java @@ -23,6 +23,7 @@ import rife.bld.publish.PublishLicense; import rife.bld.publish.PublishScm; import java.util.List; +import java.util.Locale; import static rife.bld.dependencies.Repository.*; import static rife.bld.dependencies.Scope.compile; @@ -33,7 +34,7 @@ public class CompileKotlinOperationBuild extends Project { public CompileKotlinOperationBuild() { pkg = "rife.bld.extension"; name = "bld-kotlin"; - version = version(1, 0, 4); + version = version(1, 1, 0, "SNAPSHOT"); javaRelease = 17; @@ -43,11 +44,11 @@ public class CompileKotlinOperationBuild extends Project { repositories = List.of(MAVEN_LOCAL, MAVEN_CENTRAL, RIFE2_RELEASES, RIFE2_SNAPSHOTS); scope(compile) - .include(dependency("com.uwyn.rife2", "bld", version(2, 2, 0))); + .include(dependency("com.uwyn.rife2", "bld", version(2, 2, 1))); scope(test) - .include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 11, 4))) - .include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 11, 4))) - .include(dependency("org.assertj", "assertj-core", version(3, 27, 2))); + .include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 12, 2))) + .include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 12, 2))) + .include(dependency("org.assertj", "assertj-core", version(3, 27, 3))); javadocOperation() .javadocOptions() @@ -97,10 +98,13 @@ public class CompileKotlinOperationBuild extends Project { @Override public void test() throws Exception { - new ExecOperation() - .fromProject(this) - .command("scripts/cliargs.sh") - .execute(); + var os = System.getProperty("os.name"); + if (os != null && os.toLowerCase(Locale.US).contains("linux")) { + new ExecOperation() + .fromProject(this) + .command("scripts/cliargs.sh") + .execute(); + } super.test(); } } diff --git a/src/main/java/rife/bld/extension/CompileKotlinOperation.java b/src/main/java/rife/bld/extension/CompileKotlinOperation.java index 570ff14..5932298 100644 --- a/src/main/java/rife/bld/extension/CompileKotlinOperation.java +++ b/src/main/java/rife/bld/extension/CompileKotlinOperation.java @@ -19,16 +19,16 @@ 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.ArrayList; -import java.util.Collection; -import java.util.List; +import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; @@ -40,8 +40,12 @@ import java.util.logging.Logger; */ public class CompileKotlinOperation extends AbstractOperation { private static final Logger LOGGER = Logger.getLogger(CompileKotlinOperation.class.getName()); + private static final String OS_NAME = + System.getProperty("os.name") != null ? System.getProperty("os.name").toLowerCase(Locale.US) : null; + private static final String KOTLINC_EXECUTABLE = "kotlinc" + (isWindows() ? ".bat" : ""); private final Collection 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<>(); @@ -55,6 +59,184 @@ public class CompileKotlinOperation extends AbstractOperation(); + + if (isLinux()) { + var userHome = System.getProperty("user.home"); + if (userHome != null) { + commonPaths.put(userHome + "/.sdkman/candidates/kotlin/current/bin", "SDKMAN!"); + } + commonPaths.put("/snap/bin", "Kotlin (Snap)"); + commonPaths.put("/usr/bin", null); + commonPaths.put("/usr/share", null); + commonPaths.put("/usr/local/bin", null); + commonPaths.put("/usr/local/kotlin/bin", null); + commonPaths.put("/usr/share/kotlin/bin/", null); + commonPaths.put("/opt/kotlin/bin", null); + if (userHome != null) { + commonPaths.put(userHome + "/.local/share/JetBrains/Toolbox/apps/intellij-idea-ultimate/plugins/Kotlin/kotlinc/bin", + "IntelliJ IDEA Ultimate"); + commonPaths.put(userHome + "/.local/share/JetBrains/Toolbox/apps/intellij-idea-community-edition/plugins/Kotlin/kotlinc/bin", + "IntelliJ IDEA Community Edition"); + commonPaths.put(userHome + "/.local/share/JetBrains/Toolbox/apps/android-studio/plugins/Kotlin/kotlinc/bin", + "Android Studio"); + } + commonPaths.put("/snap/intellij-idea-ultimate/current/commons/plugins/Kotlin/kotlinc/bin", + "IntelliJ IDEA Ultimate (Snap)"); + commonPaths.put("/snap/intellij-idea-community/current/commons/plugins/Kotlin/kotlinc/bin", + "IntelliJ IDEA Community Edition (Snap)"); + commonPaths.put("/snap/android-studio/current/android-studio/commons/plugins/Kotlin/kotlinc/bin", + "Android Studio (Snap)"); + } else if (isWindows()) { + commonPaths.put("C:\\tools\\kotlinc\\bin", null); + var localAppData = System.getenv("LOCALAPPDATA"); + if (localAppData != null) { + commonPaths.put(localAppData + "\\Programs\\IntelliJ IDEA Ultimate\\plugins\\Kotlin\\kotlinc\\bin", + "IntelliJ IDEA Ultimate"); + commonPaths.put(localAppData + "\\Programs\\IntelliJ IDEA Community Edition\\plugins\\Kotlin\\kotlinc\\bin", + "IntelliJ IDEA Community Edition"); + commonPaths.put(localAppData + "\\Programs\\Android Studio\\plugins\\Kotlin\\kotlinc\\bin", + "Android Studio"); + } + var programFiles = System.getenv("ProgramFiles"); + if (programFiles != null) { + commonPaths.put(programFiles + "\\Kotlin\\bin", null); + } + } else if (isMacOS()) { + var userHome = System.getProperty("user.home"); + if (userHome != null) { + commonPaths.put(userHome + "/.sdkman/candidates/kotlin/current/bin", "SDKMAN!"); + } + commonPaths.put("/opt/homebrew/bin", "Homebrew"); + commonPaths.put("/usr/local/bin", null); + commonPaths.put("/Applications/IntelliJ IDEA.app/Contents/plugins/Kotlin/kotlinc/bin/", + "IntelliJ IDEA"); + commonPaths.put("/Applications/IntelliJ IDEA Community Edition.app/Contents/plugins/Kotlin/kotlinc/bin/", + "IntelliJ IDEA Community Edition"); + commonPaths.put("/Applications/Android Studio.app/Contents/plugins/Kotlin/kotlinc/bin", + "Android Studio"); + } + + for (var path : commonPaths.keySet()) { + kotlincPath = findKotlincInDir(path); + if (kotlincPath != null) { + logKotlincPath(kotlincPath, isSilent, commonPaths.get(path)); + return kotlincPath; + } + } + + // Try 'which' or 'where' commands (less reliable but sometimes works) + try { + Process process; + if (isWindows()) { + process = Runtime.getRuntime().exec("where kotlinc"); + } else { + process = Runtime.getRuntime().exec("which kotlinc"); + } + + try (var scanner = new Scanner(process.getInputStream())) { + if (scanner.hasNextLine()) { + kotlincPath = scanner.nextLine().trim(); + if (isExecutable(new File(kotlincPath))) { + logKotlincPath(kotlincPath, isSilent); + return kotlincPath; + } + } + } + } catch (Exception ignored) { + // Ignore exceptions from which/where, as they might not be available + } + + return KOTLINC_EXECUTABLE; + } + + private static boolean isExecutable(File file) { + return file != null && file.exists() && file.isFile() && file.canExecute(); + } + + /** + * Determines if the operating system is Linux. + * + * @return true if the operating system is Linux, false otherwise. + * @since 1.1.0 + */ + public static boolean isLinux() { + return OS_NAME != null && (OS_NAME.contains("linux") || OS_NAME.contains("unix")); // Consider Unix-like systems as well. + } + + /** + * Determines if the current operating system is macOS. + * + * @return true if the OS is macOS, false otherwise. + * @since 1.1.0 + */ + public static boolean isMacOS() { + return OS_NAME != null && (OS_NAME.contains("mac") || OS_NAME.contains("darwin") || OS_NAME.contains("osx")); + } + /** * Determines if the given string is not blank. * @@ -65,6 +247,30 @@ 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."); @@ -296,49 +519,84 @@ public class CompileKotlinOperation extends AbstractOperation(); var args = new ArrayList(); // kotlinc - args.add(kotlinCompiler()); + if (kotlinc_ != null) { + command.add(kotlinc_.getAbsolutePath()); + } else if (kotlinHome_ != null) { + var kotlinc = findKotlincInDir(kotlinHome_.getAbsolutePath()); + if (kotlinc != null) { + command.add(kotlinc); + } else { + if (LOGGER.isLoggable(Level.SEVERE) && !silent()) { + LOGGER.severe("Could not locate Kotlin compiler in: " + kotlinHome_); + } + throw new ExitStatusException(ExitStatusException.EXIT_FAILURE); + } + } else { + command.add(findKotlincPath(silent())); + } + + // JVM options + if (!jvmOptions_.isEmpty()) { + jvmOptions_.forEach(s -> command.add("-J" + s)); + } // classpath - if (classpath != null && !classpath.isEmpty()) { + if (compileOptions_ != null && !compileOptions_.classpath().isEmpty()) { + cp.addAll(compileOptions_.classpath().stream().map(this::cleanPath).toList()); + } + if (!cp.isEmpty()) { args.add("-cp"); - args.add(FileUtils.joinPaths(classpath.stream().toList())); + args.add('"' + FileUtils.joinPaths(cp.stream().map(this::cleanPath).toList()) + '"'); + } + + // compile options + if (compileOptions_ != null && !compileOptions_.args().isEmpty()) { + args.addAll(compileOptions_.args()); } // 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()); @@ -374,19 +632,41 @@ public class CompileKotlinOperation extends AbstractOperation * Sets the following from the project: *
    - *
  • {@link #kotlinHome() kotlinHome} to the {@code KOTLIN_HOME} environment variable, if set.
  • *
  • {@link #workDir() workDir} to the project's directory.
  • *
  • {@link #buildMainDirectory() buildMainDirectory}
  • *
  • {@link #buildTestDirectory() buildTestDirectory}
  • @@ -405,14 +685,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)); } /** @@ -755,15 +1045,17 @@ public class CompileKotlinOperation extends AbstractOperation advancedOptions_ = new ArrayList<>(); private final Collection argFile_ = new ArrayList<>(); private final Collection classpath_ = new ArrayList<>(); - private final Collection jvmOptions_ = new ArrayList<>(); private final Collection optIn_ = new ArrayList<>(); private final Collection options_ = new ArrayList<>(); private final Collection plugin_ = new ArrayList<>(); @@ -112,7 +117,6 @@ public class CompileOptions { return this; } - /** * Allow using declarations only from the specified version of Kotlin bundled libraries. * @@ -251,13 +255,27 @@ public class CompileOptions { // @argfile if (!argFile_.isEmpty()) { - 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))); + argFile_.forEach(f -> { + if (f.exists()) { + try { + try (var reader = Files.newBufferedReader(f.toPath(), Charset.defaultCharset())) { + var tokenizer = new AbstractToolProviderOperation.CommandLineTokenizer(reader); + String token; + while ((token = tokenizer.nextToken()) != null) { + args.add(token); + } + } + } catch (IOException e) { + if (LOGGER.isLoggable(Level.WARNING)) { + LOGGER.log(Level.WARNING, "Could not read: " + f.getAbsolutePath(), e); + } + } + } else { + if (LOGGER.isLoggable(Level.WARNING)) { + LOGGER.warning("File not found: " + f.getAbsolutePath()); + } + } + }); } // expression @@ -293,11 +311,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"); @@ -375,7 +388,7 @@ public class CompileOptions { args.add("-verbose"); } - // Wwrror + // Werror if (wError_) { args.add("-Werror"); } @@ -385,9 +398,15 @@ public class CompileOptions { args.add("-Wextra"); } - // advanced option (X) + // advanced options (X) if (!advancedOptions_.isEmpty()) { - advancedOptions_.forEach(it -> args.add("-X" + it)); + advancedOptions_.forEach(it -> { + if (it.startsWith("-X")) { + args.add(it); + } else { + args.add("-X" + it); + } + }); } return args; @@ -678,7 +697,7 @@ public class CompileOptions { * Limit the API of the JDK in the classpath to the specified Java version. Automatically sets * {@link #jvmTarget(String) JVM target} version. *

    - * Possible values are 1.8, 9, 10, ..., 22. The default value is 1.8. + * Possible values are 1.8, 9, 10, ..., 23. The default value is 1.8. * * @param version the target version * @return this operation instance @@ -693,8 +712,6 @@ public class CompileOptions { *

    * Limit the API of the JDK in the classpath to the specified Java version. Automatically sets * {@link #jvmTarget(String) JVM target} version. - *

    - * Possible values are 1.8, 9, 10, ..., 22. The default value is 1.8. * * @param version the target version * @return this operation instance @@ -704,36 +721,6 @@ public class CompileOptions { return jdkRelease(String.valueOf(version)); } - /** - * Retrieves the Java Virtual Machine options. - * - * @return the JVM options - */ - public Collection jvmOptions() { - return jvmOptions_; - } - - /** - * Pass an option directly to 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 JVM - * - * @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. * @@ -748,7 +735,7 @@ public class CompileOptions { /** * Specify the target version of the generated JVM bytecode. *

    - * Possible values are 1.8, 9, 10, ..., 22. The default value is 1.8. + * Possible values are 1.8, 9, 10, ..., 23. The default value is 1.8. * * @param target the target version * @return this operation instance diff --git a/src/main/java/rife/bld/extension/kotlin/CompilerPlugin.java b/src/main/java/rife/bld/extension/kotlin/CompilerPlugin.java index 03d4382..f1fd584 100644 --- a/src/main/java/rife/bld/extension/kotlin/CompilerPlugin.java +++ b/src/main/java/rife/bld/extension/kotlin/CompilerPlugin.java @@ -17,6 +17,7 @@ package rife.bld.extension.kotlin; /** + * @author Erik C. Thauvin * Defines the known Kotlin compiler plugin JARs. * * @author Erik C. Thauvin @@ -25,6 +26,8 @@ package rife.bld.extension.kotlin; public enum CompilerPlugin { ALL_OPEN("allopen-compiler-plugin.jar"), ASSIGNMENT("assignment-compiler-plugin.jar"), + COMPOSE("compose-compiler-plugin.jar"), + KOTLIN_IMPORTS_DUMPER("kotlin-imports-dumper-compiler-plugin.jar"), KOTLINX_SERIALIZATION("kotlinx-serialization-compiler-plugin.jar"), KOTLIN_SERIALIZATION("kotlin-serialization-compiler-plugin.jar"), LOMBOK("lombok-compiler-plugin.jar"), diff --git a/src/main/java/rife/bld/extension/kotlin/JvmOptions.java b/src/main/java/rife/bld/extension/kotlin/JvmOptions.java new file mode 100644 index 0000000..7e2ec62 --- /dev/null +++ b/src/main/java/rife/bld/extension/kotlin/JvmOptions.java @@ -0,0 +1,90 @@ +/* + * Copyright 2023-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package rife.bld.extension.kotlin; + +import rife.tools.StringUtils; + +import java.io.Serial; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * Java Virtual Machine options. + * + * @author Erik C. Thauvin + * @since 1.1.0 + */ +@SuppressWarnings("PMD.LooseCoupling") +public class JvmOptions extends ArrayList { + /** + * Keyword to enable native access for all code on the class path. + */ + public final static String ALL_UNNAMED = "ALL-UNNAMED"; + + @Serial + private static final long serialVersionUID = 1L; + + /** + * Modules that are permitted to perform restricted native operations. + * The module name can also be {@link #ALL_UNNAMED}. + * + * @param modules the module names + * @return this list of options + */ + public JvmOptions enableNativeAccess(String... modules) { + return enableNativeAccess(List.of(modules)); + } + + /** + * Modules that are permitted to perform restricted native operations. + * The module name can also be {@link #ALL_UNNAMED}. + * + * @param modules the module names + * @return this list of options + */ + public JvmOptions enableNativeAccess(Collection modules) { + add("--enable-native-access=" + StringUtils.join(modules, ",")); + return this; + } + + /** + * Controls what action the Java runtime takes when native access is not enabled for a module. + * + * @param access the access mode + * @return this list of options + */ + public JvmOptions illegalNativeAccess(NativeAccess access) { + add("--illegal-native-access=" + access.mode); + return this; + } + + /** + * Illegal native access modes. + */ + public enum NativeAccess { + ALLOW("allow"), + DENY("deny"), + WARN("warn"); + + public final String mode; + + NativeAccess(String mode) { + this.mode = mode; + } + } +} diff --git a/src/test/java/rife/bld/extension/CompileKotlinOperationTest.java b/src/test/java/rife/bld/extension/CompileKotlinOperationTest.java index 9fffc25..4e0182e 100644 --- a/src/test/java/rife/bld/extension/CompileKotlinOperationTest.java +++ b/src/test/java/rife/bld/extension/CompileKotlinOperationTest.java @@ -23,6 +23,7 @@ import rife.bld.BaseProject; import rife.bld.blueprints.BaseProjectBlueprint; import rife.bld.extension.kotlin.CompileOptions; import rife.bld.extension.kotlin.CompilerPlugin; +import rife.bld.extension.kotlin.JvmOptions; import rife.tools.FileUtils; import java.io.File; @@ -30,6 +31,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Objects; import java.util.logging.ConsoleHandler; import java.util.logging.Level; @@ -103,11 +105,11 @@ class CompileKotlinOperationTest { .testSourceFiles(List.of(new File("tfile3"), new File("tfile4"))) .testSourceFiles(new File("tfile5"), new File("tfile6")) .plugins("plugin1", "plugin2") - .plugins(CompilerPlugin.KOTLIN_SERIALIZATION, CompilerPlugin.ASSIGNMENT) + .plugins(CompilerPlugin.KOTLIN_SERIALIZATION, CompilerPlugin.ASSIGNMENT, CompilerPlugin.COMPOSE) .plugins(new File("lib/compile"), CompilerPlugin.LOMBOK, CompilerPlugin.POWER_ASSERT) - .plugins(Path.of("lib/compile"), CompilerPlugin.NOARG, CompilerPlugin.ALL_OPEN) + .plugins(Path.of("lib/compile"), CompilerPlugin.NOARG, CompilerPlugin.ALL_OPEN, + CompilerPlugin.KOTLIN_IMPORTS_DUMPER) .plugins("lib/compile", CompilerPlugin.KOTLINX_SERIALIZATION, CompilerPlugin.SAM_WITH_RECEIVER) - .plugins(List.of("plugin3", "plugin4")); try (var softly = new AutoCloseableSoftAssertions()) { @@ -131,12 +133,14 @@ class CompileKotlinOperationTest { new File("tfile1"), new File("tfile2"), new File("tfile3"), new File("tfile4"), new File("tfile5"), new File("tfile6")); softly.assertThat(op.plugins()).as("plugins").contains("plugin1", "plugin2", "plugin3", "plugin4", - "/kotlin_home/lib/kotlin-serialization-compiler-plugin.jar", - "/kotlin_home/lib/assignment-compiler-plugin.jar", + new File("/kotlin_home/lib/kotlin-serialization-compiler-plugin.jar").getAbsolutePath(), + new File("/kotlin_home/lib/assignment-compiler-plugin.jar").getAbsolutePath(), + new File("/kotlin_home/lib/compose-compiler-plugin.jar").getAbsolutePath(), new File("lib/compile", "lombok-compiler-plugin.jar").getAbsolutePath(), new File("lib/compile", "power-assert-compiler-plugin.jar").getAbsolutePath(), new File("lib/compile", "noarg-compiler-plugin.jar").getAbsolutePath(), new File("lib/compile", "allopen-compiler-plugin.jar").getAbsolutePath(), + new File("lib/compile", "kotlin-imports-dumper-compiler-plugin.jar").getAbsolutePath(), new File("lib/compile", "kotlinx-serialization-compiler-plugin.jar").getAbsolutePath(), new File("lib/compile", "sam-with-receiver-compiler-plugin.jar").getAbsolutePath()); } @@ -176,10 +180,16 @@ class CompileKotlinOperationTest { .compileTestClasspath(mainDir.getAbsolutePath()); op.compileOptions().verbose(true); - op.compileOptions().jdkRelease("17"); + op.compileOptions().argFile("src/test/resources/argfile.txt", "src/test/resources/argfile2.txt"); + + 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", "-no-stdlib", "-verbose"); + var matches = List.of("-Xjdk-release=17", "-no-reflect", "-progressive", "-include-runtime", "-no-stdlib", + "-verbose"); assertThat(args).as(args + " == " + matches).isEqualTo(matches); op.execute(); @@ -204,6 +214,20 @@ class CompileKotlinOperationTest { } } + @Test + void testFindKotlincPath() { + assertThat(CompileKotlinOperation.findKotlincPath()).doesNotStartWith("kotlinc"); + } + + @Test + void testFromProject() { + 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")); + } + @Test void testFromProjectNoKotlin() { var op = new CompileKotlinOperation().fromProject( @@ -212,6 +236,21 @@ class CompileKotlinOperationTest { assertThat(op.testSourceDirectories()).isEmpty(); } + @Test + void testIsOS() { + var osName = System.getProperty("os.name"); + if (osName != null) { + var os = osName.toLowerCase(Locale.US); + if (os.contains("win")) { + assertThat(CompileKotlinOperation.isWindows()).isTrue(); + } else if (os.contains("linux") || os.contains("unix")) { + assertThat(CompileKotlinOperation.isLinux()).isTrue(); + } else if (os.contains("mac") || os.contains("darwin")) { + assertThat(CompileKotlinOperation.isMacOS()).isTrue(); + } + } + } + @Test void testKotlinHome() { var foo = new File("foo"); @@ -313,6 +352,8 @@ class CompileKotlinOperationTest { .fromProject(new BaseProject()) .plugins(CompilerPlugin.ALL_OPEN, CompilerPlugin.ASSIGNMENT, + CompilerPlugin.COMPOSE, + CompilerPlugin.KOTLIN_IMPORTS_DUMPER, CompilerPlugin.KOTLINX_SERIALIZATION, CompilerPlugin.KOTLIN_SERIALIZATION, CompilerPlugin.LOMBOK, diff --git a/src/test/java/rife/bld/extension/kotlin/CompileOptionsTest.java b/src/test/java/rife/bld/extension/kotlin/CompileOptionsTest.java index df78097..c6e6965 100644 --- a/src/test/java/rife/bld/extension/kotlin/CompileOptionsTest.java +++ b/src/test/java/rife/bld/extension/kotlin/CompileOptionsTest.java @@ -18,6 +18,8 @@ package rife.bld.extension.kotlin; import org.assertj.core.api.AutoCloseableSoftAssertions; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledOnOs; +import org.junit.jupiter.api.condition.OS; import java.io.File; import java.io.IOException; @@ -45,14 +47,11 @@ class CompileOptionsTest { .collect(Collectors.joining(File.pathSeparator)); } - @Test @SuppressWarnings("PMD.UnitTestShouldIncludeAssert") void testArgs() { 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,8 +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", @@ -115,10 +112,9 @@ class CompileOptionsTest { @Test void testArgsCollections() { - var advanceOptions = List.of("Xoption1", "Xoption2"); + var advanceOptions = List.of("-Xoption1", "option=2"); 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"); @@ -128,7 +124,6 @@ class CompileOptionsTest { .advancedOptions(advanceOptions) .argFile(argFile) .classpath(classpath) - .jvmOptions(jvmOptions) .noStdLib(false) .optIn(optIn) .options(options) @@ -146,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") @@ -167,7 +160,7 @@ class CompileOptionsTest { "-foo", "-bar", "-script-templates", "temp1,temp2", - "-XXoption1", "-XXoption2", + "-Xoption1", "-Xoption=2", "-P", "plugin:id:name:value", "-P", "plugin:id2:name2:value2"); @@ -192,20 +185,27 @@ class CompileOptionsTest { var bar = new File("bar.txt"); var options = new CompileOptions(); + options = options.argFile(foo); + assertThat(options.argFile()).contains(foo); + options.argFile().clear(); + assertThat(options.argFile()).isEmpty(); + options.argFile(foo, bar); assertThat(options.argFile()).contains(foo, bar); options.argFile().clear(); + assertThat(options.argFile()).isEmpty(); options = options.argFile(foo.toPath(), bar.toPath()); assertThat(options.argFile()).contains(foo, bar); options.argFile().clear(); + assertThat(options.argFile()).isEmpty(); - options.argFile(foo.getAbsolutePath(), bar.getAbsolutePath()); + options = options.argFile(foo.getAbsolutePath(), bar.getAbsolutePath()); assertThat(options.argFile()).contains(new File(foo.getAbsolutePath()), new File(bar.getAbsolutePath())); - options.argFile().clear(); } @Test + @EnabledOnOs(OS.LINUX) void testCheckAllParams() throws IOException { var args = Files.readAllLines(Paths.get("src", "test", "resources", "kotlinc-args.txt")); @@ -214,10 +214,7 @@ class CompileOptionsTest { var params = new CompileOptions() .advancedOptions("Xoption") .apiVersion("11") - .argFile("file") - .classpath("classpath") .expression("expression") - .jvmOptions("option") .includeRuntime(true) .javaParameters(true) .jdkHome("jdkhome") @@ -239,6 +236,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; @@ -259,31 +260,45 @@ class CompileOptionsTest { var bar = new File("bar.txt"); var options = new CompileOptions(); + options = options.classpath(foo); + assertThat(options.classpath()).as("File").containsExactly(foo); + options.classpath().clear(); + assertThat(options.argFile()).isEmpty(); + + options.classpath(foo, bar); assertThat(options.classpath()).as("File...").containsExactly(foo, bar); options.classpath().clear(); + assertThat(options.argFile()).isEmpty(); + options.classpath(List.of(foo, bar)); assertThat(options.classpath()).as("List(File...)").containsExactly(foo, bar); options.classpath().clear(); + assertThat(options.argFile()).isEmpty(); + options = options.classpath(foo.toPath(), bar.toPath()); assertThat(options.classpath()).as("Path...").containsExactly(foo, bar); options.classpath().clear(); + assertThat(options.argFile()).isEmpty(); + options = options.classpathPaths(List.of(foo.toPath(), bar.toPath())); assertThat(options.classpath()).as("List(Path...)").containsExactly(foo, bar); options.classpath().clear(); + assertThat(options.argFile()).isEmpty(); + options.classpath(foo.getAbsolutePath(), bar.getAbsolutePath()); assertThat(options.classpath()).as("String...") .containsExactly(new File(foo.getAbsolutePath()), new File(bar.getAbsolutePath())); options.classpath().clear(); + assertThat(options.argFile()).isEmpty(); options.classpathStrings(List.of(foo.getAbsolutePath(), bar.getAbsolutePath())); assertThat(options.classpath()).as("List(String...)") .containsExactly(new File(foo.getAbsolutePath()), new File(bar.getAbsolutePath())); - options.classpath().clear(); } @Test diff --git a/src/test/java/rife/bld/extension/kotlin/JvmOptionsTest.java b/src/test/java/rife/bld/extension/kotlin/JvmOptionsTest.java new file mode 100644 index 0000000..6f8474f --- /dev/null +++ b/src/test/java/rife/bld/extension/kotlin/JvmOptionsTest.java @@ -0,0 +1,78 @@ +/* + * Copyright 2023-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package rife.bld.extension.kotlin; + +import org.junit.jupiter.api.Test; +import rife.bld.extension.CompileKotlinOperation; + +import java.util.List; + +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"); + + op = new CompileKotlinOperation().jvmOptions(new JvmOptions().enableNativeAccess("m1", "m2")); + assertThat(op.jvmOptions()).as("m1,m2").containsExactly("--enable-native-access=m1,m2"); + } + + @Test + void testEnableNativeAccess() { + var options = new JvmOptions().enableNativeAccess(JvmOptions.ALL_UNNAMED); + assertThat(options).as(JvmOptions.ALL_UNNAMED).containsExactly("--enable-native-access=ALL-UNNAMED"); + + options = new JvmOptions().enableNativeAccess("m1"); + assertThat(options).as("m1").containsExactly("--enable-native-access=m1"); + + options = new JvmOptions().enableNativeAccess("m1", "m2"); + assertThat(options).as("m1,m2").containsExactly("--enable-native-access=m1,m2"); + } + + @Test + void testIllegalNativeAccess() { + var options = new JvmOptions().illegalNativeAccess(JvmOptions.NativeAccess.ALLOW); + assertThat(options).as("ALLOW").containsExactly("--illegal-native-access=allow"); + + options = new JvmOptions().illegalNativeAccess(JvmOptions.NativeAccess.DENY); + assertThat(options).as("DENY").containsExactly("--illegal-native-access=deny"); + + options = new JvmOptions().illegalNativeAccess(JvmOptions.NativeAccess.WARN); + assertThat(options).as("WARN").containsExactly("--illegal-native-access=warn"); + } + + @Test + void testJvmOptions() { + var op = new CompileKotlinOperation().jvmOptions("option1", "option2"); + assertThat(op.jvmOptions()).as("option1,option2").containsExactly("option1", "option2"); + + op = new CompileKotlinOperation().jvmOptions(List.of("option1", "option2")); + assertThat(op.jvmOptions()).as("List.of(option1,option2)").containsExactly("option1", "option2"); + + 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"); + + 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"); + } +} diff --git a/src/test/resources/argfile.txt b/src/test/resources/argfile.txt new file mode 100644 index 0000000..d128d62 --- /dev/null +++ b/src/test/resources/argfile.txt @@ -0,0 +1,3 @@ +-Xjdk-release=17 -no-reflect + +-progressive diff --git a/src/test/resources/argfile2.txt b/src/test/resources/argfile2.txt new file mode 100644 index 0000000..93f9181 --- /dev/null +++ b/src/test/resources/argfile2.txt @@ -0,0 +1 @@ +-include-runtime \ No newline at end of file