Xcode 13.2b2 - Swift build system integration fails to recognise availability checks

I'm unsure if this is specifically an Xcode bug or a bug with the Swift build system, however the beta version of Xcode 13.2 states in the release notes:

  • The build system and Swift compiler have a new mode that better utilizes available cores, resulting in faster builds for Swift projects. The mode is opt-in, and you can enable globally with the following user default:
defaults write com.apple.dt.XCBuild EnableSwiftBuildSystemIntegration 1

Please report any issues with the new build system mode through Feedback Assistant. (84467780)

Of course I wanted to try this out - unfortunately, it looks like enabling this causes Xcode to not recognise if #available checks correctly where the version you are checking is higher than the package platform/minimum deployment target of what you are trying to build.

For example, trying to build the CustomDump library with EnableSwiftBuildSystemIntegration turned on results in it failing to compile for iOS, complaining that certain APIs are only available on iOS 14, even though those calls are wrapped in an if #available(iOS 14) check:

CustomDump has a minimum iOS deployment target of iOS 13.

I have a similar problem with the PhoneNumberKit library, where iOS 11 availability checks break in a similar way. This library has a minimum deployment target of iOS 9.

In both cases, the error can be fixed by increasing the platform/deployment target to at least whatever version is failing in the availability check.

Feedback filed: FB9764935


Yup. Same here. FB9764703


Thanks for giving the new integration a try. We're tracking this issue already. It probably got fixed in [Sema] Generate TRC for unparsed functions right before type-checking by xymus · Pull Request #39337 · apple/swift · GitHub.
Thanks for the reports, we'll update through Feedback Assistent once we think it should be fixed.

There are two potential workarounds:

  1. Move the #availability checks to a function and call that from the didSet/computed property context.
  2. This is probably not a realistic option but setting the deployment target high enough (SDK version for example) should also work around.

The line that is failing in the screenshot is not in a didSet so it doesn’t look like the problem is just that.

Unfortunately these workarounds aren’t much help when we are dealing with third party code and I wouldn’t expect libraries to ship new versions with a workaround for this bug so I guess we will just have to wait until it’s fixed.

Xcode 13.2 RC works for me, however there is a new bug (FB9803912):

  1. In a large mixed project where you're using a pre-compiled header file (.pch): while the app is building (CMD+B), modify a .h by adding / removing a character
  2. Build will stop with errors such as "xxxxx.h has been modified since the precompiled header ... was built"
  3. If you now try and build again (CMD+B) build repeatedly fails with the same build errors (including several others such as Dependency 332 failed with value failedCommand.

The only workaround is to clean build first and then build. In the past, if this would ever happen, building again would clear whatever cache there was.

Can confirm this problem seems to be fixed in 13.3, I've not tried the 13.2 RC. Not had any issues with our project yet although didn't see massive speed improvements on a clean build on an 8 core iMac Pro - a reduction from 132 to 125s. Should I be seeing better? I'm about to try it on an M1 Max to see if its any better.

UPDATE: Our project builds a lot quicker on an M1 Max but still only seeing marginal improvements on a clean build with timing summary enabled. Down from 78s to 72s.

The new build system integration is designed to help with multicore scaling. The more cores, the larger the effect. My 10/20 iMac saw about a 15% improvement while my M1 Max saw only about 5%, so I think this is expected.

In comparison, fewer cores (> 1 of course) should still result in faster compilation, provided the individual cores have higher clock speeds and overall CPU <-> RAM / cache latency is low (where both should be true for a M1 Max with its unified architecture). During a clean build, my understanding is that the time it takes to perform other processes such as provisioning, planning, building dependency graphs, building pre-compiled headers (in a mixed project) etc are all excluded from these optimizations as this support is purely added to the swift compilation step (it's able to figure out dependency graphs better and seems to be able to compile independent build-graphs in parallel, provided there are enough cores).

I'm certainly seeing improvement in between builds, even for a large mixed project.

The bug I posted above has not been fixed as of Xcode 13.3 beta 2, and so each time I fall into that trap (which I seem to every hour), I need to perform a clean build to get it to build again, which seems to take roughly the same time it did in Xcode 13.1 without the multicore scaling option. So I've had to unfortunately keep this option turned off :(