appcenter-sdk-apple icon indicating copy to clipboard operation
appcenter-sdk-apple copied to clipboard

Distribute as binary Swift package

Open apps4everyone opened this issue 3 years ago • 13 comments

Hey, would like not to compile the SDK every time. maybe it is possible to release also as binary frameworks as Swift package to make it possible to consume like this: (maybe the binaryTarget zip/XCFrameworks has to be split in AppCenter, AppCenterAnalytics, AppCenterCrashes and AppCenterDistribute)

// swift-tools-version:5.3

import PackageDescription

let package = Package(
    name: "AppCenter",
    products: [
        .library(name: "AppCenter", targets: ["AppCenter"]),
        .library(name: "AppCenterAnalytics", targets: ["AppCenterAnalytics"]),
        .library(name: "AppCenterCrashes", targets: ["AppCenterCrashes"]),
        .library(name: "AppCenterDistribute", targets: ["AppCenterDistribute"])
    ],
    dependencies: [
    ],
    targets: [
        .binaryTarget(
            name: "AppCenter",
            url: "https://github.com/microsoft/appcenter-sdk-apple/releases/download/4.1.1/AppCenter-SDK-Apple-XCFramework-4.1.1.zip",
            checksum: "some-checksum"
        )
    ]
)

Infos here: https://www.wwdcnotes.com/notes/wwdc20/10147/

apps4everyone avatar May 02 '21 10:05 apps4everyone

Hi @apps4everyone

Sorry for the delay and thank you for bringing it to our attention.

I created a work item for this feature request.

DmitriyKirakosyan avatar May 06 '21 07:05 DmitriyKirakosyan

thx @DmitriyKirakosyan, can I somehow see the progress (ticket)? Also for https://github.com/microsoft/appcenter-sdk-apple/issues/2298 ?

apps4everyone avatar May 06 '21 08:05 apps4everyone

We will keep you updated in your github issues if anything new is merged or released.

DmitriyKirakosyan avatar May 06 '21 08:05 DmitriyKirakosyan

@DmitriyKirakosyan @aleksandr-dorofeev @AnastasiaKubova

This feature would be very useful, because compiling the entire swift package takes up a lot of time (both locally and on CI)

Any updates on this?

arielelkin avatar Nov 02 '21 10:11 arielelkin

Hi @arielelkin , I agree it would be better to distribute xcframework via SPM as we do with Cocoapods, however there is an issue with SPM which I was not able to fix. It doesn't properly link translation resources for Distribute module. Here is my attempt to distribute binary via SPM: https://github.com/DmitriyKirakosyan/mobile-center-sdk-ios/blob/spm-xcframework/Package.swift. This approach works well except the problem that all strings in alerts from Distribute are not localized.

If you have an idea how to fix this issue, please let me know.

We have this feature on our board, but due to other priorities we didn't dive deep into it yet.

DmitriyKirakosyan avatar Nov 02 '21 11:11 DmitriyKirakosyan

@DmitriyKirakosyan I've taken a look at your branch.

You're defining Resources/AppCenterDistribute.strings as a resource for the AppCenterDistributeResources target: https://github.com/DmitriyKirakosyan/mobile-center-sdk-ios/blob/spm-xcframework/Package.swift#L57

But this file doesn't exist in /AppCenterDistribute/AppCenterDistribute/Resources/

Are you trying to set the entire contents of /AppCenterDistribute/AppCenterDistribute/Resources/ as resources or a specific file? If it's the former, you could try with

            resources: [
                .process("Resources"),
            ]

arielelkin avatar Nov 08 '21 11:11 arielelkin

thx @DmitriyKirakosyan for working on this, @arielelkin keep in mind the url's and checksum's should be updated before merging and on new release. Maybe there is a way to generate those values...

apps4everyone avatar Nov 08 '21 13:11 apps4everyone

Thanks @arielelkin , that makes sense. I'll check it again with your suggestion.

DmitriyKirakosyan avatar Nov 08 '21 23:11 DmitriyKirakosyan

Hi @arielelkin , I experimented with it but was not able to make it work. I tried what you suggested, also tried the approach firebase sdk uses, like adding two (.m and .h) empty source files in Res dir, but this also didn't work in combination with an binary target. I'm out of ideas at this moment, may be SPM doesn't support distributing binary target with resources at this moment. If anyone interested, you can try to experiment with it too.

DmitriyKirakosyan avatar Nov 11 '21 07:11 DmitriyKirakosyan

may be SPM doesn't support distributing binary target with resources at this moment

Binary targets are just XCFrameworks on Apple's platforms. They do support resources.

tonyarnold avatar Feb 01 '22 05:02 tonyarnold

🤔 I don‘t think SPM itself supports building XCFramework at present, but it should be achieved by creating and configuring new targets in the wrapper Xcode Project. Like what Realm did.

Additional work may be needed: the first is about resources, which should not be located through Bundle.module when building XCFramework. The second is that we may need multiple XCFramework, because it seems that there can only be one Swift module in each Framework.

gongzhang avatar Feb 01 '22 16:02 gongzhang

Hi there! Yes, you are right! We spent some time investigating this issue and we didn't find a quick and easy way to implement it in App Center SDK. Unfortunately, we don't have ETA for this feature at this moment, but we are keeping an eye on this thread (see more info in our Roadmap). Feel free to open contribution PR if you have any solution for this issue.

AnastasiaKubova avatar Feb 02 '22 06:02 AnastasiaKubova

I looked into this a bit. It's pretty doable for the current state, and given that SPM only supports Analytics and Crashes right now in general and there are already binaries for it, it's not too complicated. The main difference would be that instead of including one zip with all of the frameworks, you would need a separate zip uploaded for each xcframework.

The bigger challenge as noted is the resources. Looking at the Distribute issue, I see two paths forward:

  • There's a way to make a dummy target that includes the Resources bundle, then you have an overall product that includes the target for the binaryTarget xcframework and the dummy target with the resources (I believe Firebase does something similar)
  • Not bundle the resources in general. Given that it is one specific string, the resources aren't super useful and the SDK gives good extension points for providing custom text

thedavidharris avatar Aug 28 '22 17:08 thedavidharris

Example of how Google Maps does this with a dummy target: https://github.com/googlemaps/ios-maps-sdk/blob/main/Package.swift#L39.

thedavidharris avatar Jan 02 '24 17:01 thedavidharris

I think the changes to Packages.swift only is not enough as, as far as I understand, AppCenter has to be built differently for it to get the correct module bundle https://github.com/microsoft/appcenter-sdk-apple/blob/4bc5282dfc6c273a993e67d8f8c61d8014d257e0/AppCenterDistribute/AppCenterDistribute/MSACDistributeUtil.m#L21

EDIT: Or we need a way to define a list of bundles to search for, as for me, the result for APP_CENTER_DISTRIBUTE_BUNDLE_NAME is different in my swift package image

ilendemli avatar Jan 04 '24 17:01 ilendemli

Made some progress regarding this, creating a pull request soon: https://github.com/ilendemli/appcenter-sdk-apple/tree/spm-fixes

Here is a package to try it out, https://github.com/ilendemli/appcenter-sdk-apple-spm

you will need to add following to your main app

if let bundleURL = Bundle.main.url(forResource: "AppCenter_AppCenterDistributeTarget", withExtension: "bundle") {
    Distribute.resourceBundle = Bundle(url: bundleURL)
}

ilendemli avatar Jan 08 '24 10:01 ilendemli

As there is a workaround and we do not plan to add support in the next year, I'm closing the issue.

lucen-ms avatar Feb 07 '24 10:02 lucen-ms

Hey guys I am using Kotlin Multiplatform which outputs xcframeworks both debug and release, and wanted to distribute it with SPM package. I used AWS Code artifacts to publish the package.

// swift-tools-version: 5.9

import PackageDescription

let packageName = "SomeArtifactPackage"

let package = Package(
    name: packageName,
    platforms: [
        .iOS(.v13), // Adjust based on minimum supported iOS version
        .macOS(.v10_15), // Add other platforms if needed
        // ...
    ],
    products: [
        // Products define the executables and libraries a package produces, making them visible to other packages.
        .library(
            name: packageName,
            targets: [packageName]),
    ],
    targets: [
        // Targets are the basic building blocks of a package, defining a module or a test suite.
        // Targets can depend on other targets in this package and products from dependencies.
        .binaryTarget(
            name: packageName,
            url: URL(string: "https://us-west-2.artifacts.aws.amazonaws.com/<repo>/path.zip")!,
            checksum: "checksum-of-your-package.zip" // Replace with actual checksum
        ),
    ]
)

Now I am confused with

  • targets should it be .binary or .binaryTarget
  • how will the versioning work? should I hard code the version everytime since url will have version i guess, not sure either
  • my code artifacts are private repo how to handle that

Any help will be appreciated

  • Docs link
  • community anyone who have tried it with aws code artifacts

Thankyou in advance

tushar1998 avatar Apr 10 '24 06:04 tushar1998