Search code examples
androidkotlinunity-game-engine

Build error Unity3d Android (kotlinx-coroutines-core-jvm VS kotlinx-coroutines-core)


I have next error in my Android application build:

Execution failed for task ':unityLibrary:mergeReleaseJavaResource'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.MergeJavaResWorkAction
   > 2 files found with path 'META-INF/kotlinx_coroutines_core.version' from inputs:
      
   - .../Library/Bee/Android/Prj/IL2CPP/Gradle/unityLibrary/libs/org.jetbrains.kotlinx.kotlinx-coroutines-core-jvm-1.7.1.jar
      
   - .../Library/Bee/Android/Prj/IL2CPP/Gradle/unityLibrary/libs/org.jetbrains.kotlinx.kotlinx-coroutines-core-1.7.1.jar

     Adding a packagingOptions block may help, please refer to
     https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.PackagingOptions.html
     for more information

I managing the dependencies with Google jar-resolver. Both org.jetbrains.kotlinx.kotlinx-coroutines-core-1.7.1.jar and org.jetbrains.kotlinx.kotlinx-coroutines-core-jvm-1.7.1.jar are transitive dependencies. I can exclude one of them, but which one? And is it safe? What is difference between jvm and regular versions for these?

P.S. This error becomes appear after I update AdMob plugin, so one of them should be a dependency of the AdMob.


Solution

  • Why this is happening?

    There are two libs, that are mentioned in the question. You can download them here(core) and here(core-jvm). If you unarchive any of them as a zip archive, you see, that there is folder META-INF inside both of them and file kotlinx_coroutines_core.version there. Generally, almost every jar dependency contains file META-INF/*package_name*.version. But speaking about these two, their files have the same name. IMHO, it's some kind of a mistake made by developers. Probably, jvm lib would have *-jvm postfix in version file also. Anyway, it is what it is, and we can do nothing with jar dependencies.

    Because of this, your build system(Unity3d or any) doesn't know what file should be taken and do fail a build process.

    Also, these libraries are not the same, and it is wrong to exclude any of them. Such solution may lead to build crashes, wrong behaviour and so on.

    How to fix?

    The easiest way to fix this is to add exclude('META-INF/kotlinx_coroutines_core.version') method to your gradle script in packagingOptions section, as it mentioned in the error message. When you do this, gradle don't add any META-INF/kotlinx_coroutines_core.version from any dependency, so there is not be a conflict.

    Speaking about Unity3d, depends on your project structure you have to add packagingOptions section to either mainTemplate.gradle or launcherTemplate.gradle or both of them. Check this link to discover how to work with gradle templates in Unity3d https://docs.unity3d.com/Manual/gradle-templates.html

        packagingOptions {
               exclude('META-INF/kotlinx_coroutines_core.version')
        }
    

    This will lead to lack of metadata for your build, that, potentially, can raise some new exotic issues, but I do not know a better solution. (Maybe some merge script or something)

    This is a generic solution for such kind of problems. BUT! In this specific case, it is better to use pickFirst instead of exclude. Both of your dependencies has the same version, so instead of just exclude info about versions, you can just take any of them. This prevents lack of metadata for your build and is much more safety in terms of build consistency.

        packagingOptions {
               pickFirst('META-INF/kotlinx_coroutines_core.version')
        }