icerockdev / moko-kswift

Swift-friendly api generator for Kotlin/Native frameworks
https://moko.icerock.dev
Apache License 2.0
350 stars 21 forks source link

At which phase code is actually being generated? I need to run build 2 times #87

Closed radimjanda754 closed 1 year ago

radimjanda754 commented 1 year ago

With clean project currently I need to run build 2 times, at first the code is generated inside build/cocoapods/framework/sharedSwift folder and just after I use pod install the code appears properly in Pods section in xcode.

If I use pod install before first build, then no code is still generated.

Is there some solution to not run whole build 2 times? Can I run just some specific command before running pod install and then run full build?

Alex009 commented 1 year ago

Hello! Now I'm going to explain how the plugin works and the integration process through CocoaPods, so that you can better understand how to use it most effectively.

The Gradle plugin adds an extra action at the end of the link***Framework task. During this action, it generates Swift code for the assembled framework. Here, there is a peculiarity of how Gradle works - if the task is not meant to be executed (for example, because the framework has already been successfully compiled), then the additional action will not be performed. This means that when your framework is already compiled and you change the KSwift Gradle settings but don't alter the Kotlin code, the Swift files will not get updated. In this case, you either need to make a change in the Kotlin code (so the framework is recompiled) or delete the current framework located in the build/bin path.

Next, after the Gradle KSwift plugin has completed its work and generated Swift code in build/bin/<arch>/sharedSwift, another plugin, the cocoapods gradle plugin, takes over. It transfers the content of the build/bin/<arch> folder to the build/cocoapods folder, from where the cocoapods (not the gradle plugin, but the ruby application) will pick up both the framework and the generated Swift files.

The final step involves CocoaPods - when we execute pod install, the cocoapods utility does two things - for our Kotlin framework, it looks at the assembled framework and adds to the Xcode target, which triggers recompilation of the Kotlin framework through Gradle when the Xcode target itself is compiled. The second thing involves our other cocoapod - sharedSwift (where the generated Swift files reside). For this cocoapod, it reads the source directory (i.e., the folder where the generated Swift files are located) and creates an Xcode target with the files found at that moment, as well as establishes a link from sharedSwift to the shared Xcode target. That is, the set of generated Swift files that will make it into Xcode is determined exactly at the moment of the pod install call.

In summary, the most efficient way to use KSwift is as follows:

  1. Configure all filtering options and features in Gradle
  2. Write code in Kotlin
  3. Initially assemble the framework. For example, manually call link***Framework, after which you can ensure that there is a folder with Swift files in build/bin/<arch>
  4. Invoke podspec to generate the podspec and copy the generated files to the cocoapods folder.
  5. Execute pod install.

If you've created a new Kotlin module or connected a new dependency for which new generated files should exist, you need to re-run pod install after successfully generating Swift files.

I understand and agree that the current usage is not convenient or simple, but I hope that by understanding the mechanics of the process, it will be easier for you to use the plugin. In the future, I hope we can find a way to simplify the integration.

radimjanda754 commented 1 year ago

Okay, thank you, I found the generated code build/bin/<arch> originally I was looking only into the cocoapods directory where it wasnt after running link***Framework