touchlab-lab / KotlinCocoapods

Apache License 2.0
75 stars 6 forks source link

generateDummyFramework: resource must not be null #23

Open inickt opened 3 years ago

inickt commented 3 years ago

Hey all! Thanks for maintaining this plugin. I wanted to be able to export dependencies and use a dynamic framework for my project so this looks great.

I am having a problem integrating the plugin. For both my project and a clean clone of https://github.com/touchlab/KaMPKit I am unable to run the generateDummyFramework gradle task, which causes the podspec task to fail. I am using the Android Studio 4.2 Preview to work around some Big Sur issues. Here is a stacktrace:

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':shared:generateDummyFramework'.
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.lambda$executeIfValid$1(ExecuteActionsTaskExecuter.java:200)
    at org.gradle.internal.Try$Failure.ifSuccessfulOrElse(Try.java:263)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:198)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:179)
    at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:109)
    at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
    at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:62)
    at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
    at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56)
    at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
    at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
    at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
    at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:200)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:195)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:75)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:68)
    at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:153)
    at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:68)
    at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:62)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.lambda$call$2(DefaultBuildOperationExecutor.java:76)
    at org.gradle.internal.operations.UnmanagedBuildOperationWrapper.callWithUnmanagedSupport(UnmanagedBuildOperationWrapper.java:54)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:76)
    at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
    at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:41)
    at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:372)
    at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:359)
    at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:352)
    at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:338)
    at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.lambda$run$0(DefaultPlanExecutor.java:127)
    at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:191)
    at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:182)
    at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:124)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
    at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
    at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
Caused by: java.lang.IllegalStateException: resource must not be null
    at co.touchlab.kotlin.gradle.tasks.DummyFrameworkTask.copyResource(CocoapodsTasks.kt:159)
    at co.touchlab.kotlin.gradle.tasks.DummyFrameworkTask.copyFrameworkFile(CocoapodsTasks.kt:174)
    at co.touchlab.kotlin.gradle.tasks.DummyFrameworkTask.copyFrameworkFile$default(CocoapodsTasks.kt:173)
    at co.touchlab.kotlin.gradle.tasks.DummyFrameworkTask.create(CocoapodsTasks.kt:200)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...

Not sure why the dummy task is failing, it's working okay with the upstream Cocoapods plugin. Please let me know if there is any other information you need to help with debugging. Thanks!

extmkv commented 3 years ago

@inickt did you found the problem/solution?

inickt commented 3 years ago

@extmkv I did not. I am currently using the default Cocoapods plugin with the following in our build.gradle.kts:

    targets.withType<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget> {
        binaries.withType<org.jetbrains.kotlin.gradle.plugin.mpp.Framework> {
            isStatic = false
            export(project(":common"))
        }
    }

This lets us have a dynamic framework and export our other project in the framework, and we are manually maintaining the podspec based of the one generated from this plugin so everything works okay in Xcode.

extmkv commented 3 years ago

Thanks for the update @inickt !

I'm using the version 0.12 of the plugin, I notice the plugin is trying to copy the resource Header/placeholder.h but locally I've the Header/dummy.h

russhwolf commented 3 years ago

@inickt Are you certain that you're actually creating a dynamic framework there? The podspec that generates when I do similar indicates static. See https://github.com/touchlab/KaMPKit/blob/rw/official-cocoapods/shared/shared.podspec#L10

I'd like to understand this better to determine whether we should continue to maintain this fork or start pointing people back toward the official plugin.

inickt commented 3 years ago

@russhwolf From what I can tell I think its working? My main reasons for making a dynamic framework were to:

  1. make SwiftUI previews compile (https://github.com/JetBrains/kotlin-native/issues/3059)
  2. avoid duplicate symbol warnings (we use the shared library in a notification extension as well)

Everything seems ok right now (seeing a .framework in built app, the above 2 cases are fixed). I am manually maintaining our podspec file right now, so we have noPodspec() in our cocoapods configuration in build.grade.kts. That way I can delete the spec.static_framework line and keep the script to touch the framework.