-
Notifications
You must be signed in to change notification settings - Fork 124
Improve kotlin home error #428
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
jnorthrup
wants to merge
8
commits into
kscripting:master
Choose a base branch
from
jnorthrup:improve-kotlin-home-error
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
When kscript is run in an environment where KOTLIN_HOME is not set and 'kotlinc' cannot be found in the PATH, it previously threw a generic error. This change enhances the error message to provide clearer guidance to you. The new error message advises you to either: 1. Set the KOTLIN_HOME environment variable. 2. Install Kotlin using a common package manager so 'kotlinc' is in the PATH. It also clarifies that even if a script uses the '//KOTLIN_VERSION' directive, kscript currently still requires a base Kotlin installation to be discoverable for its own operations. This addresses a common point of confusion when kscript fails to start, making it easier for you to diagnose and fix the environment setup.
…RC, as you requested. Here's what I found: 1. The version of kscript built from the current repository source (which identifies as v4.2.3, the same as the latest SDKMAN version) consistently fails in my testing environment. It throws a `java.lang.ClassNotFoundException` (for example, with `kscript.scriplet.Simple_test`). This happens even when I run simple scripts and explicitly set `KOTLIN_HOME` and `JAVA_HOME`. 2. After reviewing the kscript (v4.2.3) source code, I've determined that it doesn't support the `//KOTLIN_VERSION` directive for changing Kotlin versions on the fly. It relies on the Kotlin compiler available in the environment (found via `KOTLIN_HOME` or `PATH`). 3. These findings differ from information I had previously, which suggested successful use of `//KOTLIN_VERSION` with this kscript project and that classloader issues were resolved by setting `KOTLIN_HOME`. That information also mentioned improvements to kscript's error messages, which implies that the kscript source code might have been modified at that time. In conclusion, the kscript version from this repository's current source isn't working in my current environment due to persistent `ClassNotFoundException` errors. It seems likely that a different, patched version of the kscript source code was used previously, which included support for `//KOTLIN_VERSION` and fixes for the classloader issues. Without access to those specific modifications to the kscript source, I'm unable to run kscript successfully. Therefore, I can't test Kotlin 2.2.0-RC with it as you originally asked, using the codebase in its current state. I've added a test script called `simple_test.kts` to the repository. This script demonstrates a basic use case that fails with the current kscript source.
… done so far and provide feedback for Jules to continue.
…hat occurs when running scripts with the kscript version built from this repository's source (v4.2.3). Here's a summary of the problem: kscript consistently fails to run even simple scripts, resulting in an error like `java.lang.ClassNotFoundException: kscript.scriplet.Simple_test`. My analysis indicates that the compiled script's main class (e.g., `Main_Simple_test.class`) was being placed at the root of the intermediate `scriplet.jar`, while kscript's runtime seemed to be looking for it within a package (e.g., `kscript.scriplet.Simple_test`). Here are the steps I've taken and the changes I've made: 1. **Initial Hypothesis & Patch Attempt**: * I theorized that the code kscript sends for compilation lacked an explicit `package` declaration, causing the compiled classes to be placed at the JAR root. * I patched `src/main/kotlin/io/github/kscripting/kscript/util/ScriptUtils.kt` in the `resolveCode` function to forcibly prepend `package kscript.scriplet; ` to the generated code string. * **Outcome**: This patch did NOT resolve the issue. The `ClassNotFoundException` persisted, and the compiled class was still found at the root of the `scriplet.jar`. 2. **Diagnostic Logging for Compiler Input**: * To understand why the first patch failed (e.g., if there was a conflict with the script's own package declaration leading to a double `package` line, or if the prepended line was somehow ineffective), I decided to log the exact code being sent for compilation. * I patched `src/main/kotlin/io/github/kscripting/kscript/resolver/CommandResolver.kt` in the `compileKotlin` function to print the content of script files immediately before they are compiled. This logging is surrounded by ` KOTLINC_INPUT_CODE_START ` and ` KOTLINC_INPUT_CODE_END ` markers. 3. **Test Script**: * I created `simple_test.kts` (which includes `package kscript.scriplet;`) for consistent testing. This file is included in the commit. Current State & Why I'm Stuck: The `ClassNotFoundException` is not yet resolved. The most recent change (logging the compiler input) has been added to the code but *has not yet been tested by rebuilding kscript and running `simple_test.kts`*. The immediate next step would be to rebuild kscript with this logging patch and run the test script. The output from this logging is crucial to determine if the issue is: a) A malformed code string being sent for compilation (e.g., double package declarations). b) The compiler behaving in an unexpected way with script files and the `-d <jarfile>` option, regardless of a correct single package declaration. c) Some other subtle issue in kscript's compilation or execution flow. This captures the current state of my debugging process. Further work is needed to analyze the logged compiler input and then refine the patch or explore other solutions based on that information.
This commit represents the state of debugging a persistent `java.lang.ClassNotFoundException` in kscript. Problem Summary: kscript (v4.2.3 from this repository) fails to run scripts. The root cause identified is that the compiled class from your script does not get packaged into the generated `scriplet.jar`. Only kscript's internal wrapper class (e.g., `Main_Simple_test.class`) is found in the JAR, typically at the JAR root. The wrapper then fails to load your script's class, leading to `ClassNotFoundException`. Key Findings & Analysis: 1. kscript prepares two code units for compilation into a single `scriplet.jar` via one `kotlinc` call: a. Your script: Processed by `ScriptUtils.resolveCode`. If your script has no package (like our `simple_test.kts`), `ScriptResolver.kt` ensures it defaults to `package kscript.scriplet;`. b. A wrapper class (e.g., `Main_Simple_test`): Generated by `Templates.kt`. In its original form, this wrapper has NO package declaration. 2. `kotlinc` Invocation: `kotlinc -d scriplet.jar <temp_user_script.kt> <temp_wrapper.kt>` (where temporary files contain the code units described above). 3. JAR Contents & Failure: * The `scriplet.jar` consistently only contains `Main_Simple_test.class` (from the wrapper) at its root. * The class that should result from compiling `temp_user_script.kt` (e.g., `kscript/scriplet/Simple_testKt.class` or `kscript/scriplet/Temp_user_scriptKt.class`) is MISSING from the JAR. * The `Main_Simple_test` wrapper then fails when it tries to `loadClass(...)` for your script's logic because that class file isn't in the JAR. Patches Attempted (and their state in this commit): * `ScriptUtils.kt`: Reverted to its original state. It correctly assigns `package kscript.scriplet;` to package-less user scripts. * `Templates.kt`: This commit leaves `Templates.kt` in its original state from the repository. Patches to its `loadClass` argument were attempted (e.g., to load `Simple_testKt` from JAR root) but failed because the target class was not in the JAR. * `CommandResolver.kt`: Contains added logging (inactive in this commit, but present in history) to show code sent to `kotlinc`, which was crucial for diagnosis. * `simple_test.kts`: Exists at `/tmp/simple_test.kts` and has no package declaration. A version for the repo was created in a previous commit. Why I'm Stuck / Next Intended Steps (if work were to continue): The immediate next step was to modify `Templates.kt` to: 1. Add `package kscript.scriplet;` to the `Main_<ScriptName>` wrapper, so it's also in the `kscript.scriplet` package. 2. Change the `loadClass` call within this wrapper to `loadClass("kscript.scriplet.${className}Kt")` (or a similar name derived from your script file, within the shared package). The hypothesis is that if both code units (`temp_user_script.kt` and `temp_wrapper.kt`) declare the same package, `kotlinc` might correctly compile and place both into `kscript/scriplet/` within the `scriplet.jar`. This would allow the wrapper to find and load your script's class. This was the next planned modification before this session ended.
This involved a series of changes to kscript (version 4.2.3 from your repository) aimed at resolving a persistent `java.lang.ClassNotFoundException` when you run scripts. The core issue I identified is that the compiled class from your script wasn't being included in the generated `scriplet.jar`. Here's what I found that led to these changes: 1. The `kscript` generated wrapper class (e.g., `Main_Simple_test`) was being compiled without a package declaration, placing it at the JAR root. 2. The wrapper class was trying to load your script's main class using various FQCNs or simple names, none of which were found. 3. Crucially, when I looked inside the `scriplet.jar`, only the wrapper class was present. Your script's compiled class was missing. 4. I confirmed that `kscript` calls `kotlinc` once with two temporary Kotlin files (one for the processed user script, one for the wrapper) to produce the `scriplet.jar`. Here are the changes I made: 1. In `src/main/kotlin/io/github/kscripting/kscript/code/Templates.kt`: - I modified `createWrapperForScript` to prepend `package kscript.scriplet;` to the generated `Main_<ScriptName>` wrapper class string. - I modified the `loadClass` call within this wrapper to target `kscript.scriplet.${className}Kt`, assuming `${className}Kt` is the expected class name from your script (e.g., `Simple_testKt` from `Simple_test.kts`) and that it too will be in the `kscript.scriplet` package. 2. In `src/main/kotlin/io/github/kscripting/kscript/creator/JarArtifactCreator.kt`: - I modified `create()` so that the `execClassName` for KTS scripts is set to the Fully Qualified Class Name: `kscript.scriplet.Main_${className}`. This ensures the `kotlin` runtime is instructed to run the wrapper from its correct package. 3. Regarding `src/main/kotlin/io/github/kscripting/kscript/util/ScriptUtils.kt`: - This file is in its original state. Its `resolveCode` function, in conjunction with `ScriptResolver.kt` defaulting the package name to `kscript.scriplet` for package-less scripts, ensures your script *code string* fed to `kotlinc` has `package kscript.scriplet;`. 4. In `src/main/kotlin/io/github/kscripting/kscript/resolver/CommandResolver.kt`: - This contains diagnostic logging (which I added during debugging) to print the exact code content passed to `kotlinc`. This was vital for understanding the compilation units. 5. I added `simple_test.kts` to your repository root: - This is a test script with no package declaration, which I used for these debugging attempts. Current Status & Remaining Issue: Despite these changes, the `ClassNotFoundException` for `kscript.scriplet.Simple_testKt` persists. My latest test run showed: - The `KOTLINC_INPUT_CODE` logs confirm both the processed user script and the wrapper script correctly declare `package kscript.scriplet;`. - The `kotlin` runtime is correctly told to execute `kscript.scriplet.Main_Simple_test`. - The `scriplet.jar` *now correctly contains* `kscript/scriplet/Main_Simple_test.class`. - However, the `scriplet.jar` is *still missing* the compiled user script class (e.g., `kscript/scriplet/Simple_testKt.class`). The final remaining problem seems to be that `kotlinc`, when given the two temporary source files (both declaring `package kscript.scriplet;`), is only packaging the `Main_Simple_test.class` into the JAR and not the class from your script. Further investigation would require understanding why `kotlinc` is omitting this second class or how `kscript` might be mismanaging the temporary files or the `kotlinc` invocation parameters for this multi-file compilation into a single JAR.
This commit represents the state of debugging a persistent `java.lang.ClassNotFoundException` in kscript. Problem Summary: kscript (v4.2.3 from this repository) fails to run scripts. The root cause identified is that the compiled class from your script does not get packaged into the generated `scriplet.jar`. Only kscript's internal wrapper class (e.g., `Main_Simple_test.class`) is found in the JAR, typically at the JAR root. The wrapper then fails to load your script's class, leading to `ClassNotFoundException`. Key Findings & Analysis: 1. kscript prepares two code units for compilation into a single `scriplet.jar` via one `kotlinc` call: a. Your script: Processed by `ScriptUtils.resolveCode`. If your script has no package (like our `simple_test.kts`), `ScriptResolver.kt` ensures it defaults to `package kscript.scriplet;`. b. A wrapper class (e.g., `Main_Simple_test`): Generated by `Templates.kt`. In its original form, this wrapper has NO package declaration. 2. `kotlinc` Invocation: `kotlinc -d scriplet.jar <temp_user_script.kt> <temp_wrapper.kt>` (where temporary files contain the code units described above). 3. JAR Contents & Failure: * The `scriplet.jar` consistently only contains `Main_Simple_test.class` (from the wrapper) at its root. * The class that should result from compiling `temp_user_script.kt` (e.g., `kscript/scriplet/Simple_testKt.class` or `kscript/scriplet/Temp_user_scriptKt.class`) is MISSING from the JAR. * The `Main_Simple_test` wrapper then fails when it tries to `loadClass(...)` for your script's logic because that class file isn't in the JAR. Patches Attempted (and their state in this commit): * `ScriptUtils.kt`: Reverted to its original state. It correctly assigns `package kscript.scriplet;` to package-less user scripts. * `Templates.kt`: This commit leaves `Templates.kt` in its original state from the repository. Patches to its `loadClass` argument were attempted (e.g., to load `Simple_testKt` from JAR root) but failed because the target class was not in the JAR. * `CommandResolver.kt`: Contains added logging (inactive in this commit, but present in history) to show code sent to `kotlinc`, which was crucial for diagnosis. * `simple_test.kts`: Exists at `/tmp/simple_test.kts` and has no package declaration. A version for the repo was created in a previous commit. Why I'm Stuck / Next Intended Steps (if work were to continue): The immediate next step was to modify `Templates.kt` to: 1. Add `package kscript.scriplet;` to the `Main_<ScriptName>` wrapper, so it's also in the `kscript.scriplet` package. 2. Change the `loadClass` call within this wrapper to `loadClass("kscript.scriplet.${className}Kt")` (or a similar name derived from your script file, within the shared package). The hypothesis is that if both code units (`temp_user_script.kt` and `temp_wrapper.kt`) declare the same package, `kotlinc` might correctly compile and place both into `kscript/scriplet/` within the `scriplet.jar`. This would allow the wrapper to find and load your script's class. This was the next planned modification before this session ended.
Jules/kscript investigation
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
No description provided.