Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RevenueCat.xcframework.zip not compatible with use in SPM binaryTarget() #2163

Open
5 tasks done
scogeo opened this issue Dec 16, 2022 · 5 comments
Open
5 tasks done
Labels

Comments

@scogeo
Copy link

scogeo commented Dec 16, 2022

Describe the bug
The RevenueCat.xcframework.zip that is produced for each release is not compatible for use as a binary target in swift package manager. Using a pre-compiled xcframework can substantially cut down on build times for both development and CI environments and increase overall productivity. For example one could define a Package.swift using a binary target and provide the correct checksum for that release:

let package = Package(
/// ....
  targets: [
    /// ...
    .binaryTarget(name: "RevenueCat",
                  url: "https://github.com/RevenueCat/purchases-ios/releases/download/4.15.4/RevenueCat.xcframework.zip",
                  checksum: "<the correct checksum>),
  ],
/// ...
)

SPM requires that the zip file contain only the framework and that the framework is available at the root level of the zip file per Apple's documentation. The current xcframework zip file contains a directory at the root named "xcframeworks" and then multiple sub-directories including the RevenueCat.xcframework below it as follows:

  • (root)
    • xcframeworks
      • archives
      • RevenueCat.dSYMs
      • RevenueCat.xcframework

The directory structure, and the archives and RevenueCat.dSYMs seem to be artifacts of how the xcframework was built using fastlane and are certainly not needed in the final zip. #1118 already included the dSYMs info directly in the xcframework.

The fix is fairly straightforward which is to only include RevenueCat.xcframework directory in the final zip file so the structure would be as follows:

  • (root)
    • RevenueCat.xcframework

This would then be compatible with both SPM and Carthage. Note that I have not tested this with Carthage, but there are other projects that provide Carthage xcframework.zip files that are structured in this manner and compatible with SPM.

I already have a PR to fix the issue that I will submit shortly.

  1. Environment
    1. Platform: iOS 16.x
    2. SDK version: 4.15.4
    3. StoreKit 2 (disabled with useStoreKit2IfEnabled(false)) (Y/N): N/A
    4. OS version: MacOS 13.1 (build environment)
    5. Xcode version: 14.2
    6. How widespread is the issue. Percentage of devices affected.
  2. Debug logs that reproduce the issue
  3. Steps to reproduce, with a description of expected vs. actual behavior
  4. Other information (e.g. stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, etc.)
@scogeo scogeo added the bug label Dec 16, 2022
@RCGitBot
Copy link
Contributor

RCGitBot commented Dec 16, 2022

👀 SDKONCALL-193 We've just linked this issue to our internal tracker and notified the team. Thank you for reporting, we're checking this out!

@aboedo
Copy link
Member

aboedo commented Dec 16, 2022

@scogeo thanks for reporting!

That's valid feedback.

The xcframework was originally meant for folks using Carthage, whose build times are much slower, especially because Carthage will build every single project and target in the repo and we don't have a way to provide a specific manifest, like we do for SPM.

But I agree with you - even though SPM is faster because it can build only the specific files it needs, vending a binary alternative would make it faster.

I'm adding this to the backlog, but I don't have an ETA for it yet.

@stale
Copy link

stale bot commented Dec 23, 2022

This issue has been automatically marked as stale due to inactivity. It will be closed if no further activity occurs. Please reach out if you have additional information to help us investigate further!

@stale stale bot added the status: waiting-for-reply Issues that are waiting for a reply label Dec 23, 2022
@stale stale bot closed this as completed Dec 30, 2022
@aboedo aboedo reopened this Dec 30, 2022
@aboedo
Copy link
Member

aboedo commented Dec 30, 2022

oops, this shouldn't have been marked as stale, we still need to integrate the changes

@stale stale bot removed status: waiting-for-reply Issues that are waiting for a reply labels Dec 30, 2022
@erhardbrand
Copy link

erhardbrand commented Feb 22, 2023

An alternative approach would be to create a symbolic link to the RevenueCat.xcframework:
This would place a symlink in the root of the archive, which satisfies the SPM requirement to have the xcframework in the root, while keeping the current folder structure intact for backwards capability as used by Carthage users (xcframeworks/*).

I modified the Fastfile's export_xcframework lane to:

  1. Create a RevenueCat.xcframework symlink to xcframeworks/RevenueCat.xcframework
  2. Create the RevenueCat.xcframework.zip archive from within the build directory using ditto
  3. Dropped the --keepParent option since we are now creating the archive from within the build folder

Note: Step 2 is required because ditto doesn't support multiple source directories as input, so the archive step needed to be done from within the encapsulating directory.

The archive then contains:

Screenshot 2023-02-22 at 15 23 39

  desc "Export XCFramework"
  lane :export_xcframework do |options|
    output_directory = 'build/xcframeworks'
    platforms = [
        'iOS',
        'macOS',
        'maccatalyst',
        'tvOS',
        'watchOS'
      ]

    create_xcframework(
      destinations: platforms,
      scheme: 'RevenueCat',
      xcframework_output_directory: output_directory,
      # bitcode produces issues with Catalyst when validating builds,
      # with a message: "object not signed at all".
      enable_bitcode: false,
      include_debug_symbols: true
    )
    # sh runs from the Fastfile's location, but other commands run from the project root.
    output_directory_for_sh = "../#{output_directory}"
    xcframework_build_output_directory = "../build"
    xcframeworks_zip_path_for_sh = "../RevenueCat.xcframework.zip"

    Dir.chdir(xcframework_build_output_directory) do
      sh("ln -s xcframeworks/RevenueCat.xcframework RevenueCat.xcframework")
      sh("ditto", "-c", "-k", "--sequesterRsrc",
        ".",
        xcframeworks_zip_path_for_sh)
    end
  end

I validated this locally by updating the RevenueCat Package.swift file to use a binaryTarget and pointed the url to the newly built RevenueCat.xcframework.zip:

targets: [
// ...
        .binaryTarget(name: "RevenueCat",
                url: "https://local-url/RevenueCat.xcframework.zip",
                checksum: "checksum"),
    ]

Xcode imported the RevenueCat SDK successfully:

rc-import

Xcode's SourcePackages directory also shows that the SPM artifact now has the RevenueCat.xcframework symlink at its root:

Screenshot 2023-02-22 at 15 32 48

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
4 participants