How do I add a Swift package dependency for a dynamic library?

Viewed 919

I am trying to migrate an iOS app to use Swift package manager, converting frameworks to packages. For most of my code, this has not been pretty straightforward, and I have a growing number of modules & packages that work fine.

The problem is with a module that depends on third-party libraries. One library, "libA", is only available as a binary libA.a with C headers, and I have created an xcframework that I import into a module "MyLibA" via the Package.swift file, using a binaryTarget. The library is first converted to an xcframework as follows:

    lipo -extract arm64 -output libA_arm_ios/libA.a libA/bin/libA.a
    lipo -extract x86_64 -output libA_x86_ios/libA.a libA/bin/libA.a

    xcodebuild -create-xcframework -libA.a libA_arm_ios/libA.a -library \
        libA_x86_ios/libA.a -headers libA/headers -output libA.xcframework

and then included in the swift package as follows:

    import PackageDescription
    
    let package = Package(
        name: "MyLibA",
        products: [
            .library(
                name: "MyLibA",
                targets: ["MyLibA"]),
        ],
        dependencies: [
        ],
        targets: [
            .target(
                name: "MyLibA",
                dependencies: ["libA"]),
            .binaryTarget(name: "libA", path: "build/libA.xcframework"),
            .testTarget(
                name: "MyLibATests",
                dependencies: ["MyLibA"]),
        ]
    )

libA, however, depends in turn on zlib, which is available as libz.tbd on the Mac. So when I add the MyLibA dependency and try to run MyLibATests, I get the linker error

Undefined symbols for architecture arm64:
  "_zlibVersion", referenced from:
      _libA_method in libA.a(libA_la-version.o)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

So the question is, how do I handle the zlib dependency within this package? Do I need to find/create a suitable .a and then wrap it in an xcframework as I did for libA? Is there a simpler solution?

1 Answers

Wow. So simple. I had been going down a wrong path based on reading about having to wrap system libraries, etc., as I've been learning about the Swift Package Manager.

zlib is a system library, so all I needed to do was add

   .linkedLibrary("z")

under linkerSettings: for the target:

    targets: [
        .target(
            name: "MyLibA",
            dependencies: ["libA"],
            linkerSettings: [
                .linkedLibrary("z")
            ])
        )
     ]

:facepalm:

Related