Could someone point me to example of a multiplatfo...
# arrow
c
Could someone point me to example of a multiplatform (JVM + JS) project using optics?
1
I am able to use optics in a jvm project, but the instructions don't extend to multiplatform.
s
c
I don't understand these instructions at all. How do I extend
project(":test-processor")
to a scaffolded multiplatform project via IntelliJ.
s
project(":test-processor")
needs to be replaced by the
arrow-optics-ksp
dependency
c
I'll try this again, but I swore this gave me a very strange error.
s
So
add("kspCommonMainMetadata", "io.arrow-kt:arrow-optics-ksp-plugin:$arrowVersion")
c
Ohhhhhhh, I was doing
kspJvm
. I think I get it. Will try during my lunch. Thanks Simon!
I just get
Copy code
Project with path 'io.arrow-kt:arrow-optics-ksp-plugin:1.1.3' could not be found in root project
I think I put the core/optics depends in
commonMain
, i.e.
Copy code
val arrowVersion = "1.1.3"
kotlin {
    ...
    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation("io.arrow-kt:arrow-core:$arrowVersion")
                implementation("io.arrow-kt:arrow-optics:$arrowVersion")
            }
        }
    ...
}
Then at the bottom in
Copy code
dependencies {
    add("kspCommonMainMetadata", project("io.arrow-kt:arrow-optics-ksp-plugin:$arrowVersion"))
}
https://github.com/chiroptical/shoebill-app/blob/main/build.gradle.kts I made the code public to make it easier. This complains about jsMain not having optics. It is unclear how to deal with this situation from the documentation unfortunately.
I figured it out! https://kotlinlang.slack.com/archives/C5UPMM0A0/p1671547328597829?thread_ts=1671547058.508639&cid=C5UPMM0A0 you showed me the right way. I didn't listen, I had the second paramater wrapped in
project("io.arrow...")
🤦
Next step figure out how to use them in the
commonMain
code...
s
I thought that is what
kspCommonMainMetadata
was for, but I've not used KSP in KMP.
c
Copy code
Could not determine the dependencies of task ':jsTestPackageJson'.
> Could not resolve all dependencies for configuration ':jsTestNpm'.
   > Could not resolve io.arrow-kt:arrow-core:1.1.2.
     Required by:
         project :
      > No matching variant of io.arrow-kt:arrow-core:1.1.2 was found. The consumer was configured to find a usage of 'kotlin-runtime' of a library, preferably optimized for non-jvm, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'js', attribute 'org.jetbrains.kotlin.js.compiler' with value 'legacy' but:
          - Variant 'iosArm32ApiElements-published' capability io.arrow-kt:arrow-core:1.1.2 declares a library:
              - Incompatible because this component declares a usage of 'kotlin-api' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'native' and the consumer needed a usage of 'kotlin-runtime' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'js'
              - Other compatible attributes:
                  - Doesn't say anything about its target Java environment (preferred optimized for non-jvm)
                  - Doesn't say anything about org.jetbrains.kotlin.js.compiler (required 'legacy')
This is where I am now. Is there a better place to ask for help here?
s
Arrow doesn't publish
LEGACY
target only
IR
.
c
Now we are getting somewhere!
I see the
generated
directory now and can use optics in commonMain, but KSP throws an NPE. I probably have to configure the directories or something next.
I really appreciate your help here Simon. I am a noob with Kotlin. The language feels familiar but the tooling is still alien.
s
You probably want to do this:
Copy code
js(IR) {
  browser()
  nodejs()
}
We should probably update https://github.com/arrow-kt/Arrow-MPP-Template/blob/main/build.gradle.kts to include Optics & KSP 🤔
c
Mine is like,
Copy code
js(IR) {
        binaries.executable()
        browser()
    }
With
nodejs()
, I get
Copy code
Could not create task ':jvmProcessResources'.
> Task with name 'jsBrowserDistribution' not found in root project
Ohh, I probably just need to comment that part out?
s
Yes, if you're not using it then just remove it
js(IR) {
is the important bit
c
That worked, but I still get the NPE from KSP. I'll do some more research on that.
s
Can you try
1.1.4-rc2
?
c
Yeah, that seems to work!
What an adventure ha
s
Okay, then some fix was added for the NPE issue between 1.1.3 and 1.1.4 😅 1.1.4 will be released later this week, or first week of Jan.
Can you share your final setup? Would love to add this to the MPP template.
c
Absolutely. I still think I need to mess with the IDE settings but I think that should be easy
s
Setting up KSP for KMP is annoying 😕 The Google KSP / Jetbrains documentation for it is not great.
c
It isn't so bad that I had your help, but that isn't sustainable ha
Is there anything I can do to make this easier for others? Or are you planning on doing some documentation?
s
I think it would be great if we can set it up in the Arrow MPP template, and link that from the docs. If you're interested in contributing this, that would be awesome!
c
Yeah, I can definitely try doing that.
Question, do you have a more elegant approach to setting the source directories for common optics?
Copy code
sourceSets {
        val commonMain by getting {
            dependencies {
                kotlin.srcDir(makeKspDir("commonMain"))
                implementation("io.arrow-kt:arrow-core:$arrowVersion")
                implementation("io.arrow-kt:arrow-optics:$arrowVersion")
            }
        }
    }
where
Copy code
fun makeKspDir(name: String) = file("build/generated/ksp/metadata/$name/kotlin")
It seems like it should be possible to do this for every target (terminology?) but hard to find a solution via google.
Without these, you just get failures when trying to use the optics because the compiler can't find the companions.
Ohh, actually that works fine but the imports are pretty weird.
In
jvmMain
, a file
UseHello.kt
,
Copy code
package app.shoebill.application

import Hello
import value

val x = Hello(0)
val y = Hello.value.modify(x) { it + 1 }
The
import value
is pretty weird right? Is there no way to have packages in
commonMain
?
s
The
import value
is pretty weird right? Is there no way to have packages in
commonMain
?
Yes, that is possible. Are they not respected?
Question, do you have a more elegant approach to setting the source directories for common optics?
You can probably loop over the
kotlin.sourceSets
and set them that way in Gradle.
c
AFAICT, the generated code fails with a compilation error. I’ll update the template this morning and put together a potential bug report using it.
Okay, I think my issue was actually due to stale dependencies or something. I purged my
.gradle
and things are working again. I feel like everything is just a bit more fragile with multiplatform at the moment.
https://github.com/arrow-kt/Arrow-MPP-Template/pull/44 dependency update and optics additions 🙂