Get Url to a Local File with Spm (Swift Package Manager)

How to import local xml file in my Swift program using SPM?

From Swift 5.3, it is possible to add resources using Package.swift, which has been done in the code.

To call the added resources, it is required to use:

Bundle.module.url(forResource: myFile, withExtension: myExtension)

However, this is not possible in the extension made previously, where it was self.url.
Thus, I deleted the extension and changed the function loadPN(filePath: String) into:

  func loadPN(filePath: String) {
if let url = Bundle.module.url(forResource: filePath, withExtension: nil) {
let parser = XMLParser(contentsOf: url)!
parser.delegate = self
parser.parse()
}
}

testDoesNotWork test finally passed.

Can I make a local module with the Swift Package manager?

You can reference a local directory in your Package.swift file, but it must be a Git repository. Also, initializing the repo, committing, and tagging is not sufficient; the repository must be pushed to a remote for swift build to function correctly.

According to the SwiftPM Usage Guide:

Packages are Git repositories, tagged with semantic versions, containing a Package.swift file at their root. Initializing the package created a Package.swift file, but to make it a usable package we need to initialize a Git repository with at least one version tag.

The Swift Package Manager Documentation also states that "you can specify a URL (or local path) to any valid Swift package" and provides an example Package.swift with a local file reference: .Package(url: "../StringExtensions", "1.0.0").

Note: I edited the answer to clarify that Swift Package Manager can reference a local path, but the path must contain a valid Git repository with a tag. My original test project pointed to a dependent local path that contained a .git directory, and so it successfully built with swift build.

Swift Package Manager Dependency Mirroring

Having an Xcode project makes this task basically impossible (at the time of writing). Xcode's integration with SPM works fine for most things, but is not (yet?) at par with what SPM can do in pure SPM packages.

The problem is, that swift package config is always only local to the package and does not have any effect on projects / packages that depend on the package. And with Xcode currently having no counterpart to swift package config, it's not possible to do this at the moment.

What you could do, however, is to clone all your dependencies locally and then reference them as local packages from Xcode (simply dragging the package folder into the open Xcode project will do so). Xcode will be smart enough to take the dependencies from the local local checkout (or at least it was smart enough last time I tried this).

Let's hope for a future Xcode version with full SPM support!

Adding Local dependencies in XCode11 using SPM

This is the way I did it :

  • Drag and drop your package folder (in my example "DataStructures") from the finder directly into the Frameworks group of your target. You will see that the dropped item take a brown folder color (you can use the arrow to "get into it").
  • Go to your project target page, in the "Framework and Libraries" click the "+" button. Your package should show up in the "Workspace" area as a library.

Sample Image

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

Cleanly handling /usr/local/ with Swift package manager and libevent

What you've found out, and documented in your answer, is a good start but not the full story. Yes, SwiftPM uses pkg-config to determine where certain libraries are installed. Yes, SwiftPM uses the pkgConfig name which it'll pass on to pkg-config. However the search paths are a bit more involved. On macOS it uses the following list as a base search path:

  • /usr/local/lib/pkgconfig
  • /usr/local/share/pkgconfig
  • /usr/lib/pkgconfig
  • /usr/share/pkgconfig
  • PKG_CONFIG_PATH environment variable

However SwiftPM doesn't use the pkg-config command, but instead parses .pc files directly. By setting the pkgConfig parameter on your package, it knows what filename to look for in the paths listed above. And, for the example in your answer, the story stops here. If there's a libevent.pc file found it parses that file, and any flags returned are passed on to the compiler and linker.

However if you were to define package providers, e.g.:

providers: [
.Brew("libsodium"),
.Apt("libsodium-dev")
]

Then SwiftPM adds additional search paths depending on the package provider for the platform it is building for. Continuing the example of macOS, SwiftPM will run brew --prefix. If this returns a path, the following path is added as a additional search path:

  • [brewPrefix]/opt/[packageName]/lib/pkgconfig

In my example of libsodium, SwiftPM is now able to infer the location of the library without requiring brew link or symlinks at all. In my verbose build output it lists the libsodium library path in my cellar: -L/usr/local/Cellar/libsodium/1.0.11/lib.

How do I use a local SPM package without a git repository?

Note that even for a local directory you have to create a git repository (local). Just run git init in the local directory, git commit and add a tag, e.g. git tag 1.0.0.



Related Topics



Leave a reply



Submit