diff --git a/README.md b/README.md index d0d0ff9..06ce2cb 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,14 @@ for all available configuration options. Please make sure the Kotlin compiler is [installed](https://kotlinlang.org/docs/command-line.html#install-the-compiler). +The plugin will look in common locations such as: +- `KOTLIN_HOME` +- `PATH` +- SDKMAN! +- Homebrew +- JetBrains Toolbox (IntelliJ IDEA, Android Studio) +- etc. + You can also manually configure the Kotlin home location as follows: ```java diff --git a/src/main/java/rife/bld/extension/CompileKotlinOperation.java b/src/main/java/rife/bld/extension/CompileKotlinOperation.java index 570ff14..f1c912b 100644 --- a/src/main/java/rife/bld/extension/CompileKotlinOperation.java +++ b/src/main/java/rife/bld/extension/CompileKotlinOperation.java @@ -26,9 +26,7 @@ import rife.tools.FileUtils; import java.io.File; import java.io.IOException; 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,6 +38,9 @@ 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 Collection mainSourceDirectories_ = new ArrayList<>(); @@ -55,6 +56,145 @@ public class CompileKotlinOperation extends AbstractOperation commonPaths = new ArrayList<>(); + + if (isLinux()) { + commonPaths.add("/usr/bin"); + commonPaths.add("/usr/local/bin"); + commonPaths.add("/usr/local/kotlin/bin"); + commonPaths.add("/opt/kotlin/bin"); + var userHome = System.getProperty("user.home"); + if (userHome != null) { + commonPaths.add(userHome + "/.sdkman/candidates/kotlin/current/bin"); // SDKMAN! + commonPaths.add(userHome + "/.local/share/JetBrains/Toolbox/apps/intellij-idea-ultimate/plugins/Kotlin/bin"); // Toolbox IDEA Ultimate + commonPaths.add(userHome + "/.local/share/JetBrains/Toolbox/apps/intellij-idea-community-edition/plugins/Kotlin/bin"); // Toolbox IDEA CE + commonPaths.add(userHome + "/.local/share/JetBrains/Toolbox/apps/android-studio/plugins/Kotlin/bin"); // Toolbox Android Studio + } + } else if (isWindows()) { + var localAppData = System.getenv("LOCALAPPDATA"); + if (localAppData != null) { + commonPaths.add(localAppData + "\\Programs\\IntelliJ IDEA Ultimate\\plugins\\Kotlin\\kotlinc\\bin"); // Toolbox IDEA Ultimate + commonPaths.add(localAppData + "\\Programs\\IntelliJ IDEA Community Edition\\plugins\\Kotlin\\kotlinc\\bin"); // Toolbox IDEA CE + commonPaths.add(localAppData + "\\Programs\\Android Studio\\plugins\\Kotlin\\kotlinc\\bin"); // Toolbox Android Studio + } + var programFiles = System.getenv("ProgramFiles"); + if (programFiles != null) { + commonPaths.add(programFiles + File.separator + "Kotlin"); + } + } else if (isMacOS()) { + commonPaths.add("/usr/local/bin"); // Homebrew + commonPaths.add("/opt/homebrew/bin"); // Homebrew + var userHome = System.getProperty("user.home"); + if (userHome != null) { + commonPaths.add(userHome + "/.sdkman/candidates/kotlin/current/bin"); // SDKMAN! + } + commonPaths.add("/Applications/IntelliJ IDEA Ultimate.app/Contents/plugins/Kotlin/bin"); //IntelliJ IDEA Ultimate + commonPaths.add("/Applications/IntelliJ IDEA.app/Contents/plugins/Kotlin/bin"); //IntelliJ IDEA + commonPaths.add("/Applications/Android Studio.app/Contents/plugins/Kotlin/bin"); //Android Studio + } + + for (var location : commonPaths) { + kotlincPath = findKotlincInDir(location); + if (kotlincPath != null) { + 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))) { + 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. + */ + 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. + */ + public static boolean isMacOS() { + return OS_NAME != null && (OS_NAME.contains("mac") || OS_NAME.contains("darwin")); + } + /** * Determines if the given string is not blank. * @@ -65,6 +205,15 @@ public class CompileKotlinOperation extends AbstractOperation(); // kotlinc - args.add(kotlinCompiler()); + if (kotlinc_ != null) { + args.add(kotlinc_.getAbsolutePath()); + } else if (kotlinHome_ != null) { + args.add(Objects.requireNonNullElseGet(findKotlincInDir(kotlinHome_.getAbsolutePath()), + CompileKotlinOperation::findKotlincPath)); + } else { + args.add(findKotlincPath()); + } // classpath if (classpath != null && !classpath.isEmpty()) { @@ -386,7 +542,6 @@ 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 +560,6 @@ public class CompileKotlinOperation extends AbstractOperation