Xcode 15 Beta + Cycle inside <Target>; building could produce unreliable results

Feedback raised: FB12477645 — Reporting here for visibility of others.

I maintain a project that was failing to build in Xcode 15 beta 1/2. It failed with error:

Cycle inside <Target>; building could produce unreliable results.

I narrowed it down and reproduced in a new project with these 2 steps:

  1. Add blank build script phase with input files: $(TARGET_BUILD_DIR)/$(INFOPLIST_PATH)

  2. Add a binary SPM package like twilio-video-ios or medallia

Either of the steps on their own is OK, but when both are applied the build error occurs.

5 Likes

For what it's worth, it's still happening in Beta 3. We have two production apps that aren't building because of this :(

The issue is still present in beta 4.
I was using a build phase to inject values in Info.plist during the build and in Xcode 15 betas this results in a "cycle".

The workaround I came up with is using Info.plist preprocessor prefix file.
Instead of modifying Info.plist directly in the build phase, it now adds values to the prefix header

echo "#define KEY VALUE" > "${BUILT_PRODUCTS_DIR}/My-Info.plist-Prefix.pch"

And set $(BUILT_PRODUCTS_DIR)/My-Info.plist-Prefix.pch as an output file of the build phase.

Then, enable Preprocess Info.plist File build setting and set prefix file to the same path as in the build phase.
If everything is done correctly, Xcode will replace stubs in Info.plist with values from the prefix file.

This isn't a perfect solution, but at least it unblocks builds on Xcode 15.

1 Like

@azarovalex Thanks for replying. I encountered the same issue. Could you give a more specified clarification for each step? Thanks very much. :smiley:

Sure thing, @jonathanim.
Let's say you had a build phase that injected some dynamic value INJECTED_VALUE to Info.plist with a key PLIST_KEY. This is my use case that stopped working in Xcode 15 betas, and here is what I did as a workaround:

First, add this key to Info.plist with a mocked value that later will be replaced, let's say

<key>PLIST_KEY</key>
<string>MOCKED_VALUE</string>

Then change the build phase that previously modified the Info.plist to generate a .pch file:

echo "#define MOCKED_VALUE INJECTED_VALUE" > "${BUILT_PRODUCTS_DIR}/My-Info.plist-Prefix.pch"

Add $(BUILT_PRODUCTS_DIR)/My-Info.plist-Prefix.pch as an output file of the build phase.

Lastly, enable the "Preprocess Info.plist File" build setting in your target and set "Info.plist Preprocessor Prefix File" to the same prefix file $(BUILT_PRODUCTS_DIR)/Dash-Info.plist-Prefix.pch.

After following these steps Xcode will now substitute the value in your Info.plist with runtime generated values that the build phase is writing in the prefix header. Hope that solves your problem.

1 Like

Oh my goodness. This is a lifesaver post, I didn't know we could use precompiled headers in Info.plist and this worked a treat! Thank you!

2 Likes

This is still present in the Beta 5, - however for those with Crashlytics in their project, this might help:

This worked to make builds compile successfully for me, - might be worth checking to make sure it doesn't have any ill side effects for the Crashlytics functionality though

Not sure if it helps in your situation. I fixed this problem by following the answers in this post Cycle inside my app on XCode 15 be… | Apple Developer Forums

Check comments of Akira_Hayakawa_Atsurae.

In my case, the following solved the problem. I paid attention again to the order of the Build Phase. When I was checking the Build Phase, I found that the "Embed Foundation Extensions" (Widget Extension) related to WatchApp were last in the order. (RunScript was also executed in the middle). I noticed this and solved the problem by rearranging the order of Embed Foundation Extensions to be right after Copy Bundle Resources. 
2 Likes

Oh, thx, this helped in my case!