Skip to content
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

Fix serialization using standalone kotlinx compiler #2690

Merged
merged 6 commits into from
Apr 12, 2021

Conversation

peternewman
Copy link
Collaborator

@peternewman
Copy link
Collaborator Author

I'm assuming this works on GitHub actions too, but it doesn't run as it only goes on master.

Copy link
Member

@FloEdelmann FloEdelmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It works correctly on my Ubuntu machine, so it should also work fine on GitHub actions.

It works fine without a change, too, though 😅
How is the linked issue triggered for you? When you run this from the command line?

kotlinc -script -Xplugin=/snap/kotlin/current/lib/kotlinx-serialization-compiler-plugin.jar .github/generate-quest-list.main.kts

@peternewman
Copy link
Collaborator Author

peternewman commented Mar 29, 2021

It works correctly on my Ubuntu machine, so it should also work fine on GitHub actions.

Cool.

It works fine without a change, too, though sweat_smile

Odd. Other changes to the code fix it for me too I think (not sure exactly what) I think that was just some poor testing.

How is the linked issue triggered for you? When you run this from the command line?

Indeed. Well nearly the same as that:

kotlinc -script -Xplugin=/snap/kotlin/current/lib/kotlinx-serialization-compiler-plugin.jar .github/generate-quest-list.main.kts

Like so (using kotlin-compiler-1.4.31.zip):

~/Downloads/kotlinc/bin/kotlinc -script -Xplugin=/home/user/Downloads/kotlinc/lib/kotlinx-serialization-compiler-plugin.jar .github/generate-quest-list.main.kts
kotlinx.serialization.SerializationException: Serializer for class 'ApiResult' is not found.
Mark the class as @Serializable or provide the serializer explicitly.
	at kotlinx.serialization.internal.Platform_commonKt.serializerNotRegistered(Platform.common.kt:91)
	at kotlinx.serialization.internal.PlatformKt.platformSpecificSerializerNotRegistered(Platform.kt:29)
	at kotlinx.serialization.SerializersKt__SerializersKt.serializer(Serializers.kt:59)
	at kotlinx.serialization.SerializersKt.serializer(Unknown Source)
	at Generate_quest_list_main.getWikiTableContent(generate-quest-list.main.kts:269)
	at Generate_quest_list_main.main(generate-quest-list.main.kts:36)
	at Generate_quest_list_main.<init>(generate-quest-list.main.kts:27)

Is this some weird path/include thing as I'm just running it from the zip?

@FloEdelmann
Copy link
Member

FloEdelmann commented Mar 29, 2021

Is this some weird path/include thing as I'm just running it from the zip?

Hmm, not sure.

Can we completely avoid the compiler plugin by calling the serializer function explicitly? That probably also means dropping the @Serializable annotations.

Then calling the script would be much easier:

- kotlinc -script -Xplugin=/path/to/kotlinx-serialization-compiler-plugin.jar .github/generate-quest-list.main.kts
+ kotlinc -script .github/generate-quest-list.main.kts

@smichel17
Copy link
Member

smichel17 commented Mar 29, 2021

I recently encountered a similar error when trying to build StreetComplete. For me it was about the system Java version (openjdk 11.0.10), which did not match the version Android was expecting. I fixed it by pointing gradle to Android Studio's version of Java (openjdk version "1.8.0_242-release") instead. I added this arg when calling gradle (your path will be different): -Dorg.gradle.java.home="/var/lib/flatpak/app/com.google.AndroidStudio/current/active/files/extra/android-studio/jre/"

@peternewman
Copy link
Collaborator Author

Based on this diff:

178a179
> @Serializable
180a182
> @Serializable
191c193
<     return Json.decodeFromString<ApiResult>(jsonString).parse.wikitext
---
>     return Json.decodeFromString(ApiResult.serializer(), jsonString).parse.wikitext

Then calling the script would be much easier:

- kotlinc -script -Xplugin=/path/to/kotlinx-serialization-compiler-plugin.jar .github/generate-quest-list.main.kts
+ kotlinc -script .github/generate-quest-list.main.kts

That fails for me with:

~/Downloads/kotlinc/bin/kotlinc -script .github/generate-quest-list.main.kts
error: not enough information to infer type variable T (generate-quest-list.main.kts:191:17)
error: unresolved reference: serializer (generate-quest-list.main.kts:191:44)
.github/generate-quest-list.main.kts:191:17: error: not enough information to infer type variable T
    return Json.decodeFromString(ApiResult.serializer(), jsonString).parse.wikitext
                ^
.github/generate-quest-list.main.kts:191:44: error: unresolved reference: serializer
    return Json.decodeFromString(ApiResult.serializer(), jsonString).parse.wikitext
                                           ^

I recently encountered a similar error when trying to build StreetComplete. For me it was about the system Java version (openjdk 11.0.10), which did not match the version Android was expecting.

They definitely won't match, is Kotlin not standalone (it's all a bit new to me), but I'm not using Gradle at all, just running that script directly.

@westnordost
Copy link
Member

The serializer for a class marked with @Serializable are not created via reflection but using a gradle plugin. Thus, to execute that plugin is mandatory.

@peternewman
Copy link
Collaborator Author

The serializer for a class marked with @Serializable are not created via reflection but using a gradle plugin. Thus, to execute that plugin is mandatory.

So I think you're saying that @FloEdelmann 's suggestion in #2690 (comment) won't work @westnordost ?

@westnordost
Copy link
Member

No, I don't know. I just stated how the kotlinx-serialization library works. I'd like to leave the rest for @FloEdelmann as I don't have an overview of this code involved here and also never tried to execute it myself.

@FloEdelmann
Copy link
Member

FloEdelmann commented Apr 7, 2021

@peternewman I still don't get why the change would be necessary. The unchanged code works fine on the Ubuntu-based GitHub Actions runner.

The changed code also works fine when running from the command line, but when editing the file inside Android Studio, it's complaining about two issues:

  1. grafik

  1. grafik

Are you sure that it's not a missing configuration on your machine?

@FloEdelmann
Copy link
Member

Interestingly, both versions seem to work fine with or without the -Xplugin parameter on my machine now:

$ kotlinc -script -Xplugin=/snap/kotlin/current/lib/kotlinx-serialization-compiler-plugin.jar .github/generate-quest-list.main.kts
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.intellij.util.ReflectionUtil to method java.util.ResourceBundle.setParent(java.util.ResourceBundle)
WARNING: Please consider reporting this to the maintainers of com.intellij.util.ReflectionUtil
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
$ kotlinc -script .github/generate-quest-list.main.kts
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.intellij.util.ReflectionUtil to method java.util.ResourceBundle.setParent(java.util.ResourceBundle)
WARNING: Please consider reporting this to the maintainers of com.intellij.util.ReflectionUtil
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

@peternewman
Copy link
Collaborator Author

The changed code also works fine when running from the command line, but when editing the file inside Android Studio, it's complaining about two issues:

Hmm, does it provide any suggestions for how to fix it? So does it actually not run from within Android Studio in that state?

Are you sure that it's not a missing configuration on your machine?

No, and admittedly trying to replicate the same fault on the Ubuntu runner, I can't manage to, even when making it as similar as possible to my machine (i.e. no configuration (apart from what the runner has built in, just checking out the code and downloading and extracting the zip):
https://github.com/peternewman/StreetComplete/runs/2297950539?check_suite_focus=true

Interestingly, both versions seem to work fine with or without the -Xplugin parameter on my machine now:

Are you sure it's actually recompiling? During some of this testing, I've grown increasingly suspicious that it's secretly caching some stuff somehow/somewhere, e.g. it sometimes seems to arbitrarily break or work for no discernible reason.

Doing the following on a clean checkout, to revert my change seems to consistently break it, regardless of the paths and locations of the compiler and plugin:
git checkout -- .github/generate-quest-list.main.kts

I'm sort of out of ideas for how to troubleshoot it at my end and confused how this fix works for me but isn't required on the runner etc.

See also Kotlin/kotlinx.serialization#1125

@peternewman
Copy link
Collaborator Author

Edit @FloEdelmann . I've found a far simpler fix, which makes just as much sense in that I've swapped the order of the classes so it's not used before it's been defined, which seems reasonable and fixes my issue. Is this acceptable to you (and I guess more importantly does it not break stuff for you)?

@FloEdelmann
Copy link
Member

It now throws an error for me, while on the master branch, it works fine 🙁

$ kotlinc -script -Xplugin=/snap/kotlin/current/lib/kotlinx-serialization-compiler-plugin.jar .github/generate-quest-list.main.kts
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.intellij.util.ReflectionUtil to method java.util.ResourceBundle.setParent(java.util.ResourceBundle)
WARNING: Please consider reporting this to the maintainers of com.intellij.util.ReflectionUtil
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
kotlinx.serialization.SerializationException: Serializer for class 'ApiResult' is not found.
Mark the class as @Serializable or provide the serializer explicitly.
        at kotlinx.serialization.internal.Platform_commonKt.serializerNotRegistered(Platform.common.kt:91)
        at kotlinx.serialization.internal.PlatformKt.platformSpecificSerializerNotRegistered(Platform.kt:29)
        at kotlinx.serialization.SerializersKt__SerializersKt.serializer(Serializers.kt:59)
        at kotlinx.serialization.SerializersKt.serializer(Unknown Source)
        at Generate_quest_list_main.getWikiTableContent(generate-quest-list.main.kts:269)
        at Generate_quest_list_main.main(generate-quest-list.main.kts:36)
        at Generate_quest_list_main.<init>(generate-quest-list.main.kts:27)

@peternewman
Copy link
Collaborator Author

That's odd, as it works fine on multiple action runners:
https://github.com/peternewman/StreetComplete/actions/runs/730769889

😕

@westnordost
Copy link
Member

westnordost commented Apr 8, 2021

Are you both taking into account that kotlinx-serialization once on build creates the serializer-classes for classes annotated with @Serializable and then these serializers are available in the build cache? (so f.e. if you then launch the script without first running the gradle plugin, it will probably work)

I don't know exactly how you start the script and how the GitHub actions work, I just want to point out that if you want to reproduce a problem with running the script, you should make sure that the build cache is cleared before each new run.

@peternewman
Copy link
Collaborator Author

Are you both taking into account that kotlinx-serialization once on build creates the serializer-classes for classes annotated with @Serializable and then these serializers are available in the build cache? (so f.e. if you then launch the script without first running the gradle plugin, it will probably work)

I wasn't aware, but that confirms my theory:

Are you sure it's actually recompiling? During some of this testing, I've grown increasingly suspicious that it's secretly caching some stuff somehow/somewhere, e.g. it sometimes seems to arbitrarily break or work for no discernible reason.

Having a look, there is some stuff in ~/.cache/main.kts.compiled.cache/ but even having cleared that out it's building fine for me (and has started repopulating, so it's clearly the right place) with my current proposed fix.

I don't know exactly how you start the script

The workflow just runs these commands:

- run: sudo snap install kotlin --channel=1.4/stable --classic
- run: kotlinc -script -Xplugin=/snap/kotlin/current/lib/kotlinx-serialization-compiler-plugin.jar .github/generate-quest-list.main.kts

and how the GitHub actions work

Unless you do some config to make them do otherwise, they spin up a clean image, check out the code from git and then run the command, i.e. it's a clean slate with no previous cached data.

Copy link
Member

@FloEdelmann FloEdelmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, clearing the ~/.cache/main.kts.compiled.cache/ directory does the trick!

Then this looks fine :)
I like that it's just a simple line swap.

@westnordost westnordost merged commit 9d8b615 into streetcomplete:master Apr 12, 2021
@peternewman
Copy link
Collaborator Author

Thanks for the merge @westnordost .

Indeed, clearing the ~/.cache/main.kts.compiled.cache/ directory does the trick!

Glad to hear it @FloEdelmann

Then this looks fine :)
I like that it's just a simple line swap.

I have to admit that clearing my cache also fixed both of them (original and this) for me (I suspect I didn't have the plugin probably in the path, or possibly used the wrong one when I first ran it, so it cached a failed build). Although it still seems sense to not use them before we define them anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants