Hi, wondering if multi-module KMM module could be ...
# touchlab-tools
a
Hi, wondering if multi-module KMM module could be configured in a project. I’ve been trying to separate our common module out to smaller modules to no success. If I move out modules, some modules will have its own
cocoapods
intergration but the problem is I do not know how to integrate them back to a single
common
module without an issue. Just wondering if anyone has tried this out? Is it even possible at the moment? Would really appreciate any tips. Thanks in advance
a
I think the modules can be just a dependency and not have cocoapods integration, making your
shared
module have those modules as dependency
Only your
shared
module should have the cocoapods integration treat the other modules as a Gradle module as you normally would.
a
I have a scenario where I am wrapping a library (thats only present for android and ios) and bridging them to create a “KMM” common code that I could use. I would love to move this out as a separate module but the way I am handling it at the moment is through Cocoapods and Cinterop. I am assuming this isnt possible to do?
a
You mean the libraries you are wrapping are pulled from cocoapods right??
a
yes
a
I think you can. Have you tried separating it? What errors are you getting?
a
I did. I don’t know the correct way to integrate it back. The main common module generates a podspec file as well as the “library” module. I tried adding in the “library” pod inside the cocoapods of the main common module:
Copy code
cocoapods {
   ...
   pod("mylibrary", path = file("pathToLibrary")
   ...
}
But everytime I try to build the iOS app it just fails. The error is also not very descriptive as well (Or maybe I just don’t know how to read it.).
I also tried to integrate the “library” pod file directly to the iosApp pod file which looked like this:
Copy code
target 'iosApp' do
  use_frameworks!
  platform :ios, '...'
  pod 'common', :path => '../commonPath'
  pod 'mylibrary', :path => '../mylibraryPath'
end
this also throws the same error I get in the first approach.
a
Are you exposing your KMM as a cocoapods library??
a
I guess the answer is yes
a
The library you wanna wrap can be a module, but don't make it a cocoapods library but a Gradle lib that the
shared
can add as dependency.
a
how would I add the ios library then?
a
You can add the iOS library as a dependency to the wrapped module you wanna create
a
Sorry I’m not really too familiar with all the ios related things. Do you have some docs I could read or some steps to do this? Honestly already thankful for all the replies and help. Thank you very much. I worry about doing these additional steps to achieve what I want to do. I wonder how hard or easy that would be so I could evaluate if its worth it to proceed.
a
You are on the right path. You just have to figure out what the error is. If you can share, that'll be great
a
I can’t really share what I have now but I’ll try and create a sample project tom and share it here.
a
Aiit. according to this you are on track
r
I'm not completely following what you're doing. If you're just modularizing your Kotlin, you can do that at the gradle level and just have a single top-level module that you configure with cocoapods. If you need to modularize your iOS consumption as well (for example, creating multiple different frameworks that are consumed differently by different iOS apps), then things get more complicated. Are you using KmmBridge or any other Touchlab stuff in your project? It doesn't look like your issues are related to our tools, so you might get more help in #multiplatform since there's fewer people in this channel.
a
@russhwolf looks like im posting on the wrong channel sorry about that. Modularizing the common module at the gradle level is easy. I am already able to do it. The only problem I have now is that we are using a library on our project which is not a KMM compatible library but it has an Android Library and an iOS library counterpart. I need to be able to use the library in commonMain to avoid duplication. So what I did was add in the iOS library through cocoapods and add in the android library in androidMain. By doing this, I was able to create a commonMain bridging the two platform targets. This works well because initially I only have a single common module. I wanted to move this "bridging" code out of the common module to its own separate module. But it seems that since the commonModule still has a cocoapods implementation and so does the new "bridging" module, it could not work.
l
At my work, we have a multimodule project that has an ffmpeg module (using FFmpegKit via gradle/cocoapods on Android/iOS), so that should be similar to what you described. I set up the cocoapods plugin in the ffmpeg module and the ‘main’ module depends on the ffmpeg module and also uses the cocoapods plugin. This works well on our side.
I have noticed that the consuming app may have to also declare the cocoapods as well. I’m not sure that the generated cocoapods handles dependencies well (or at least didn’t a year ago, and I haven’t bothered to remove it in the PodFile).
Can you specify what the error is? I know that this workflow is possible, since I use it at work.
Let’s say that your main module is A and your convenience module is B. Your gradle for A should depend on B. If you want a consumer of A to be able to call methods from B, make sure to add
export(project(":B"))
to the framework block of the cocoapods config.
r
I think the issue is, A depends on B, A applies the cocoapods plugin, but B needs to use a pod dependency. Is that correct?
l
In that case, B should declare the pod dependency so it can be used inside of B. Then A can depend on B (using gradle) and call the methods B provides in commonMain.
a
how were you able to provide the cocoapods of :B to :A? In your project does :A also have its own cocoapods?
l
To give a more concrete example, in project-ffmpeg, I have expect/actuals for FFmpegKit that let me call methods. The project-ffmpeg build.gradle.kts uses the cocoapod plugin to pull in FFmpegKit (a cocoapod library). Now my mobileApp module build.gradle.kts has
implementation(project(":project-ffmpeg"))
in the commonMain dependencies. the mobileApp module also applies the cocoapods plugin so it can be used by the iOS app as a cocoapod.
Annoyingly, the mobileApp.podspec does not include FFmpegKit as a dependency. I found it best to add FFmpegKit to the iOS app’s PodFile.
At this point, the mobileApp module can call the methods defined by project-ffmpeg.
a
you mean, manually add it to the iosApp pod file? do i understand it correctly?
l
Yes.
a
i see thats what i was struggling to do. i was trying to integrate the generated podspec file of the, in this case, ffmpeg module to either the pod file of the iosApp or the :common module.
l
From what I see, the cocoapods plugin does not properly detect cross-module dependencies to add them to the podspec. I’d recommend not adding
pod("FFmpegKit")
to the mobileApp cocoapods block due to a bug in cinterop. A module that uses cinterop can’t correctly depend on a module that uses the same cinterop without errors.
You could probably add a gradle task to run after that updates the podfile with the dependencies you want.
I haven’t tested this, but I know that as of 1.7.20 (maybe 1.7.0, not entirely sure), you can customize the podspec with a custom property. You may be able to declare the dependency that way. Just avoid using the pod in a module that depends on another module that uses the same pod.
r
Yeah I think you could do
extraSpecAttributes["dependency"] = "XYZ"
in your cocoapods block if you want to get the dependency into your podspec. It probably won't work if you have more than one pod dependency though, because it's using a map internally
I don't remember when that was added but I think it was earlier than 1.7.20
a
wait just to clarify heres what i understand :iosApp podFile —- add mmfpeg-kit manually :common cocoapods { export(project(“:mmfpeg”) } commonMain { dependencies { implementation(“:mmfpeg”) } } :mmfpeg cocoapods { pod(“:mmfpeg-kit”) } did i understand it right?
l
That looks correct.
r
yeah I think that looks right
l
Keep in mind that the :ffmpeg module in this case needs to expose all FFmpegKit interactions through explicit methods. You won’t be able to access FFmpegKit (the original pod) from outside of :ffmpeg until they fix the cinterop bug.
But it sounds like that’s what you wanted anyways, since you wanted to use the original pod in commonMain. Also, just to clarify, FFmpegKit was just a concrete example that I’ve done and know works. For your case, replace FFmpegKit with your cocoapod.
a
yes ❤️ thank you very much @Landry Norris and @russhwolf i wont be able to try this now as its quite late now where i live but I will try this out tom. Thank you very kuch really appreciate all the help. ❤️ K
Just wanted to confirm that the setup above work ❤️ thank you to all who helped 😄
824 Views