syncComposeResourcesForIos fails with "Failed to create directory"
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:
- iOS
Versions
- Kotlin version: 1.9.20-RC
- Compose Multiplatform version: 1.5.10-rc01
- Xcode 15.0
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)
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.
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.
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)
@chrisbanes Thank you for your investigation! it's helpful!
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.
@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 yes, agreed. I still think there's an opportunity to document this, and come up with the long term fix so that
syncComposeResourcesForIosworks in the sandbox.
Totally agree 👍🏼
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
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:
Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.