JetBrains / compose-multiplatform

Compose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.
https://jetbrains.com/lp/compose-multiplatform
Apache License 2.0
15.79k stars 1.14k forks source link

syncComposeResourcesForIos fails with "Failed to create directory" #3829

Open chrisbanes opened 10 months ago

chrisbanes commented 10 months ago

Describe the bug In my PR to upgrade to Kotlin 1.9.20-RC &CMP 1.5.10-rc01, the build now fails every time.

Affected platforms Select one of the platforms below:

Versions

To Reproduce

https://github.com/chrisbanes/tivi/pull/1588 triggers this every build from Xcode.

error: Failed to create directory '/Users/chris.banes/Library/Developer/Xcode/DerivedData/Tivi-enhntrsefxvbgvajmmdntgymofur/Build/Products/Debug-iphonesimulator/Tivi dev.app/compose-resources'

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':shared:qa:syncComposeResourcesForIos'.
> Failed to create directory '/Users/chris.banes/Library/Developer/Xcode/DerivedData/Tivi-enhntrsefxvbgvajmmdntgymofur/Build/Products/Debug-iphonesimulator/Tivi dev.app/compose-resources'

* Try:
> Run with --info or --debug option to get more log output.
> Get more help at https://help.gradle.org.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':shared:qa:syncComposeResourcesForIos'.
    at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:38)
    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:204)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:199)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
    at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
    at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
    at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:78)
    at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
    at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:42)
    at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:331)
    at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:318)
    at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.lambda$execute$0(DefaultTaskExecutionGraph.java:314)
    at org.gradle.internal.operations.CurrentBuildOperationRef.with(CurrentBuildOperationRef.java:80)
    at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:314)
    at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:303)
    at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:463)
    at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:380)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
    at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)

Caused by: org.gradle.api.UncheckedIOException: Failed to create directory '/Users/chris.banes/Library/Developer/Xcode/DerivedData/Tivi-enhntrsefxvbgvajmmdntgymofur/Build/Products/Debug-iphonesimulator/Tivi dev.app/compose-resources'
    at org.gradle.util.internal.GFileUtils.mkdirs(GFileUtils.java:322)
    at org.gradle.internal.execution.steps.CreateOutputsStep.ensureOutput(CreateOutputsStep.java:57)
    at org.gradle.internal.execution.steps.CreateOutputsStep.access$000(CreateOutputsStep.java:28)
    at org.gradle.internal.execution.steps.CreateOutputsStep$1.visitOutputProperty(CreateOutputsStep.java:42)
    at org.gradle.api.internal.tasks.execution.TaskExecution.visitOutputs(TaskExecution.java:348)
    at org.gradle.internal.execution.steps.CreateOutputsStep.execute(CreateOutputsStep.java:39)
    at org.gradle.internal.execution.steps.CreateOutputsStep.execute(CreateOutputsStep.java:28)
chrisbanes commented 10 months ago

I've checked and the directory /Users/chris.banes/Library/Developer/Xcode/DerivedData/Tivi-enhntrsefxvbgvajmmdntgymofur/Build/Products/Debug-iphonesimulator/Tivi dev.app does exist.

I can call mkdir -p /Users/chris.banes/Library/Developer/Xcode/DerivedData/Tivi-enhntrsefxvbgvajmmdntgymofur/Build/Products/Debug-iphonesimulator/Tivi dev.app/compose-resources just fine too. Seems to be something weird going on with Gradle or Java.

chrisbanes commented 10 months ago

I think I've worked this out. The ENABLE_USER_SCRIPT_SANDBOXING build setting in Xcode seems to have changed it's default value to true in Xcode 15 (or it prompted me to set it), which means that any run scripts are sandboxed.

From https://www.wwdcnotes.com/notes/wwdc22/110364/:

enable the build setting ENABLE_USER_SCRIPT_SANDBOXING to block shell scripts phases from accidentally accessing source files (PROJECT_DIR) and intermediate build objects, unless those are explicitly declared as an input or output for the phase

I've tried setting ENABLE_USER_SCRIPT_SANDBOXING to off in my project, but I'm still seeing the error. Might need to wipe all of the build caches.

Long term it seems that we either have to turn sandboxing off and document it for users (probably not a great idea), or the embedAndSignAppleFrameworkForXcode needs to output a 'output file list' which we can point Xcode to.

chrisbanes commented 10 months ago

Update: so disabling ENABLE_USER_SCRIPT_SANDBOXING does work, but my Gradle daemon was still being sandboxed as it was created from when ENABLE_USER_SCRIPT_SANDBOXING was turned on.

i.e. if you hit this, turn off ENABLE_USER_SCRIPT_SANDBOXING and kill any running Gradle daemons (./gradlew --stop)

eymar commented 10 months ago

@chrisbanes Thank you for your investigation! it's helpful!

GuilhE commented 10 months ago

I don't believe this issue is specific to compose-multiplatform because I encountered the same problem after updating to Xcode 15. I also discovered that iOS developers were facing the same issue: https://stackoverflow.com/a/76434029/1423773 and https://github.com/CocoaPods/CocoaPods/issues/11946. in my case, just switching that flag to false worked.

chrisbanes commented 10 months ago

@GuilhE yes, agreed. I still think there's an opportunity to document this, and come up with the long term fix so that syncComposeResourcesForIos works in the sandbox.

GuilhE commented 10 months ago

@GuilhE yes, agreed. I still think there's an opportunity to document this, and come up with the long term fix so that syncComposeResourcesForIos works in the sandbox.

Totally agree 👍🏼

ngallazzi commented 9 months ago

Same here for a Kotlin Multiplatform project

> Task :shared:embedAndSignAppleFrameworkForXcode FAILED
error: Failed to create directory '/Users/nicolagallazzi/Library/Developer/Xcode/DerivedData/iosApp-aymhszjracyejsdcwymwesnnbasx/Build/Intermediates.noindex/ArchiveIntermediates/Development/InstallationBuildProductsLocation/Applications/Babaco Market - Dev.app/Frameworks'

XCode 15, multiplaform plugin version 1.9.10

GuilhE commented 6 months ago

At least now it's "documented":

error: Sandbox environment detected (ENABLE_USER_SCRIPT_SANDBOXING = YES). It's not supported so far.
FAILURE: Build failed with an exception.

But Xcode is always trying to make us turn it on:

Screenshot 2024-02-15 at 17 40 06

okushnikov commented 1 month ago

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.