hey team, there's a new rust library we have to in...
# multiplatform
a
hey team, there's a new rust library we have to introduce into our kotlin multiplatform sdk, this library has only swift/android bindings or kmp binding that only contain ios/android impelementation. our sdk supports multiple targets including js. currently this library breaks compilation for js targets. is there a way to tell the compiler for that specific module that uses this rust library to not compile this library for other targets apart from ios/android and define some sort of mock implementation for the module interface for js targets? one thing to mention there's heavy logic in commonMain based on this rust lib that we don't want to duplicate in separate ios/android modules, so we need this rust dependency in commonMain. also we don't want to fork library as it's being constantly updated. this is the way we currently define dependency in that module:
Copy code
getByName("commonMain") {
            dependencies {
                implementation(libs...)
            }
        }
p
The rust library author is providing the kotlin wrapper or are you doing the kotlin wrapper/binder library? In the first scenario I would suggest them to include a JS target with an empty implementation, at least for compilation. If the second case, then add the js implementation. You can create a Library
target expander
module on your end that actually supports js. Then inside this module, use the library for Android/iOS and do your own JS implementation.
j
You could create an intermediate source set for iOS+Android to contain this common code that doesn't include JS.
a
thanks @Pablichjenkov, seems like a good idea to clarify with author, they're currently working on full support for js, but it doesn't seem like it going to be very soon. @Jeff Lockhart thanks for the suggestion, do you mean smth like this? I remember there were some differences with iOS sub-targets but on paper looks good
Copy code
kotlin {
    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation(libs.yourCommonDependencies)
            }
        }

        val iosAndroidCommonMain by creating {
            dependsOn(commonMain)
            dependencies {
                implementation(libs.rustlib)
            }
        }

        val iosMain by getting {
            dependsOn(iosAndroidCommonMain)
        }
        val androidMain by getting {
            dependsOn(iosAndroidCommonMain)
        }

        val jsMain by getting {
            dependsOn(commonMain)
            dependencies {
                implementation(libs.mockrustlib)//or code it in module itself
            }
        }
    }
}
j
Yes, exactly. Except you shouldn't have to explicitly set up the default source set hierarchy dependencies like
jsMain.dependsOn(commonMain)
. You just might need an explicit call to
applyDefaultHierarchyTemplate()
, since your usage of
dependsOn
prevents it from being applied by default. But even better, I prefer using the new source set hierarchy tree API, which is more concise and easier to read. It is still experimental, the API has just had a few minor mostly naming changes since it was introduced. You could do the same with:
Copy code
kotlin {
    @OptIn(ExperimentalKotlinGradlePluginApi::class)
    applyDefaultHierarchyTemplate {
        common {
            group("iosAndroidCommon") {
                withAndroidTarget()
                group("ios")
                // or withIos()
            }
        }
    }

    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation(libs.yourCommonDependencies)
            }
        }

        val iosAndroidCommonMain by getting {
            dependencies {
                implementation(libs.rustlib)
            }
        }

        val jsMain by getting {
            dependencies {
                implementation(libs.mockrustlib)//or code it in module itself
            }
        }
    }
}
group("ios")
ties the default hierarchy's intermediate
iosMain
source set in as the child source set, where
withIos()
connects all the iOS target source sets directly. I prefer the former.
👍 3