Swift Package Manager Dynamic Library

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

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.

Sample Image

And that's it.

Swift Package Manager link shared archive library on MacOS

I believe I have figured it out, and the solution is as follows.

In Package.swift, add this snippet in the beginning:

var linkerSettings: [PackageDescription.LinkerSetting] = [.linkedLibrary("/path/to/libfoo.a")]
#if os(macOS)
linkerSettings = [
.unsafeFlags(["-L/path/to/"]),
.linkedLibrary("foo")
]
#endif

And then, where it used to say

linkerSettings: [
.linkedLibrary("/path/to/libfoo.a")
]

replace that code with

linkerSettings: linkerSettings

instead.

Swift Package Manager: How to add local shared library as dependency to multiple executables?

This should do it. You don't need to add a "dependency" to a target where all the sources are on your local computer.

// swift-tools-version:5.3

import PackageDescription

let package = Package(
name: "dmx-db",
products: [
.executable(name: "DmxServer", targets: ["DmxServer"]),
.executable(name: "DmxClient", targets: ["DmxClient"]),
// This lib will be imported into both, client and server.
.library(name: "DmxLib", targets: ["DmxLib"]),
],
dependencies: [
.package(url: "https://github.com/grpc/grpc-swift.git", from: "1.0.0-alpha.21"),
.package(url: "https://github.com/codewinsdotcom/PostgresClientKit", from: "1.0.0"),
.package(url: "https://github.com/swift-server/swift-service-lifecycle.git", from: "1.0.0-alpha.5"),
],
targets: [
.target(name: "DmxServer", dependencies: [
"DmxLib",
.product(name: "GRPC", package: "grpc-swift"),
.product(name: "PostgresClientKit", package: "PostgresClientKit"),
.product(name: "Lifecycle", package: "swift-service-lifecycle"),
]),
.target(name: "DmxClient", dependencies: [
"DmxLib",
.product(name: "GRPC", package: "grpc-swift"),
]),
.target(name: "DmxLib", dependencies: []),
]
)

This does require that you have a Sources directory in the root directory of your package, and inside it you have three folders, named DmxLib, DmxClient, and DmxServer, respectively.

Note: I've actually updated the swift-tools-version to 5.3, because I copied and modified this from one of my projects, but I think it should work with a swift-tools-version of 5.2

Swift Package Manifest - What is the difference between library targets and target dependencies?

From the Swift Package Manager Documentation

A target may build either a library or an executable as its product.
A library contains a module that can be imported by other Swift code.
...

A library is something that can be imported by other swift code.

The dependencies that your library relies on are defined in the

.target(name: "MyTestPackage", dependencies: ["Helper"])

The targets could be thought of as the modules, organized in folders.

When you define the MyTestPackage, you declare its dependencies Helper in the targets array of the package. If you didn't declare it there, code in MyTestPackage won't be able to import Helpers.

In the first example, the library MyTestPackage's target includes helpers as a dependency of MyTestPackage, so you could delete the Helper library and should still be able to import both MyTestPackage and Helper in your project.

In the second example, you declare both MyTestPackage and Helpers as targets that make up the MyTestPackage library, so again you should be able to delete the Helper library and still import code from both modules.

If you were to delete both libraries from either example, you would not be able to import any code into your project



Related Topics



Leave a reply



Submit