Answering my own question.
I was only able to get a working solution by creating a C wrapper package around the system library; that C wrapper package, in turn, is then wrapped with another Swift wrapper to expose 'Swifty-style' code - I was not able to get a single package that included all the required parts.
My working solution is as follows...
Package: CGeographicLib
Folder structure for the the system library's C wrapper is:
.
├── Package.swift
├── README.md
└── Sources
├── CGeographicLib
│ ├── CGeodesic.cpp
│ └── include
│ └── CGeodesic.h
└── geographiclib
├── geographiclib.h
└── module.modulemap
Updated Package.swift
:
import PackageDescription
let package = Package(
name: "CGeographicLib",
platforms: [.macOS(.v11)],
products: [
.library(name: "CGeographicLib", targets: ["CGeographicLib"])
],
targets: [
.systemLibrary(name: "geographiclib",
pkgConfig: "geographiclib",
providers: [
.brew(["geographiclib"])
]),
.target(name: "CGeographicLib", dependencies: ["geographiclib"])
],
cxxLanguageStandard: .cxx20
)
I added platforms: [.macOS(.v11)]
as the latest version of the GeographicLib
system library only supports macOS v11 or later.
The system library that I am using has some C++11 extensions, I added the language standard .cxx20
, but this could equally be .cxx11
too and it should still work for the system library I am using.
Updated module.modulemap
:
module geographiclib [system] {
umbrella header "geographiclib.h"
link "geographiclib"
export *
}
Umbrella header, geographiclib.h
is unchanged.
For the new C wrapper elements:
CGeodesic.h
:
#ifdef __cplusplus
extern "C" {
#endif
double geoLibInverse(double lat1, double lon1, double lat2, double lon2);
#ifdef __cplusplus
}
#endif
CGeodesic.cpp
:
#include "include/CGeodesic.h"
#include "../../geographiclib/geographiclib.h"
double geoLibInverse(double lat1, double lon1, double lat2, double lon2) {
using namespace std;
using namespace GeographicLib;
Geodesic geod(Constants::WGS84_a(), Constants::WGS84_f());
double s12;
geod.Inverse(lat1, lon1, lat2, lon2, s12);
return s12;
}
Package: SwiftyGeographicLib
Folder structure for the Swift package that uses the C wrapper package is:
.
├── Package.swift
├── README.md
├── Sources
│ └── SwiftyGeographicLib
│ └── Geodesic.swift
└── Tests
└── SwiftyGeographicLibTests
└── SwiftyGeographicLibTests.swift
Package.swift
:
import PackageDescription
let package = Package(
name: "SwiftyGeographicLib",
platforms: [.macOS(.v11)],
products: [
.library(
name: "SwiftyGeographicLib",
targets: ["SwiftyGeographicLib"]),
],
dependencies: [
.package(name: "CGeographicLib",
url: "/Users/kieran/codeProjects/z.TestProjects/SPM/CGeographicLib",
branch: "master")
],
targets: [
.target(
name: "SwiftyGeographicLib",
dependencies: ["CGeographicLib"]),
.testTarget(
name: "SwiftyGeographicLibTests",
dependencies: ["SwiftyGeographicLib"]),
]
)
The package dependency in this example is pointing to a local package - I could equally have uploaded and created a version tag on GitHub.
Geodesic.swift
:
import Foundation
import CGeographicLib
public func geodesicInverse(lat1: Double, lon1: Double, lat2: Double, lon2: Double) -> Double {
return geoLibInverse(lat1, lon1, lat2, lon2)
}