Search code examples
iosswiftrealmswift-package-managerxcode13

How to add a Swift package manager as a dynamic library in xcode 13?


I am currently working in switching dependency manager of a project from Carthage to Swift Package Manager,

We have for example realm dependency that used to be a dynamic framework when building with Carthage,

But in SPM when I try to add realm it by default gives a realm static framework and I could not find a way to switch to dynamic,

Since we have some submodules in our project dependent on each other trying to link the static library gives duplicate symbols errors.

I would be much easier if I could download realm directly as dynamic framework as I can get with Carthage,

No options to choose enter image description here

enter image description here

Does anyone knows how to do that?

Thanks in advance for any help :)


Solution

  • Packages can produce dynamic libraries but they have to explicitly tell Xcode that they want the library to be made into a dynamic library. Realm does not do this. Instead, the folks at Realm go with the default behavior which lets Xcode decide which whether it will construct a static or dynamic library. As far as I know, Xcode always chooses to build a static library.

    To get around this you can create your own package that includes the Realm package as a dependency and explicitly make your library dynamic. You can find plenty of tutorials that show you how to make a package so I won't get into that here.

    If you create a package and load the following content into your Package.swift file, then import the package into your project, you will have solved your problem. I named my package "RealmUmbrella" but you can call yours whatever you like.

    import PackageDescription
    
    let package = Package(
        name: "RealmUmbrella",
        platforms: [.iOS(.v14)],
        products: [
            .library(
                name: "RealmUmbrella",
                type: .dynamic,
                targets: ["RealmUmbrella"]
            ),
        ],
        dependencies: [
            .package(name: "Realm", url: "https://github.com/realm/realm-cocoa", "10.0.0"..<"11.0.0")
        ],
        targets: [
            .target(
                name: "RealmUmbrella",
                dependencies: [.product(name: "RealmSwift", package: "Realm")]
            ),
        ]
    )
    

    Notice how I specify .dynamic here:

            .library(
                name: "RealmUmbrella",
                type: .dynamic,
                targets: ["RealmUmbrella"]
            ),
    

    Once I added my umbrella package into my project, I clicked on the project file in the project navigator, selected my target, then navigated to "General" tab and scrolled down to "Frameworks, Libraries, and Embedded Content". Then I specified, "Embed and Sign" in the "Embed" column for my package.

    enter image description here

    And that's it.