airbnb / lottie-ios

An iOS library to natively render After Effects vector animations
http://airbnb.io/lottie/
Apache License 2.0
25.76k stars 3.75k forks source link

lottie-spm compilation fails with Xcode 14.3 beta #1963

Closed ilendemli closed 1 year ago

ilendemli commented 1 year ago

Which Version of Lottie are you using?

Lottie 4.1.3

Expected Behavior

Project to compile without errors

Actual Behavior

Project does not compile because of unsupported SDK by the compiler

Xcode 14.3 beta has been released and Lottie fails to compile with the following error: Failed to build module 'Lottie'; this SDK is not supported by the compiler (the SDK is built with 'Apple Swift version 5.5.2 (swiftlang-1300.0.47.5 clang-1300.0.29.30)', while this compiler is 'Apple Swift version 5.8 (swiftlang-5.8.0.117.11 clang-1403.0.22.8.60)'). Please select a toolchain which matches the SDK.

Might be a solution for future releases: https://stackoverflow.com/a/70562356/3928565

PS: I am using the lottie-spm integration in my project

calda commented 1 year ago

This looks like a bug in Xcode 14.3, considering this works correctly in Xcode 14.2.

For now if you need to use the Xcode 14.3 beta i'd suggest using lottie-ios instead of lottie-spm. I'll file a feedback with Apple to let them know about this regression.

calda commented 1 year ago

Filed as FB11994464

SajjadKharrazi commented 1 year ago

what about Xcode 14.3 beta 2?

ilendemli commented 1 year ago

@SajjadKharrazi still fails to compile

florentmorin commented 1 year ago

Still fail with Xcode 14.3 beta 3.

tshortli commented 1 year ago

I'll grant that it's not super intuitive, but when you see an error like

Failed to build module 'Lottie'; this SDK is not supported by the compiler (the SDK is built with 'Apple Swift version 5.5.2 (swiftlang-1300.0.47.5 clang-1300.0.29.30)', while this compiler is 'Apple Swift version 5.8 (swiftlang-5.8.0.117.11 clang-1403.0.22.8.60)'). Please select a toolchain which matches the SDK

It indicates that there's something wrong with the textual interface of the module. There should be other errors earlier in the build log that indicate the underlying problems. I reproduced this and all of the errors are duplicates of this:

/Users/allan/Library/Developer/Xcode/DerivedData/lottie-spm-main-blvyxsipwvcwbufoycfdhvhokztd/Build/Products/Debug/Lottie.framework/Modules/Lottie.swiftmodule/arm64-apple-macos.swiftinterface:260:17: 'MainActor' is only available in macOS 10.15 or newer

It looks like Lottie is missing @availability annotations for its APIs that are annotated @MainActor. Note that this will only reproduce when the client of Lottie has a deployment target that is lower than the lowest deployment target supported by Swift concurrency.

calda commented 1 year ago

@tshortli, any clue why this is a problem in Xcode 14.3 but not a problem in Xcode 14.2? We're use the same Lottie.xcframework in both cases (which was built by Xcode 13.2.1, so it can support consumers using Xcode 13.2 / Swift 5.5). Does this imply that Xcode 14.3 no longer supports .xframeworks built by Xcode 13.2.1, or is there a configuration change we'd need to make on our end?

tshortli commented 1 year ago

No, it doesn't imply a general incompatibility. There's just a straightforward availability typechecking error in the interface of the framework. It's possible that this availability error was undiagnosed by previous compilers, but I don't think that would be the case. Regardless of the exact reason this has only been noticed now, it should be safe to just add the appropriate @available annotations; they are needed to satisfy the type checker and to ensure that clients of Lottie don't try to use those declarations when back deploying to OSes that don't support concurrency.

calda commented 1 year ago

It's possible that this availability error was undiagnosed by previous compilers

Ah ok, this makes sense to me. I understand how this could be an issue on our end that happened to not be diagnosed as an error in previous versions. Thanks for the info, I'll look in to fixing this!

IanHoar commented 1 year ago

This is in the known issues:

The Xcode “Strict Concurrency Checking” setting is not correctly passed to the compiler. If you set it to “Minimal” (the default), the compiler will still perform “Targeted” checks. (105637789)

Workaround: Add -Xfrontend -strict-concurrency=minimal to OTHER_SWIFT_FLAGS under your project’s Build Settings, or add -Xswiftc -strict-concurrency=minimal when running swift build.

calda commented 1 year ago

Sorry, @tshortli, I took a look at this and don't really understand how we would work around this issue.

For example, our .swiftinterface contains:

@objc @_inheritsConvenienceInitializers @IBDesignable @_Concurrency.MainActor(unsafe) open class LottieAnimationView : Lottie.LottieAnimationViewBase {
  @_Concurrency.MainActor(unsafe) public init(animation: Lottie.LottieAnimation?, imageProvider: Lottie.AnimationImageProvider? = nil, textProvider: Lottie.AnimationTextProvider = DefaultTextProvider(), fontProvider: Lottie.AnimationFontProvider = DefaultFontProvider(), configuration: Lottie.LottieConfiguration = .shared, logger: Lottie.LottieLogger = .shared)

This @_Concurrency.MainActor(unsafe) annotation seems to be the one causing a 'MainActor' is only available in iOS 13.0 or newer error.

In the Lottie library itself, this initializer does not use any concurrency features. It's defined like this:

public init(
    animation: LottieAnimation?,
    imageProvider: AnimationImageProvider? = nil,
    textProvider: AnimationTextProvider = DefaultTextProvider(),
    fontProvider: AnimationFontProvider = DefaultFontProvider(),
    configuration: LottieConfiguration = .shared,
    logger: LottieLogger = .shared)
{ ... }

The declaration doesn't have any @available annotations, because it doesn't need any. So it seems incorrect for Xcode to emit an error here. Is there something else I'm missing?

I assume you got here via the feedback I filed. I'm happy to create a standalone repro project if that would be helpful.

tshortli commented 1 year ago

I see. Then I guess what's changed is that some part of the compiler is inferring those @MainActor attributes based off of something about those declarations and then they are getting printed that way in the .swiftinterface. I still think you ought to be able work around the error by adding explicit availability even though the compiler doesn't think you need it when building the framework from source, but now that I understand the issue better I agree there's some behavior of the compiler that does need to change. If you're able to put together a reproducer project that produces an .xcframework with similar characteristics that would be helpful.

jshier commented 1 year ago

I believe the issue is caused by the fix in https://github.com/apple/swift/pull/60672.

In short, the compiler wasn't previously requiring APIs using @MainActor to also have proper availability markup (e.g. @available(iOS 13, *)) which is now being checked in 5.8. I don't know what would happen at runtime when calling such an API from an older OS but probably nothing good. The solution is to rebuild Lottie with the new compiler, as the current version is invalid (and likely unsafe). This can be done by either setting the deployment target to the right levels, or marking up all API using @MainActor with the proper availability.

calda commented 1 year ago

Hm, we are intentionally building Lottie's distributed xcframework with Xcode 13.2.1 so it can be used by consumers still running Swift 5.5 / Swift 5.6 (which doesn't work if we build the xcframework with Xcode 14.2). Is there another way to do this? BUILD_LIBRARY_FOR_DISTRIBUTION=YES doesn't help with that specific problem.

calda commented 1 year ago

For reference, here's a really simple sample project that demonstrates the issue:

FB11994464.zip

I created a trivial library that includes a public UIView subclass:

import UIKit

public class FB11994464_Library: UIView {
  public init() {
    super.init(frame: .zero)
  }

  public required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
}

I built an XCFramework for the library (using a shell script in the zip archive) and then used that .xcframework in a trivial app target that consumes the UIView subclass:

import UIKit
import FB11994464_Library

class ViewController: UIViewController {

  override func viewDidLoad() {
    super.viewDidLoad()

    let subview: UIView = FB11994464_Library()
    view.addSubview(subview)
  }

}

In Xcode 14.2, the app target builds as expected. In Xcode 14.3 beta, the app target fails to build and emits this 'MainActor' is only available in iOS 13.0 or newer error.

jshier commented 1 year ago

I would suppose the new compiler isn't a requirement there, you just need to rebuild in a way that adds the availability to generated interface. Marking up these APIs with availability may do what you want.

Beyond the issue I posted I don't know much more. I narrowly avoided this issue with an SDK I built where I was using @MainActor with a deployment target of iOS 12 and wondering why the compiler wasn't complaining. I got pointed to the issue I posted and manually worked around the issue by bifurcating the entry point so that newer OSes trampoline through Task to get the @MainActor for later calls. It seems that, in fixing that issue, the compiler now requires all global actors to be availability checked, even auto imported ones from Apple's frameworks.

calda commented 1 year ago

I don't think this is related to using concurrency features in my library's source code -- the sample code I shared above has this same issue when built as an XCFramework but doesn't use any concurrency features.

tshortli commented 1 year ago

I believe the issue is caused by the fix in apple/swift#60672.

Yup, Jon is right. It's been long enough that I had forgotten that global actor typechecking was missing some key checks prior to Swift 5.8. I need to confirm, but I think the fix will be to relax availability checking for MainActor(unsafe) because it has no ABI effect and therefore shouldn't be constraining availability.

tshortli commented 1 year ago

Fixing with https://github.com/apple/swift/pull/64412.

calda commented 1 year ago

Thank you @tshortli!

andre-alves commented 1 year ago

Thanks for fixing this @tshortli. Is the fix going to be included in Xcode 14.3 final release?

florentmorin commented 1 year ago

Not fixed with Xcode 14.3 RC1.

xmollv commented 1 year ago

Not fixed with Xcode 14.3 RC1.

Yeah, I was going to comment the same thing. We saw last night on Xcode Cloud how our builds started to fail due to this:

Failed to build module 'Lottie'; this SDK is not supported by the compiler (the SDK is built with 'Apple Swift version 5.5.2 (swiftlang-1300.0.47.5 clang-1300.0.29.30)', while this compiler is 'Apple Swift version 5.8 (swiftlang-5.8.0.124.1 clang-1403.0.22.11.100)'). Please select a toolchain which matches the SDK.

Are we all assuming that the final 14.3 will have this issue solved? We also faced the same issue with Giphy and they have a branch with a fix just for this, just sharing in case that it helps! https://github.com/Giphy/giphy-ios-sdk/issues/221

calda commented 1 year ago

The best workaround for now is still to use lottie-ios rather than lottie-spm. I'd prefer not to have to drop support for iOS 11 / 12, but will consider that sort of workaround if this bug isn't fixed by the time Xcode 14.3 is released.

xmollv commented 1 year ago

The best workaround for now is still to use lottie-ios rather than lottie-spm. I'd prefer not to have to drop support for iOS 11 / 12, but will consider that sort of workaround if this bug isn't fixed by the time Xcode 14.3 is released.

For now we'll keep using Xcode 14.2 since there's no rush to upgrade (and keep using lottie-spm). But yeah, if we have to end up upgrading to 14.3 and the issue is still there, we'll revert to using lottie-ios 👍🏼

jshier commented 1 year ago

The Swift 5.8 version of the fix PR just went up: https://github.com/apple/swift/pull/64538. Unfortunately Apple's Xcode release process takes long enough it seems unlikely we'll see this in Xcode 14.3 even if they accept the PR today. Perhaps 14.3.1?

IanHoar commented 1 year ago

Reverting to lottie-ios has unblocked us for now so I'll continue using that until the fix makes it into Xcode or some other change is made to this repo

calda commented 1 year ago

This issue is resolved in Xcode 14.3 RC 2: https://github.com/apple/swift/pull/64412#issuecomment-1485621729

RamblinWreck77 commented 1 year ago

@calda Just a heads up, Apple is currently rejecting builds from Xcode 14.3 RC2 as "beta" if you try and ship to the store using it. I have a build on the store from RC1 so being "RC" isn't the issue.

I've already contacted developer support.