Xcode 13 gives me a hard time building my project which consists of targets with build phases that generate code.
E.g. one build phase generates the file Secrets+Generated.swift
by simply using a shell script that echoes some code into that file.
The build phase defines that file as an output file. No input file, no input file list and no output file list, as only that one file is created/modified.
Almost all the time when building the project, the build fails:
error: input file '[ProjectPath]/Secrets+Generated.swift' was modified during the build
error: input file '[ProjectPath]/Secrets+Generated.swift' was modified during the build
Command CompileSwiftSources failed with a nonzero exit code
Has anyone encountered that issue or knows what to do? I tried toggling the checkbox "Based on dependency analysis", but that didn’t help. I didn’t have that issue when using Xcode 12. Interesting to note is the duplicate error message despite having only one build phase generating that particular file.
Btw. I get the same problem when using code generation tools like swiftgen, Sourcery or Cuckoo.
Edit: Here are my build phases:
The three marked build phases all generate one such file. All of them fail occasionally. I do not know if that makes a difference, but these are defined for only one target (Notification Service Extension) which is a dependency of my main app target, so it gets triggered only once when I build the app.
5
Answers
Had the exact same problem. I was able to solve it by changing the used shell from
/bin/sh
to/bin/zsh
. Don’t ask me why that works, though.EDIT 2:
Tom Lokhorst’s solution above seems to be the right way to resolve this: https://stackoverflow.com/a/69481200/12117100
EDIT:
There is an issue with the original solution. Xcode 12.5 users who try to build the test target will get the error
Build input file cannot be found...
as the script that generates GeneratedMocks.swift might be run after the build starts.Something that seems to work for both Xcode 12.5 and Xcode 13 is to add this to a
cuckoo-output.xcfilelist
(name it whatever you want) file:and add that xcfilelist to the Run Script’s Output File Lists instead of adding the path to
GeneratedMocks.swift
directly in Output Files.Original:
I had this issue after setting up Cuckoo for the first time in Xcode 13 and including
${PROJECT_DIR}/${PROJECT_NAME}Tests/GeneratedMocks.swift
in the Output Files section of the Run script.Removing the path from Output Files seems to do the trick for now.
I’ve experienced the same issue in the WooCommerce iOS project the aggregate target we use to generate a
.swift
file with secrets at build time.This PR seems to fix the issue. I say seems because I haven’t experienced it since, but I am also not 100% sure that the issue is gone, because it wasn’t occurring 100% of the builds for me.
What I think might have done the trick was making the build phase run script input and output files definition homogeneous. Previously, we set the inputs via
.xcfilelist
and outputs via the Xcode UI. Now we use a.xcfilelist
for both.Honestly, this seems like an Xcode bug to me 🙊
Unfortunately the proposed workaround by Copripop does not work at least for the setup with Cuckoo. But the compile error occurs much more seldom now.
But I got an official answer from apple that this error occurs as expected because the input file is modified during the build job. As I understood that happens because the build phases can run in parallel. Before Xcode 13 the parallel execution was avoided when the output file definition fit to the input file of the next phase with the same file. This seems to be broken in Xcode 13.
Nevertheless the answer contained a hint about how to solve the problem for not Cuckoo setups. It recommends to use build rules, which are executed during the compile build phase. Here the link with a time marker for this topic: https://developer.apple.com/videos/play/wwdc2021/10210/?time=379
The build rule can be defined as matching the source file by naming convention and then run the script correctly. The output files from the build rules are automatically set to the compile build phase. So this should not be defined there.
Hopefully this helps some people to solve the problem, when they are able to define a match by naming convention. I did not find a good approach for Cuckoo.
Btw: There is already an issue opened for Cuckoo: https://github.com/Brightify/Cuckoo/issues/400
I’m debugging a similar issue in R.swift, I think I’ve found the cause of the issue.
Xcode 13 appears to execute Run Script build phases during index builds. This can cause a file to be written to by an index pass, in parallel with a build.
To check if this is happening for you, add this to your build script:
say $ACTION
On Xcode 12, it only says "build", but in Xcode 13 I hear it saying "indexbuild" during compilation, whenever I save .swift files or otherwise navigate through my code.
To prevent your script from running during indexing, add this check: