swiftlang / swift-package-manager

The Package Manager for the Swift Programming Language
Apache License 2.0
9.7k stars 1.33k forks source link

Package containing single binary target can't be embedded into an app via Xcode, causes app to crash #6069

Open calda opened 1 year ago

calda commented 1 year ago

Description

We have a lottie-spm package that wraps the lottie-ios repo by providing a product that just contains a binary target:

// lottie-spm 4.0.1 Package.swift 
let package = Package(
  name: "Lottie",
  platforms: [.iOS("11.0"), .macOS("10.10"), .tvOS("11.0")],
  products: [.library(name: "Lottie", targets: ["Lottie"])],
  targets: [
    .binaryTarget(
      name: "Lottie",
      url: "https://github.com/airbnb/lottie-ios/releases/download/4.0.1/Lottie.xcframework.zip",
      checksum: "b6d8b0b81975d91965b8bb00cffb0eae4b3d94538b6950a90bc1366afd5d4239"),
  ])

I'm able to depend on this package from test targets and iOS app simulator builds without any issues, but Xcode doesn't let you embed the framework into an app product. This causes an app to crash when ran on a physical device. You can reproduce this by building the Example iOS app in lottie-spm 4.0.1 and then running it on a physical iOS device (it crashes).

We were able to work around this issue by adding an additional stub / empty target to the package:

let package = Package(
  name: "Lottie",
  platforms: [.iOS("11.0"), .macOS("10.10"), .tvOS("11.0")],
  products: [.library(name: "Lottie", targets: ["Lottie", "_LottieStub"])],
  targets: [
    .binaryTarget(
      name: "Lottie",
      url: "https://github.com/airbnb/lottie-ios/releases/download/4.1.0/Lottie.xcframework.zip",
      checksum: "e954f5bfc5049196593c59c6eb21321016ffaba4417e9b4ece2a6a9eb54baa9a"),

    // Without at least one regular (non-binary) target, this package doesn't show up
    // in Xcode under "Frameworks, Libraries, and Embedded Content". That prevents
    // Lottie from being embedded in the app product, causing the app to crash when
    // ran on a physical device. As a workaround, we can include a stub target
    // with at least one source file.
    .target(name: "_LottieStub"),
  ])

I expect both package definitions to work correctly here.

Not sure if this is an issue with SPM or Xcode. Let me know if you'd prefer me to file a feedback on Xcode instead.

Expected behavior

A package with a single binary target should be able to be embedded into an iOS app via Xcode

213725218-7bd5e75c-f418-44bd-a53f-dc11d9592474

Actual behavior

A package with a single binary target cannot be embedded into an iOS app via Xcode, and causes the app to crash when ran on a physical iOS device

213724871-8655094c-68d9-4c7d-bfd8-8c24a062cb42

Steps to reproduce

Build the Example iOS app in lottie-spm 4.0.1 and then run it on a physical iOS device (it crashes).

Swift Package Manager version/commit hash

No response

Swift & OS version (output of swift --version && uname -a)

Swift 5.7

neonichu commented 1 year ago

cc @abertelrud

mparmar-covantex commented 1 year ago

Refer this, Might helpful to team.

calda commented 1 year ago

Thanks for the suggestion. When I try that I get the following package validation error:

invalid type for binary product 'Lottie'; products referencing only 
binary targets must have a type of 'library'

If I remove type: .dynamic below then the error goes away, so it sounds like this configuration isn't supported in this case. Not sure if that's intentional or not -- the wording in the error is a little confusing.

// Package.swift
let package = Package(
  name: "Lottie",
  platforms: [.iOS("11.0"), .macOS("10.10"), .tvOS("11.0")],
  products: [
    .library(
      name: "Lottie",
      type: .dynamic,
      targets: ["Lottie"])
  ],
  targets: [
    .binaryTarget(
      name: "Lottie",
      url: "https://github.com/airbnb/lottie-ios/releases/download/4.1.2/Lottie.xcframework.zip",
      checksum: "3fc1e8054e3749caee0ae189770b6793a6ab3292b4d9d8fd1b8762265339c14b"),
  ])
tomerd commented 1 year ago

cc @neonichu

Cyberbeni commented 1 year ago

We have a workspace, 1 project that contains the app, several other projects that are used by the app. One of those other projects has an SPM dependency which uses the lottie-spm 4.2.0 package. We noticed the same crash as described in this issue (crash on device only with dyld file not found error). We added the lottie-spm package as a dependency to the app project and it seems to have fixed the issue.

Edit: If we added the same package that depends on lottie-spm to the app project, that also crashed on device.

neonichu commented 1 year ago

invalid type for binary product 'Lottie'; products referencing only binary targets must have a type of 'library'

Seems like the diagnostic has regressed here, I believe it was supposed to say "type automatic" or something similar

neonichu commented 1 year ago

Might be the other way around, the current diagnostic looks good. See https://github.com/apple/swift-package-manager/blob/main/Sources/PackageLoading/ManifestLoader%2BValidation.swift#L268

Semty commented 12 months ago

We have a workspace, 1 project that contains the app, several other projects that are used by the app. One of those other projects has an SPM dependency which uses the lottie-spm 4.2.0 package. We noticed the same crash as described in this issue (crash on device only with dyld file not found error). We added the lottie-spm package as a dependency to the app project and it seems to have fixed the issue.

Edit: If we added the same package that depends on lottie-spm to the app project, that also crashed on device.

The same happens with our project as well

calda commented 9 months ago

Here's a similar bug report from @Semty (with a sample project) which demonstrates this issue: https://github.com/airbnb/lottie-ios/issues/2233

We have a workspace, 1 project that contains the app, several other projects that are used by the app. One of those other projects has an SPM dependency which uses the lottie-spm 4.2.0 package. We noticed the same crash as described in this issue

There are a few manual workarounds, including adding a custom shell script step that manually copies the Lottie.framework into the application Frameworks directory, but ideally this would work automatically since the lottie-spm SPM package has a dependency on this binary.